@com-chain/jsc3l 2.0.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +45 -0
  3. package/build/bcRead.d.ts +15 -0
  4. package/build/bcRead.js +123 -0
  5. package/build/bcRead.js.map +1 -0
  6. package/build/bcTransaction.d.ts +10 -0
  7. package/build/bcTransaction.js +135 -0
  8. package/build/bcTransaction.js.map +1 -0
  9. package/build/blockies.d.ts +1 -0
  10. package/build/blockies.js +91 -0
  11. package/build/blockies.js.map +1 -0
  12. package/build/config.d.ts +6 -0
  13. package/build/config.js +25 -0
  14. package/build/config.js.map +1 -0
  15. package/build/connection.d.ts +58 -0
  16. package/build/connection.js +204 -0
  17. package/build/connection.js.map +1 -0
  18. package/build/customization.d.ts +37 -0
  19. package/build/customization.js +129 -0
  20. package/build/customization.js.map +1 -0
  21. package/build/ethereum/cipher.d.ts +3 -0
  22. package/build/ethereum/cipher.js +94 -0
  23. package/build/ethereum/cipher.js.map +1 -0
  24. package/build/ethereum/ethFuncs.d.ts +12 -0
  25. package/build/ethereum/ethFuncs.js +70 -0
  26. package/build/ethereum/ethFuncs.js.map +1 -0
  27. package/build/ethereum/etherUnits.d.ts +5 -0
  28. package/build/ethereum/etherUnits.js +60 -0
  29. package/build/ethereum/etherUnits.js.map +1 -0
  30. package/build/ethereum/myetherwallet.d.ts +47 -0
  31. package/build/ethereum/myetherwallet.js +294 -0
  32. package/build/ethereum/myetherwallet.js.map +1 -0
  33. package/build/ethereum/uiFuncs.d.ts +3 -0
  34. package/build/ethereum/uiFuncs.js +51 -0
  35. package/build/ethereum/uiFuncs.js.map +1 -0
  36. package/build/index.d.ts +111 -0
  37. package/build/index.js +310 -0
  38. package/build/index.js.map +1 -0
  39. package/build/memo.d.ts +6 -0
  40. package/build/memo.js +24 -0
  41. package/build/memo.js.map +1 -0
  42. package/build/qr.d.ts +8 -0
  43. package/build/qr.js +35 -0
  44. package/build/qr.js.map +1 -0
  45. package/build/rest/ajaxReq.d.ts +31 -0
  46. package/build/rest/ajaxReq.js +127 -0
  47. package/build/rest/ajaxReq.js.map +1 -0
  48. package/build/rest/endpoint.d.ts +18 -0
  49. package/build/rest/endpoint.js +26 -0
  50. package/build/rest/endpoint.js.map +1 -0
  51. package/build/rest/http.d.ts +10 -0
  52. package/build/rest/http.js +60 -0
  53. package/build/rest/http.js.map +1 -0
  54. package/build/rest/serializer.d.ts +1 -0
  55. package/build/rest/serializer.js +94 -0
  56. package/build/rest/serializer.js.map +1 -0
  57. package/build/type.d.ts +24 -0
  58. package/build/type.js +9 -0
  59. package/build/type.js.map +1 -0
  60. package/build/wallet.d.ts +35 -0
  61. package/build/wallet.js +162 -0
  62. package/build/wallet.js.map +1 -0
  63. package/package.json +41 -0
  64. package/src/bcRead.ts +184 -0
  65. package/src/bcTransaction.ts +157 -0
  66. package/src/blockies.ts +113 -0
  67. package/src/config.ts +33 -0
  68. package/src/connection.ts +243 -0
  69. package/src/customization.ts +156 -0
  70. package/src/ethereum/cipher.ts +118 -0
  71. package/src/ethereum/ethFuncs.ts +73 -0
  72. package/src/ethereum/etherUnits.ts +66 -0
  73. package/src/ethereum/myetherwallet.ts +354 -0
  74. package/src/ethereum/uiFuncs.ts +55 -0
  75. package/src/index.ts +366 -0
  76. package/src/memo.ts +37 -0
  77. package/src/qr.ts +34 -0
  78. package/src/rest/ajaxReq.ts +160 -0
  79. package/src/rest/endpoint.ts +31 -0
  80. package/src/rest/http.ts +69 -0
  81. package/src/rest/serializer.ts +99 -0
  82. package/src/type.ts +37 -0
  83. package/src/wallet.ts +200 -0
  84. package/tsconfig.json +31 -0
@@ -0,0 +1,118 @@
1
+ import crypto from 'crypto'
2
+ import { ec as EC } from 'elliptic'
3
+
4
+ /// Code adapted from https://github.com/LimelabsTech/eth-ecies
5
+
6
+ const ec = new EC('secp256k1')
7
+
8
+ function AES256CbcEncrypt (iv, key, plaintext) {
9
+ const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
10
+ const firstChunk = cipher.update(plaintext)
11
+ const secondChunk = cipher.final()
12
+
13
+ return Buffer.concat([firstChunk, secondChunk])
14
+ }
15
+
16
+ function AES256CbcDecrypt (iv, key, ciphertext) {
17
+ const cipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
18
+ const firstChunk = cipher.update(ciphertext)
19
+ const secondChunk = cipher.final()
20
+
21
+ return Buffer.concat([firstChunk, secondChunk])
22
+ }
23
+
24
+ function BufferEqual (b1, b2) {
25
+ if (b1.length !== b2.length) {
26
+ return false
27
+ }
28
+
29
+ let res = 0
30
+ for (let i = 0; i < b1.length; i++) {
31
+ res |= b1[i] ^ b2[i]
32
+ }
33
+
34
+ return res === 0
35
+ }
36
+
37
+ function Encrypt (publicKey, plaintext) {
38
+ /* DEBUG */
39
+
40
+ const pubKeyTo = Buffer.from(publicKey)
41
+ const ephemPrivKey = ec.keyFromPrivate(crypto.randomBytes(32))
42
+ const ephemPubKey = ephemPrivKey.getPublic()
43
+ const ephemPubKeyEncoded = Buffer.from(ephemPubKey.encode())
44
+
45
+ // Every EC public key begins with the 0x04 prefix before giving
46
+ // the location of the two point on the curve
47
+ const concatenated = Buffer.concat([Buffer.from([0x04]), pubKeyTo])
48
+ const keys = ec.keyFromPublic(concatenated)
49
+ const pub = keys.getPublic()
50
+ const px = ephemPrivKey.derive(pub)
51
+ const hash = crypto.createHash('sha512')
52
+ .update(Buffer.from(px.toArray())).digest()
53
+ const iv = crypto.randomBytes(16)
54
+ const encryptionKey = hash.slice(0, 32)
55
+ const macKey = hash.slice(32)
56
+ const ciphertext = AES256CbcEncrypt(iv, encryptionKey, plaintext)
57
+ const dataToMac = Buffer.concat([iv, ephemPubKeyEncoded, ciphertext])
58
+ const mac = crypto.createHmac('sha256', macKey).update(dataToMac).digest()
59
+
60
+ const serializedCiphertext = Buffer.concat([
61
+ iv, // 16 bytes
62
+ ephemPubKeyEncoded, // 65 bytes
63
+ mac, // 32 bytes
64
+ ciphertext
65
+ ])
66
+
67
+ return serializedCiphertext.toString('hex')
68
+ }
69
+
70
+ function Decrypt (privateKey, encrypted) {
71
+ const encryptedBuff = Buffer.from(encrypted, 'hex')
72
+ const privateKeyBuff = Buffer.from(privateKey)
73
+
74
+ // Read iv, ephemPubKey, mac, ciphertext from encrypted message
75
+
76
+ const iv = encryptedBuff.slice(0, 16)
77
+ const ephemPubKeyEncoded = encryptedBuff.slice(16, 81)
78
+ const mac = encryptedBuff.slice(81, 113)
79
+ const ciphertext = encryptedBuff.slice(113)
80
+ const ephemPubKey = ec.keyFromPublic(ephemPubKeyEncoded).getPublic()
81
+
82
+ const px = ec.keyFromPrivate(privateKeyBuff).derive(ephemPubKey)
83
+ const hash = crypto.createHash('sha512')
84
+ .update(Buffer.from(px.toArray())).digest()
85
+ const encryptionKey = hash.slice(0, 32)
86
+ const macKey = hash.slice(32)
87
+ const dataToMac = Buffer.concat([iv, ephemPubKeyEncoded, ciphertext])
88
+ const computedMac = crypto.createHmac('sha256', macKey)
89
+ .update(dataToMac).digest()
90
+
91
+ // Verify mac
92
+ if (!BufferEqual(computedMac, mac)) {
93
+ throw new Error('MAC mismatch')
94
+ }
95
+
96
+ const plaintext = AES256CbcDecrypt(iv, encryptionKey, ciphertext)
97
+
98
+ return plaintext.toString()
99
+ }
100
+
101
+
102
+ export function shortenAddress (address) {
103
+ if (address.toLowerCase().substring(0, 2) === '0x') {
104
+ address = address.substr(2)
105
+ }
106
+ return address
107
+ }
108
+
109
+ export function cipherMsg (publicKey, message) {
110
+ const msgBuff = Buffer.from(message)
111
+ const key = Buffer.from(shortenAddress(publicKey), 'hex')
112
+ return Encrypt(key, msgBuff)
113
+ }
114
+
115
+ export function decipherMsg (privateKey, ciphered) {
116
+ const key = Buffer.from(shortenAddress(privateKey), 'hex')
117
+ return Decrypt(key, ciphered)
118
+ }
@@ -0,0 +1,73 @@
1
+ import BigNumber from 'bignumber.js'
2
+ import ethUtil from 'ethereumjs-util'
3
+
4
+ import * as etherUnits from './etherUnits'
5
+
6
+ function isChecksumAddress (address) {
7
+ return address === ethUtil.toChecksumAddress(address)
8
+ }
9
+
10
+ export function validateEtherAddress (address) {
11
+ if (address.substring(0, 2) !== '0x') return false
12
+ else if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) return false
13
+ else if (/^(0x)?[0-9a-f]{40}$/.test(address) ||
14
+ /^(0x)?[0-9A-F]{40}$/.test(address)) return true
15
+ else { return isChecksumAddress(address) }
16
+ }
17
+
18
+ export function validateHexString (str) {
19
+ if (str === '') return true
20
+ str = str.substring(0, 2) === '0x'
21
+ ? str.substring(2).toUpperCase()
22
+ : str.toUpperCase()
23
+ const re = /^[0-9A-F]+$/g
24
+ return re.test(str)
25
+ }
26
+
27
+ export function sanitizeHex (hex) {
28
+ hex = hex.substring(0, 2) === '0x' ? hex.substring(2) : hex
29
+ if (hex === '') return ''
30
+ return '0x' + padLeftEven(hex)
31
+ }
32
+
33
+ function padLeftEven (hex) {
34
+ hex = hex.length % 2 !== 0 ? '0' + hex : hex
35
+ return hex
36
+ }
37
+
38
+ export function addTinyMoreToGas (hex) {
39
+ hex = this.sanitizeHex(hex)
40
+ return new BigNumber(hex).plus(etherUnits.getValueOfUnit('gwei'))
41
+ .toDigits(2).toString(16)
42
+ }
43
+
44
+ export function decimalToHex (dec) {
45
+ return new BigNumber(dec).toString(16)
46
+ }
47
+
48
+ export function getNakedAddress (address) {
49
+ return address.toLowerCase().replace('0x', '')
50
+ }
51
+
52
+ export function padLeft (n, width, z?) {
53
+ z = z || '0'
54
+ n = n + ''
55
+ return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n
56
+ }
57
+
58
+ export function getDataObj (to, func, arrVals) {
59
+ let val = ''
60
+ for (let i = 0; i < arrVals.length; i++) val += padLeft(arrVals[i], 64)
61
+ return { to: to, data: func + val }
62
+ }
63
+
64
+ export function encodeNumber (number) {
65
+ let valueHex
66
+ if (number < 0) {
67
+ valueHex = padLeft(new BigNumber(16).pow(64).plus(number).toString(16), 64)
68
+ } else {
69
+ valueHex = padLeft(new BigNumber(number).toString(16), 64)
70
+ }
71
+
72
+ return valueHex
73
+ }
@@ -0,0 +1,66 @@
1
+ import BigNumber from 'bignumber.js'
2
+
3
+ const unitMap = {
4
+ wei: '1',
5
+ kwei: '1000',
6
+ ada: '1000',
7
+ femtoether: '1000',
8
+ mwei: '1000000',
9
+ babbage: '1000000',
10
+ picoether: '1000000',
11
+ gwei: '1000000000',
12
+ shannon: '1000000000',
13
+ nanoether: '1000000000',
14
+ nano: '1000000000',
15
+ szabo: '1000000000000',
16
+ microether: '1000000000000',
17
+ micro: '1000000000000',
18
+ finney: '1000000000000000',
19
+ milliether: '1000000000000000',
20
+ milli: '1000000000000000',
21
+ ether: '1000000000000000000',
22
+ kether: '1000000000000000000000',
23
+ grand: '1000000000000000000000',
24
+ einstein: '1000000000000000000000',
25
+ mether: '1000000000000000000000000',
26
+ gether: '1000000000000000000000000000',
27
+ tether: '1000000000000000000000000000000'
28
+ }
29
+
30
+ export function getValueOfUnit (unit) {
31
+ unit = unit ? unit.toLowerCase() : 'ether'
32
+ const unitValue = unitMap[unit]
33
+ if (unitValue === undefined) {
34
+ throw new Error(
35
+ "This unit doesn't exists, please use the " +
36
+ 'one of the following units ' + JSON.stringify(unitMap, null, 2))
37
+ }
38
+ return new BigNumber(unitValue, 10)
39
+ }
40
+
41
+ export function fiatToWei (number, pricePerEther) {
42
+ return new BigNumber(String(number))
43
+ .div(pricePerEther)
44
+ .times(this.getValueOfUnit('ether'))
45
+ .round(0)
46
+ .toString(10)
47
+ }
48
+
49
+ export function toFiat (number, unit, multi) {
50
+ return new BigNumber(this.toEther(number, unit))
51
+ .times(multi)
52
+ .round(5)
53
+ .toString(10)
54
+ }
55
+
56
+ export function toEther (number, unit) {
57
+ return new BigNumber(this.toWei(number, unit))
58
+ .div(this.getValueOfUnit('ether'))
59
+ .toString(10)
60
+ }
61
+
62
+ export function toWei (number, unit) {
63
+ return new BigNumber(String(number))
64
+ .times(this.getValueOfUnit(unit))
65
+ .toString(10)
66
+ }
@@ -0,0 +1,354 @@
1
+ import crypto from 'crypto'
2
+ import { v4 as uuidv4 } from 'uuid'
3
+ import ethUtil from 'ethereumjs-util'
4
+ import scrypt from 'scryptsy'
5
+
6
+
7
+ function decipherBuffer (decipher, data) {
8
+ return Buffer.concat([decipher.update(data), decipher.final()])
9
+ }
10
+
11
+
12
+ function decodeCryptojsSalt (input) {
13
+ const ciphertext = Buffer.from(input, 'base64')
14
+ if (ciphertext.slice(0, 8).toString() === 'Salted__') {
15
+ return {
16
+ salt: ciphertext.slice(8, 16),
17
+ ciphertext: ciphertext.slice(16)
18
+ }
19
+ } else {
20
+ return {
21
+ ciphertext: ciphertext
22
+ }
23
+ }
24
+ }
25
+
26
+ function evpKdf (data, salt, opts) {
27
+ // A single EVP iteration, returns `D_i`, where block equlas to `D_(i-1)`
28
+
29
+ function iter (block) {
30
+ let hash = crypto.createHash(opts.digest || 'md5')
31
+ hash.update(block)
32
+ hash.update(data)
33
+ hash.update(salt)
34
+ block = hash.digest()
35
+ for (let i = 1; i < (opts.count || 1); i++) {
36
+ hash = crypto.createHash(opts.digest || 'md5')
37
+ hash.update(block)
38
+ block = hash.digest()
39
+ }
40
+ return block
41
+ }
42
+ const keysize = opts.keysize || 16
43
+ const ivsize = opts.ivsize || 16
44
+ const ret = []
45
+ let i = 0
46
+ while (Buffer.concat(ret).length < (keysize + ivsize)) {
47
+ ret[i] = iter((i === 0) ? Buffer.alloc(0) : ret[i - 1])
48
+ i++
49
+ }
50
+ const tmp = Buffer.concat(ret)
51
+ return {
52
+ key: tmp.slice(0, keysize),
53
+ iv: tmp.slice(keysize, keysize + ivsize)
54
+ }
55
+ }
56
+
57
+
58
+
59
+ export default class Wallet {
60
+ privKey
61
+
62
+ constructor (priv?) {
63
+ if (!priv) {
64
+ priv = crypto.randomBytes(32)
65
+ }
66
+ this.privKey = priv.length === 32 ? priv : Buffer.from(priv, 'hex')
67
+ }
68
+
69
+ static generate (icapDirect) {
70
+ if (!icapDirect) {
71
+ return new this()
72
+ }
73
+
74
+ while (true) {
75
+ const privKey = crypto.randomBytes(32)
76
+ if (ethUtil.privateToAddress(privKey)[0] === 0) {
77
+ return new this(privKey)
78
+ }
79
+ }
80
+ }
81
+
82
+ static fromPrivateKey (priv) {
83
+ return new this(priv)
84
+ }
85
+
86
+ getPrivateKey () { return this.privKey }
87
+ getPrivateKeyString () { return this.getPrivateKey().toString('hex') }
88
+ getPublicKey () { return ethUtil.privateToPublic(this.privKey) }
89
+ getPublicKeyString () { return '0x' + this.getPublicKey().toString('hex') }
90
+ getAddress () { return ethUtil.privateToAddress(this.privKey) }
91
+ getAddressString () { return '0x' + this.getAddress().toString('hex') }
92
+ getChecksumAddressString () {
93
+ return ethUtil.toChecksumAddress(this.getAddressString())
94
+ }
95
+
96
+ toV3 (password, opts) {
97
+ opts = opts || {}
98
+ const salt = opts.salt || crypto.randomBytes(32)
99
+ const iv = opts.iv || crypto.randomBytes(16)
100
+ let derivedKey
101
+ const kdf = opts.kdf || 'scrypt'
102
+ const kdfparams: {[k: string]: any} = {
103
+ dklen: opts.dklen || 32,
104
+ salt: salt.toString('hex')
105
+ }
106
+ if (kdf === 'pbkdf2') {
107
+ kdfparams.c = opts.c || 262144
108
+ kdfparams.prf = 'hmac-sha256'
109
+ derivedKey = crypto.pbkdf2Sync(
110
+ Buffer.from(password), salt, kdfparams.c, kdfparams.dklen, 'sha256')
111
+ } else if (kdf === 'scrypt') {
112
+ // FIXME: support progress reporting callback
113
+ kdfparams.n = opts.n || 262144
114
+ kdfparams.r = opts.r || 8
115
+ kdfparams.p = opts.p || 1
116
+ derivedKey = scrypt(
117
+ Buffer.from(password), salt, kdfparams.n, kdfparams.r,
118
+ kdfparams.p, kdfparams.dklen)
119
+ } else {
120
+ throw new Error('Unsupported kdf')
121
+ }
122
+ const cipher = crypto.createCipheriv(opts.cipher || 'aes-128-ctr',
123
+ derivedKey.slice(0, 16), iv)
124
+ if (!cipher) {
125
+ throw new Error('Unsupported cipher')
126
+ }
127
+ const ciphertext = Buffer.concat(
128
+ [cipher.update(this.privKey), cipher.final()])
129
+ const mac = ethUtil.keccak(
130
+ Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
131
+
132
+ const obj: {[k: string]: any} = {
133
+ version: 3,
134
+ id: uuidv4({
135
+ random: opts.uuid || crypto.randomBytes(16)
136
+ }),
137
+ address: this.getAddress().toString('hex'),
138
+ Crypto: {
139
+ ciphertext: ciphertext.toString('hex'),
140
+ cipherparams: {
141
+ iv: iv.toString('hex')
142
+ },
143
+ cipher: opts.cipher || 'aes-128-ctr',
144
+ kdf: kdf,
145
+ kdfparams: kdfparams,
146
+ mac: mac.toString('hex')
147
+ },
148
+ // ComChain addition:
149
+ server: { name: opts.server_name }
150
+ }
151
+
152
+ if (typeof opts.message_key !== 'undefined') {
153
+ obj.message_key = opts.message_key
154
+ }
155
+
156
+ return obj
157
+ }
158
+
159
+
160
+ cipher (password, data, kdfparams) {
161
+ if (!kdfparams) {
162
+ throw new Error(
163
+ 'Wallet.cipher(..) requires a 3rd parameter kdfparams.'
164
+ )
165
+ }
166
+ const iv = crypto.randomBytes(16)
167
+ const derivedKey = scrypt(Buffer.from(password),
168
+ Buffer.from(kdfparams.salt, 'hex'),
169
+ kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen)
170
+
171
+ const cipher = crypto.createCipheriv(
172
+ 'aes-128-ctr', derivedKey.slice(0, 16), iv)
173
+
174
+ const ciphertext = Buffer.concat([cipher.update(data), cipher.final()])
175
+ const mac = ethUtil.keccak(
176
+ Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
177
+ return {
178
+ crypto: {
179
+ ciphertext: ciphertext.toString('hex'),
180
+ cipherparams: {
181
+ iv: iv.toString('hex')
182
+ },
183
+ cipher: 'aes-128-ctr',
184
+ kdf: 'scrypt',
185
+ kdfparams: kdfparams,
186
+ mac: mac.toString('hex')
187
+ }
188
+ }
189
+ }
190
+
191
+ decifer (input, password) {
192
+ const json = (typeof input === 'object')
193
+ ? input
194
+ : JSON.parse(input.toLowerCase())
195
+
196
+ const kdfparams = json.crypto.kdfparams
197
+ const derivedKey = scrypt(
198
+ Buffer.from(password),
199
+ Buffer.from(kdfparams.salt, 'hex'),
200
+ kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen)
201
+
202
+ const ciphertext = Buffer.from(json.crypto.ciphertext, 'hex')
203
+ const mac = ethUtil.keccak(
204
+ Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
205
+ if (mac.toString('hex') !== json.crypto.mac) {
206
+ throw new Error('Key derivation failed - possibly wrong passphrase')
207
+ }
208
+ const decipher = crypto.createDecipheriv(
209
+ json.crypto.cipher, derivedKey.slice(0, 16),
210
+ Buffer.from(json.crypto.cipherparams.iv, 'hex'))
211
+ return decipherBuffer(decipher, ciphertext)
212
+ }
213
+
214
+ toJSON () {
215
+ return {
216
+ address: this.getAddressString(),
217
+ checksumAddress: this.getChecksumAddressString(),
218
+ privKey: this.getPrivateKeyString(),
219
+ pubKey: this.getPublicKeyString(),
220
+ publisher: 'MyEtherWallet',
221
+ encrypted: false,
222
+ version: 2
223
+ }
224
+ }
225
+
226
+ static fromMyEtherWallet (input, password) {
227
+ const json = (typeof input === 'object') ? input : JSON.parse(input)
228
+ let privKey
229
+ if (!json.locked) {
230
+ if (json.private.length !== 64) {
231
+ throw new Error('Invalid private key length')
232
+ }
233
+ privKey = Buffer.from(json.private, 'hex')
234
+ } else {
235
+ if (typeof password !== 'string') {
236
+ throw new Error('Password required')
237
+ }
238
+ if (password.length < 7) {
239
+ throw new Error('Password must be at least 7 characters')
240
+ }
241
+ let cipher = json.encrypted ? json.private.slice(0, 128) : json.private
242
+ cipher = decodeCryptojsSalt(cipher)
243
+ const evp = evpKdf(Buffer.from(password), cipher.salt, {
244
+ keysize: 32,
245
+ ivsize: 16
246
+ })
247
+ const decipher = crypto.createDecipheriv('aes-256-cbc', evp.key, evp.iv)
248
+ privKey = decipherBuffer(decipher, Buffer.from(cipher.ciphertext))
249
+ privKey = Buffer.from((privKey.toString()), 'hex')
250
+ }
251
+ const wallet = new this(privKey)
252
+ if (wallet.getAddressString() !== json.address) {
253
+ throw new Error('Invalid private key or address')
254
+ }
255
+ return wallet
256
+ }
257
+
258
+ static fromMyEtherWalletV2 (input) {
259
+ const json = (typeof input === 'object') ? input : JSON.parse(input)
260
+ if (json.privKey.length !== 64) {
261
+ throw new Error('Invalid private key length')
262
+ };
263
+ const privKey = Buffer.from(json.privKey, 'hex')
264
+ return new this(privKey)
265
+ }
266
+
267
+ static fromEthSale (input, password) {
268
+ const json = (typeof input === 'object') ? input : JSON.parse(input)
269
+ const encseed = Buffer.from(json.encseed, 'hex')
270
+ const derivedKey = crypto.pbkdf2Sync(
271
+ Buffer.from(password), Buffer.from(password), 2000, 32, 'sha256')
272
+ .slice(0, 16)
273
+ const decipher = crypto.createDecipheriv(
274
+ 'aes-128-cbc', derivedKey, encseed.slice(0, 16))
275
+ const seed = decipherBuffer(decipher, encseed.slice(16))
276
+ const wallet = new this(ethUtil.keccak(seed))
277
+ if (wallet.getAddress().toString('hex') !== json.ethaddr) {
278
+ throw new Error('Decoded key mismatch - possibly wrong passphrase')
279
+ }
280
+ return wallet
281
+ }
282
+
283
+ static fromMyEtherWalletKey (input, password) {
284
+ let cipher = input.slice(0, 128)
285
+ cipher = decodeCryptojsSalt(cipher)
286
+ const evp = evpKdf(Buffer.from(password), cipher.salt, {
287
+ keysize: 32,
288
+ ivsize: 16
289
+ })
290
+ const decipher = crypto.createDecipheriv('aes-256-cbc', evp.key, evp.iv)
291
+ let privKey = decipherBuffer(decipher,
292
+ Buffer.from(cipher.ciphertext))
293
+ privKey = Buffer.from((privKey.toString()), 'hex')
294
+ return new this(privKey)
295
+ }
296
+
297
+ static fromV3 (input, password, nonStrict) {
298
+ const json = (typeof input === 'object')
299
+ ? input
300
+ : JSON.parse(nonStrict ? input.toLowerCase() : input)
301
+ if (json.version !== 3) {
302
+ throw new Error('Not a V3 wallet')
303
+ }
304
+ let derivedKey
305
+ let kdfparams
306
+ if (json.crypto.kdf === 'scrypt') {
307
+ kdfparams = json.crypto.kdfparams
308
+ derivedKey = scrypt(
309
+ Buffer.from(password),
310
+ Buffer.from(kdfparams.salt, 'hex'),
311
+ kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen)
312
+ } else if (json.crypto.kdf === 'pbkdf2') {
313
+ kdfparams = json.crypto.kdfparams
314
+ if (kdfparams.prf !== 'hmac-sha256') {
315
+ throw new Error('Unsupported parameters to PBKDF2')
316
+ }
317
+ derivedKey = crypto.pbkdf2Sync(
318
+ Buffer.from(password),
319
+ Buffer.from(kdfparams.salt, 'hex'),
320
+ kdfparams.c, kdfparams.dklen, 'sha256')
321
+ } else {
322
+ throw new Error('Unsupported key derivation scheme')
323
+ }
324
+ const ciphertext = Buffer.from(json.crypto.ciphertext, 'hex')
325
+ const mac = ethUtil.keccak(Buffer.concat(
326
+ [derivedKey.slice(16, 32), ciphertext]))
327
+ if (mac.toString('hex') !== json.crypto.mac) {
328
+ throw new Error('Key derivation failed - possibly wrong passphrase')
329
+ }
330
+ const decipher = crypto.createDecipheriv(
331
+ json.crypto.cipher, derivedKey.slice(0, 16),
332
+ Buffer.from(json.crypto.cipherparams.iv, 'hex'))
333
+ const seed = decipherBuffer(decipher, ciphertext)
334
+ return new this(seed)
335
+ }
336
+
337
+ toV3String (password, opts) {
338
+ return JSON.stringify(this.toV3(password, opts))
339
+ }
340
+
341
+ getV3Filename (timestamp) {
342
+ const ts = timestamp ? new Date(timestamp) : new Date()
343
+ return `UTC--${ts.toJSON().replace(/:/g, '-')}--${this.getAddress().toString('hex')}`
344
+ }
345
+
346
+ signMessage (msg) {
347
+ const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(msg))
348
+ const signature = ethUtil.ecsign(msgHash, this.privKey)
349
+ return ethUtil.bufferToHex(
350
+ Buffer.concat([signature.r, signature.s, ethUtil.toBuffer(signature.v)]))
351
+ }
352
+
353
+
354
+ }
@@ -0,0 +1,55 @@
1
+ import Tx from 'ethereumjs-tx'
2
+ import * as ethFuncs from './ethFuncs'
3
+ import * as etherUnits from './etherUnits'
4
+
5
+
6
+ function isNumeric (n) {
7
+ return !isNaN(parseFloat(n)) && isFinite(n)
8
+ }
9
+
10
+ function isTxDataValid (txData) {
11
+ if (txData.to !== '0xCONTRACT' &&
12
+ !ethFuncs.validateEtherAddress(txData.to)) {
13
+ throw new Error('ERROR_6')
14
+ } else if (!isNumeric(txData.value) ||
15
+ parseFloat(txData.value) < 0) {
16
+ throw new Error('ERROR_8')
17
+ } else if (!isNumeric(txData.gasLimit) ||
18
+ parseFloat(txData.gasLimit) <= 0) {
19
+ throw new Error('ERROR_9')
20
+ } else if (!ethFuncs.validateHexString(txData.data)) {
21
+ throw new Error('ERROR_10')
22
+ }
23
+ if (txData.to === '0xCONTRACT') txData.to = ''
24
+ }
25
+
26
+ export function generateTx (txData, data) {
27
+ try {
28
+ isTxDataValid(txData)
29
+
30
+ const rawTx: {[k: string]: any} = {
31
+ nonce: ethFuncs.sanitizeHex(data.nonce),
32
+ gasPrice: ethFuncs.sanitizeHex(
33
+ ethFuncs.addTinyMoreToGas(data.gasprice)),
34
+ gasLimit: ethFuncs.sanitizeHex(
35
+ ethFuncs.decimalToHex(txData.gasLimit)),
36
+ to: ethFuncs.sanitizeHex(txData.to),
37
+ value: ethFuncs.sanitizeHex(
38
+ ethFuncs.decimalToHex(etherUnits.toWei(txData.value, txData.unit))),
39
+ data: ethFuncs.sanitizeHex(txData.data)
40
+ }
41
+ const eTx = new Tx(rawTx)
42
+
43
+ eTx.sign(Buffer.from(txData.key, 'hex'))
44
+ rawTx.rawTx = JSON.stringify(rawTx)
45
+ rawTx.signedTx = '0x' + eTx.serialize().toString('hex')
46
+ rawTx.isError = false
47
+ return rawTx
48
+ } catch (e) {
49
+ return {
50
+ isError: true,
51
+ error: e
52
+ }
53
+ }
54
+ }
55
+