1 | var util = require('util'); |
||
2 | var assert = require('assert'); |
||
3 | var CryptoJS = require('crypto-js'); |
||
4 | var bip39 = require('bip39'); |
||
5 | |||
6 | var blocktrail = { |
||
7 | COIN: 100000000, |
||
8 | PRECISION: 8, |
||
9 | DUST: 2730, |
||
10 | BASE_FEE: 10000, |
||
11 | LOCK_TIME_TIMESTAMP_THRESHOLD: 5000000 |
||
12 | }; |
||
13 | |||
14 | var convert = function(s, from, to) { |
||
15 | return (new Buffer(s, from)).toString(to); |
||
16 | }; |
||
17 | |||
18 | var aesDecryptMnemonic = function(mnemonic, passphrase) { |
||
19 | var hex = bip39.mnemonicToEntropy(mnemonic); |
||
20 | var base64 = convert(hex, 'hex', 'base64'); |
||
21 | var decrypted = CryptoJS.AES.decrypt(base64, passphrase).toString(CryptoJS.enc.Utf8); |
||
22 | |||
23 | if (!decrypted.length) { |
||
24 | throw new blocktrail.WalletDecryptError(); |
||
25 | } |
||
26 | |||
27 | return decrypted; |
||
28 | }; |
||
29 | |||
30 | var aesDecryptMnemonicToSeed = function(mnemonic, passphrase) { |
||
31 | return aesDecryptMnemonic(mnemonic, passphrase).toString(CryptoJS.enc.Utf8); |
||
32 | }; |
||
33 | |||
34 | var aesDecryptMnemonicToSeedHex = function(mnemonic, passphrase) { |
||
35 | return convert(aesDecryptMnemonicToSeed(mnemonic, passphrase), 'base64', 'hex'); |
||
36 | }; |
||
37 | |||
38 | var aesDecryptMnemonicToSeedBuffer = function(mnemonic, passphrase) { |
||
39 | return new Buffer(aesDecryptMnemonicToSeedHex(mnemonic, passphrase), 'hex'); |
||
40 | }; |
||
41 | |||
42 | var aesEncryptSeedToMnemonic = function(seed, passphrase) { |
||
43 | var base64 = CryptoJS.AES.encrypt(seed, passphrase).toString(CryptoJS.format.OpenSSL); |
||
44 | var hex = convert(base64, 'base64', 'hex'); |
||
45 | var mnemonic = bip39.entropyToMnemonic(hex); |
||
46 | |||
47 | return mnemonic; |
||
48 | }; |
||
49 | |||
50 | var aesEncryptSeedHexToMnemonic = function(seedHex, passphrase) { |
||
51 | return aesEncryptSeedToMnemonic(convert(seedHex, 'hex', 'base64'), passphrase); |
||
52 | }; |
||
53 | |||
54 | var aesEncryptSeedBufferToMnemonic = function(seedBuffer, passphrase) { |
||
55 | return aesEncryptSeedToMnemonic(seedBuffer.toString('base64'), passphrase); |
||
56 | }; |
||
57 | |||
58 | blocktrail.convert = convert; |
||
59 | blocktrail.aesDecryptMnemonicToSeed = aesDecryptMnemonicToSeed; |
||
60 | blocktrail.aesDecryptMnemonicToSeedBuffer = aesDecryptMnemonicToSeedBuffer; |
||
61 | blocktrail.aesDecryptMnemonicToSeedHex = aesDecryptMnemonicToSeedHex; |
||
62 | blocktrail.aesEncryptSeedToMnemonic = aesEncryptSeedToMnemonic; |
||
63 | blocktrail.aesEncryptSeedHexToMnemonic = aesEncryptSeedHexToMnemonic; |
||
64 | blocktrail.aesEncryptSeedBufferToMnemonic = aesEncryptSeedBufferToMnemonic; |
||
65 | |||
66 | blocktrail.V3Crypt = { |
||
67 | KeyDerivation: require('./keyderivation'), |
||
68 | Encryption: require('./encryption'), |
||
69 | EncryptionMnemonic: require('./encryption_mnemonic') |
||
70 | }; |
||
71 | |||
72 | /** |
||
73 | * convert a BTC value to Satoshi |
||
74 | * |
||
75 | * @param btc float BTC value |
||
76 | * @returns int Satoshi value (int) |
||
77 | */ |
||
78 | blocktrail.toSatoshi = function(btc) { |
||
79 | return parseInt((btc * blocktrail.COIN).toFixed(0), 10); |
||
80 | }; |
||
81 | |||
82 | /** |
||
83 | * convert a Satoshi value to BTC |
||
84 | * |
||
85 | * @param satoshi int Satoshi value |
||
86 | * @returns {string} BTC value (float) |
||
87 | */ |
||
88 | blocktrail.toBTC = function(satoshi) { |
||
89 | return (satoshi / blocktrail.COIN).toFixed(blocktrail.PRECISION); |
||
90 | }; |
||
91 | |||
92 | /** |
||
93 | * patch the Q module to add spreadNodeify method to promises |
||
94 | * so that we can support multi parameter callbacks |
||
95 | * |
||
96 | * @param q |
||
97 | */ |
||
98 | blocktrail.patchQ = function(q) { |
||
99 | /* jshint -W003 */ |
||
100 | |||
101 | if (q.spreadNodeify && q.spreadDone) { |
||
102 | return; |
||
103 | } |
||
104 | |||
105 | q.spreadDone = spreadDone; |
||
106 | function spreadDone(value, fulfilled, rejected) { |
||
107 | return q(value).spreadDone(fulfilled, rejected); |
||
108 | } |
||
109 | |||
110 | q.makePromise.prototype.spreadDone = function(fulfilled, rejected) { |
||
111 | return this.all().done(function(array) { |
||
112 | return fulfilled.apply(void 0, array); |
||
113 | }, rejected); |
||
114 | }; |
||
115 | |||
116 | q.spreadNodeify = spreadNodeify; |
||
117 | function spreadNodeify(object, nodeback) { |
||
118 | return q(object).spreadNodeify(nodeback); |
||
119 | } |
||
120 | |||
121 | q.makePromise.prototype.spreadNodeify = function(nodeback) { |
||
122 | if (nodeback) { |
||
123 | this.then(function(value) { |
||
124 | q.nextTick(function() { |
||
125 | nodeback.apply(void 0, [null].concat(value)); |
||
126 | }); |
||
127 | }, function(error) { |
||
128 | q.nextTick(function() { |
||
129 | nodeback(error); |
||
130 | }); |
||
131 | }); |
||
132 | } else { |
||
133 | return this; |
||
134 | } |
||
135 | }; |
||
136 | }; |
||
137 | |||
138 | |||
139 | /** |
||
140 | * Add extend() method to Error type |
||
141 | * |
||
142 | * @param subTypeName |
||
143 | * @param errorCode [optional] |
||
144 | * @returns {SubType} |
||
145 | */ |
||
146 | Error.extend = function(subTypeName, errorCode /*optional*/) { |
||
147 | assert(subTypeName, 'subTypeName is required'); |
||
148 | //define new error type |
||
149 | var SubType = function(message) { |
||
150 | |||
151 | //handle constructor call without 'new' |
||
152 | if (!(this instanceof SubType)) { |
||
153 | return new SubType(message); |
||
154 | } |
||
155 | |||
156 | //populate error details |
||
157 | this.name = subTypeName; |
||
158 | this.code = errorCode; |
||
159 | this.message = message ? (message.message || message || '') : ''; |
||
160 | |||
161 | //include stack trace in error object (only supported in v8 browsers) |
||
162 | if (Error.captureStackTrace) { |
||
0 ignored issues
–
show
|
|||
163 | Error.captureStackTrace(this, this.constructor); |
||
164 | } |
||
165 | }; |
||
166 | |||
167 | //inherit the base prototype chain |
||
168 | util.inherits(SubType, this); |
||
169 | |||
170 | //override the toString method to error type name and inspected message (to expand objects) |
||
171 | SubType.prototype.toString = function() { |
||
172 | return this.name + ': ' + util.inspect(this.message); |
||
173 | }; |
||
174 | |||
175 | //attach extend() to the SubType to make it extendable further |
||
176 | SubType.extend = this.extend; |
||
177 | return SubType; |
||
178 | }; |
||
179 | |||
180 | if (typeof Uint8Array.prototype.reverse !== 'function') { |
||
181 | Buffer.prototype.reverse = function reverse() { |
||
182 | var c; |
||
183 | for (var i = 0, j = this.length - 1; i <= j; ++i, --j) { |
||
184 | c = this[i]; |
||
185 | this[i] = this[j]; |
||
186 | this[j] = c; |
||
187 | } |
||
188 | |||
189 | return this; |
||
190 | }; |
||
191 | } |
||
192 | |||
193 | //Wallet Errors |
||
194 | blocktrail.WalletInitError = Error.extend("WalletInitError", 400); |
||
195 | blocktrail.WalletCreateError = Error.extend("WalletCreateError", 400); |
||
196 | blocktrail.WalletUpgradeError = Error.extend("WalletUpgradeError", 400); |
||
197 | blocktrail.WalletChecksumError = Error.extend("WalletChecksumError", 400); |
||
198 | blocktrail.WalletDeleteError = Error.extend("WalletDeleteError", 400); |
||
199 | blocktrail.WalletDecryptError = Error.extend("WalletDecryptError", 400); |
||
200 | blocktrail.WalletAddressError = Error.extend("WalletAddressError", 500); |
||
201 | blocktrail.WalletSendError = Error.extend("WalletSendError", 400); |
||
202 | blocktrail.WalletLockedError = Error.extend("WalletLockedError", 500); |
||
203 | blocktrail.WalletFeeError = Error.extend("WalletFeeError", 500); |
||
204 | blocktrail.WalletInvalid2FAError = Error.extend("WalletInvalid2FAError", 401); |
||
205 | blocktrail.WalletMissing2FAError = Error.extend("WalletMissing2FAError", 401); |
||
206 | blocktrail.TransactionSignError = Error.extend("TransactionSignError", 500); |
||
207 | blocktrail.TransactionInputError = Error.extend("TransactionInputError", 400); |
||
208 | blocktrail.TransactionOutputError = Error.extend("TransactionOutputError", 400); |
||
209 | |||
210 | blocktrail.KeyPathError = Error.extend("KeyPathError", 400); |
||
211 | |||
212 | blocktrail.InvalidAddressError = Error.extend("InvalidAddressError", 400); |
||
213 | |||
214 | //Other Errors |
||
215 | blocktrail.Error = Error.extend("Error", 500); |
||
216 | |||
217 | blocktrail.FEE_STRATEGY_FORCE_FEE = 'force_fee'; |
||
218 | blocktrail.FEE_STRATEGY_BASE_FEE = 'base_fee'; |
||
219 | blocktrail.FEE_STRATEGY_HIGH_PRIORITY = 'high_priority'; |
||
220 | blocktrail.FEE_STRATEGY_OPTIMAL = 'optimal'; |
||
221 | blocktrail.FEE_STRATEGY_LOW_PRIORITY = 'low_priority'; |
||
222 | blocktrail.FEE_STRATEGY_MIN_RELAY_FEE = 'min_relay_fee'; |
||
223 | |||
224 | // apply patch to Q to add spreadNodeify for all dependants of this module |
||
225 | blocktrail.patchQ(require('q')); |
||
226 | |||
227 | module.exports = blocktrail; |
||
228 |
This check looks for functions where a
return
statement is found in some execution paths, but not in all.Consider this little piece of code
The function
isBig
will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly returnundefined
.This behaviour may not be what you had intended. In any case, you can add a
return undefined
to the other execution path to make the return value explicit.