@exodus/ethereum-lib 0.0.9 → 0.2.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.
package/src/abi/dai.js ADDED
@@ -0,0 +1,348 @@
1
+ export default [
2
+ {
3
+ inputs: [{ internalType: 'uint256', name: 'chainId_', type: 'uint256' }],
4
+ payable: false,
5
+ stateMutability: 'nonpayable',
6
+ type: 'constructor',
7
+ },
8
+ {
9
+ anonymous: false,
10
+ inputs: [
11
+ { indexed: true, internalType: 'address', name: 'src', type: 'address' },
12
+ {
13
+ indexed: true,
14
+ internalType: 'address',
15
+ name: 'guy',
16
+ type: 'address',
17
+ },
18
+ { indexed: false, internalType: 'uint256', name: 'wad', type: 'uint256' },
19
+ ],
20
+ name: 'Approval',
21
+ type: 'event',
22
+ },
23
+ {
24
+ anonymous: true,
25
+ inputs: [
26
+ { indexed: true, internalType: 'bytes4', name: 'sig', type: 'bytes4' },
27
+ {
28
+ indexed: true,
29
+ internalType: 'address',
30
+ name: 'usr',
31
+ type: 'address',
32
+ },
33
+ { indexed: true, internalType: 'bytes32', name: 'arg1', type: 'bytes32' },
34
+ {
35
+ indexed: true,
36
+ internalType: 'bytes32',
37
+ name: 'arg2',
38
+ type: 'bytes32',
39
+ },
40
+ { indexed: false, internalType: 'bytes', name: 'data', type: 'bytes' },
41
+ ],
42
+ name: 'LogNote',
43
+ type: 'event',
44
+ },
45
+ {
46
+ anonymous: false,
47
+ inputs: [
48
+ { indexed: true, internalType: 'address', name: 'src', type: 'address' },
49
+ {
50
+ indexed: true,
51
+ internalType: 'address',
52
+ name: 'dst',
53
+ type: 'address',
54
+ },
55
+ { indexed: false, internalType: 'uint256', name: 'wad', type: 'uint256' },
56
+ ],
57
+ name: 'Transfer',
58
+ type: 'event',
59
+ },
60
+ {
61
+ constant: true,
62
+ inputs: [],
63
+ name: 'DOMAIN_SEPARATOR',
64
+ outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
65
+ payable: false,
66
+ stateMutability: 'view',
67
+ type: 'function',
68
+ },
69
+ {
70
+ constant: true,
71
+ inputs: [],
72
+ name: 'PERMIT_TYPEHASH',
73
+ outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
74
+ payable: false,
75
+ stateMutability: 'view',
76
+ type: 'function',
77
+ },
78
+ {
79
+ constant: true,
80
+ inputs: [
81
+ { internalType: 'address', name: '', type: 'address' },
82
+ {
83
+ internalType: 'address',
84
+ name: '',
85
+ type: 'address',
86
+ },
87
+ ],
88
+ name: 'allowance',
89
+ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
90
+ payable: false,
91
+ stateMutability: 'view',
92
+ type: 'function',
93
+ },
94
+ {
95
+ constant: false,
96
+ inputs: [
97
+ { internalType: 'address', name: 'usr', type: 'address' },
98
+ {
99
+ internalType: 'uint256',
100
+ name: 'wad',
101
+ type: 'uint256',
102
+ },
103
+ ],
104
+ name: 'approve',
105
+ outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
106
+ payable: false,
107
+ stateMutability: 'nonpayable',
108
+ type: 'function',
109
+ },
110
+ {
111
+ constant: true,
112
+ inputs: [{ internalType: 'address', name: '', type: 'address' }],
113
+ name: 'balanceOf',
114
+ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
115
+ payable: false,
116
+ stateMutability: 'view',
117
+ type: 'function',
118
+ },
119
+ {
120
+ constant: false,
121
+ inputs: [
122
+ { internalType: 'address', name: 'usr', type: 'address' },
123
+ {
124
+ internalType: 'uint256',
125
+ name: 'wad',
126
+ type: 'uint256',
127
+ },
128
+ ],
129
+ name: 'burn',
130
+ outputs: [],
131
+ payable: false,
132
+ stateMutability: 'nonpayable',
133
+ type: 'function',
134
+ },
135
+ {
136
+ constant: true,
137
+ inputs: [],
138
+ name: 'decimals',
139
+ outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }],
140
+ payable: false,
141
+ stateMutability: 'view',
142
+ type: 'function',
143
+ },
144
+ {
145
+ constant: false,
146
+ inputs: [{ internalType: 'address', name: 'guy', type: 'address' }],
147
+ name: 'deny',
148
+ outputs: [],
149
+ payable: false,
150
+ stateMutability: 'nonpayable',
151
+ type: 'function',
152
+ },
153
+ {
154
+ constant: false,
155
+ inputs: [
156
+ { internalType: 'address', name: 'usr', type: 'address' },
157
+ {
158
+ internalType: 'uint256',
159
+ name: 'wad',
160
+ type: 'uint256',
161
+ },
162
+ ],
163
+ name: 'mint',
164
+ outputs: [],
165
+ payable: false,
166
+ stateMutability: 'nonpayable',
167
+ type: 'function',
168
+ },
169
+ {
170
+ constant: false,
171
+ inputs: [
172
+ { internalType: 'address', name: 'src', type: 'address' },
173
+ {
174
+ internalType: 'address',
175
+ name: 'dst',
176
+ type: 'address',
177
+ },
178
+ { internalType: 'uint256', name: 'wad', type: 'uint256' },
179
+ ],
180
+ name: 'move',
181
+ outputs: [],
182
+ payable: false,
183
+ stateMutability: 'nonpayable',
184
+ type: 'function',
185
+ },
186
+ {
187
+ constant: true,
188
+ inputs: [],
189
+ name: 'name',
190
+ outputs: [{ internalType: 'string', name: '', type: 'string' }],
191
+ payable: false,
192
+ stateMutability: 'view',
193
+ type: 'function',
194
+ },
195
+ {
196
+ constant: true,
197
+ inputs: [{ internalType: 'address', name: '', type: 'address' }],
198
+ name: 'nonces',
199
+ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
200
+ payable: false,
201
+ stateMutability: 'view',
202
+ type: 'function',
203
+ },
204
+ {
205
+ constant: false,
206
+ inputs: [
207
+ { internalType: 'address', name: 'holder', type: 'address' },
208
+ {
209
+ internalType: 'address',
210
+ name: 'spender',
211
+ type: 'address',
212
+ },
213
+ { internalType: 'uint256', name: 'nonce', type: 'uint256' },
214
+ {
215
+ internalType: 'uint256',
216
+ name: 'expiry',
217
+ type: 'uint256',
218
+ },
219
+ { internalType: 'bool', name: 'allowed', type: 'bool' },
220
+ {
221
+ internalType: 'uint8',
222
+ name: 'v',
223
+ type: 'uint8',
224
+ },
225
+ { internalType: 'bytes32', name: 'r', type: 'bytes32' },
226
+ {
227
+ internalType: 'bytes32',
228
+ name: 's',
229
+ type: 'bytes32',
230
+ },
231
+ ],
232
+ name: 'permit',
233
+ outputs: [],
234
+ payable: false,
235
+ stateMutability: 'nonpayable',
236
+ type: 'function',
237
+ },
238
+ {
239
+ constant: false,
240
+ inputs: [
241
+ { internalType: 'address', name: 'usr', type: 'address' },
242
+ {
243
+ internalType: 'uint256',
244
+ name: 'wad',
245
+ type: 'uint256',
246
+ },
247
+ ],
248
+ name: 'pull',
249
+ outputs: [],
250
+ payable: false,
251
+ stateMutability: 'nonpayable',
252
+ type: 'function',
253
+ },
254
+ {
255
+ constant: false,
256
+ inputs: [
257
+ { internalType: 'address', name: 'usr', type: 'address' },
258
+ {
259
+ internalType: 'uint256',
260
+ name: 'wad',
261
+ type: 'uint256',
262
+ },
263
+ ],
264
+ name: 'push',
265
+ outputs: [],
266
+ payable: false,
267
+ stateMutability: 'nonpayable',
268
+ type: 'function',
269
+ },
270
+ {
271
+ constant: false,
272
+ inputs: [{ internalType: 'address', name: 'guy', type: 'address' }],
273
+ name: 'rely',
274
+ outputs: [],
275
+ payable: false,
276
+ stateMutability: 'nonpayable',
277
+ type: 'function',
278
+ },
279
+ {
280
+ constant: true,
281
+ inputs: [],
282
+ name: 'symbol',
283
+ outputs: [{ internalType: 'string', name: '', type: 'string' }],
284
+ payable: false,
285
+ stateMutability: 'view',
286
+ type: 'function',
287
+ },
288
+ {
289
+ constant: true,
290
+ inputs: [],
291
+ name: 'totalSupply',
292
+ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
293
+ payable: false,
294
+ stateMutability: 'view',
295
+ type: 'function',
296
+ },
297
+ {
298
+ constant: false,
299
+ inputs: [
300
+ { internalType: 'address', name: 'dst', type: 'address' },
301
+ {
302
+ internalType: 'uint256',
303
+ name: 'wad',
304
+ type: 'uint256',
305
+ },
306
+ ],
307
+ name: 'transfer',
308
+ outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
309
+ payable: false,
310
+ stateMutability: 'nonpayable',
311
+ type: 'function',
312
+ },
313
+ {
314
+ constant: false,
315
+ inputs: [
316
+ { internalType: 'address', name: 'src', type: 'address' },
317
+ {
318
+ internalType: 'address',
319
+ name: 'dst',
320
+ type: 'address',
321
+ },
322
+ { internalType: 'uint256', name: 'wad', type: 'uint256' },
323
+ ],
324
+ name: 'transferFrom',
325
+ outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
326
+ payable: false,
327
+ stateMutability: 'nonpayable',
328
+ type: 'function',
329
+ },
330
+ {
331
+ constant: true,
332
+ inputs: [],
333
+ name: 'version',
334
+ outputs: [{ internalType: 'string', name: '', type: 'string' }],
335
+ payable: false,
336
+ stateMutability: 'view',
337
+ type: 'function',
338
+ },
339
+ {
340
+ constant: true,
341
+ inputs: [{ internalType: 'address', name: '', type: 'address' }],
342
+ name: 'wards',
343
+ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
344
+ payable: false,
345
+ stateMutability: 'view',
346
+ type: 'function',
347
+ },
348
+ ]
@@ -0,0 +1,7 @@
1
+ import cdai from './cdai'
2
+ import dai from './dai'
3
+
4
+ export default {
5
+ cdai,
6
+ dai,
7
+ }
@@ -0,0 +1 @@
1
+ export const CHAIN_IDS = { ethereum: 1, ethereumclassic: 61 }
@@ -0,0 +1,77 @@
1
+ import ethUtil from 'ethereumjs-util'
2
+
3
+ // TODO: migrate to using solidity-contract
4
+ export default function createContract(addresses, currency) {
5
+ // First 4 bytes of Keccak256('transfer(address,uint256)')
6
+ // const TRANSFER_METHOD_ID = ethUtil.bufferToHex(ethUtil.sha3('transfer(address,uint256)').slice(0, 4))
7
+ const TRANSFER_METHOD_ID = '0xa9059cbb'
8
+
9
+ // Keccak256('Transfer(address,address,uint256)')
10
+ // const TRANSFER_EVENT_ID = ethUtil.bufferToHex(ethUtil.sha3('Transfer(address,address,uint256)'))
11
+ const TRANSFER_EVENT_ID = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
12
+
13
+ const transfer = {
14
+ METHOD_ID: TRANSFER_METHOD_ID,
15
+ EVENT_ID: TRANSFER_EVENT_ID,
16
+
17
+ build(to, bufAmount) {
18
+ return Buffer.concat([
19
+ ethUtil.toBuffer(TRANSFER_METHOD_ID),
20
+ ethUtil.zeros(12),
21
+ ethUtil.toBuffer(to),
22
+ ethUtil.zeros(32 - bufAmount.length),
23
+ bufAmount,
24
+ ])
25
+ },
26
+
27
+ test(data) {
28
+ return ethUtil.bufferToHex(data.slice(0, 4)) === TRANSFER_METHOD_ID
29
+ },
30
+
31
+ parse(data) {
32
+ if (!transfer.test(data)) throw new Error('It is not transfer data')
33
+
34
+ return {
35
+ to: ethUtil.bufferToHex(data.slice(16, 36)),
36
+ amount: currency.baseUnit(ethUtil.bufferToHex(data.slice(36, 68))),
37
+ }
38
+ },
39
+ }
40
+
41
+ // ethUtil.bufferToHex(ethUtil.sha3('approve(address,uint256)').slice(0, 4))
42
+ const APPROVE_METHOD_ID = '0x095ea7b3'
43
+
44
+ // TODO: not verified:
45
+ // ethUtil.bufferToHex(ethUtil.sha3('Approve(address,address,uint256)'))
46
+ const APPROVE_EVENT_ID = '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925'
47
+
48
+ const approve = {
49
+ METHOD_ID: APPROVE_METHOD_ID,
50
+ EVENT_ID: APPROVE_EVENT_ID,
51
+
52
+ build(address, bufAmount) {
53
+ return Buffer.concat([
54
+ ethUtil.toBuffer(APPROVE_METHOD_ID),
55
+ ethUtil.zeros(12),
56
+ ethUtil.toBuffer(address),
57
+ ethUtil.zeros(32 - bufAmount.length),
58
+ bufAmount,
59
+ ])
60
+ },
61
+
62
+ test(data) {
63
+ return ethUtil.bufferToHex(data.slice(0, 4)) === APPROVE_METHOD_ID
64
+ },
65
+
66
+ parse(data) {
67
+ if (!approve.test(data)) throw new Error('It is not approve data')
68
+
69
+ return {
70
+ address: ethUtil.bufferToHex(data.slice(16, 36)),
71
+ amount: currency.baseUnit(ethUtil.bufferToHex(data.slice(36, 68))),
72
+ }
73
+ },
74
+ }
75
+
76
+ return { addresses, transfer, approve }
77
+ }
@@ -0,0 +1,8 @@
1
+ import createContractErc20 from './erc20'
2
+
3
+ export default function createContract(addresses, currency, assetName) {
4
+ switch (assetName) {
5
+ default:
6
+ return createContractErc20(addresses, currency)
7
+ }
8
+ }
package/src/encode.js ADDED
@@ -0,0 +1,36 @@
1
+ import etherUtil from 'ethereumjs-util'
2
+
3
+ export function validate(address) {
4
+ if (typeof address !== 'string') return false
5
+
6
+ // https://github.com/ethereumjs/ethereumjs-util/issues/54
7
+ if (address.slice(0, 2) !== '0x' || address.length !== 42) return false
8
+
9
+ if (!hasChecksum(address)) return true
10
+ return etherUtil.isValidChecksumAddress(address)
11
+ }
12
+
13
+ export function hasChecksum(address) {
14
+ if (/^0x[0-9A-F]{40}$/.test(address) || /^0x[0-9a-f]{40}$/.test(address)) return false
15
+ return true
16
+ }
17
+
18
+ export function encodePrivate(privKey) {
19
+ return '0x' + privKey.toString('hex')
20
+ }
21
+
22
+ export function encodePublic(compressedPubKey) {
23
+ const hash160bits = etherUtil.publicToAddress(compressedPubKey, true)
24
+ return etherUtil.toChecksumAddress(hash160bits.toString('hex'))
25
+ }
26
+
27
+ export function isValidPrivate(privateKey) {
28
+ if (privateKey.length !== 32 || !etherUtil.isValidPrivate(privateKey)) {
29
+ return false
30
+ }
31
+ return true
32
+ }
33
+
34
+ export function encodePublicFromPrivate(privateKey) {
35
+ return etherUtil.toChecksumAddress(etherUtil.privateToAddress(privateKey).toString('hex'))
36
+ }
@@ -0,0 +1,11 @@
1
+ import { FeeData } from '@exodus/asset-lib'
2
+
3
+ export default new FeeData(
4
+ {
5
+ gasPrice: '20 Gwei',
6
+ max: '250 Gwei',
7
+ min: '1 Gwei',
8
+ },
9
+ 'gasPrice',
10
+ 'ethereum'
11
+ )
@@ -0,0 +1,11 @@
1
+ import { FeeData } from '@exodus/asset-lib'
2
+
3
+ export default new FeeData(
4
+ {
5
+ gasPrice: '20 Gwei',
6
+ max: '250 Gwei',
7
+ min: '1 Gwei',
8
+ },
9
+ 'gasPrice',
10
+ 'ethereumclassic'
11
+ )
@@ -0,0 +1,2 @@
1
+ export { default as ethereum } from './ethereum'
2
+ export { default as ethereumclassic } from './ethereumclassic'
package/src/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import createContract from './create-contract'
2
+ import ABI from './abi'
3
+
4
+ export { createContract, ABI }
5
+ export * from './encode'
6
+ export * from './unsigned-tx'
7
+ export * from './utils'
8
+ export * from './constants'
@@ -0,0 +1,13 @@
1
+ /* @flow */
2
+ import createUnsignedTx from './create-unsigned-tx'
3
+ import signUnsignedTx from './sign-unsigned-tx'
4
+
5
+ import type { ParsedTransaction, SignedTransaction } from '@exodus/models/lib/types'
6
+
7
+ export default function createAndSignTx(
8
+ input: ParsedTransaction,
9
+ privateKey: Buffer
10
+ ): SignedTransaction {
11
+ const unsignedTx = createUnsignedTx(input)
12
+ return signUnsignedTx(unsignedTx, privateKey)
13
+ }
@@ -0,0 +1,62 @@
1
+ import ethUtil from 'ethereumjs-util'
2
+ import { _isEthereumToken, currency2buffer } from '../utils'
3
+ import { CHAIN_IDS } from '../constants'
4
+
5
+ import type { UnsignedTransaction } from '#/app-models'
6
+
7
+ export default function createUnsignedTx({
8
+ baseAsset,
9
+ asset,
10
+ address,
11
+ amount,
12
+ nonce,
13
+ txInput,
14
+ gasLimit,
15
+ gasPrice,
16
+ privateKey,
17
+ fromAddress,
18
+ chainId,
19
+ }): UnsignedTransaction {
20
+ if (txInput) {
21
+ txInput = ethUtil.toBuffer(txInput) // If txInput is already a Buffer, then it is passed through
22
+ } else {
23
+ txInput = Buffer.alloc(0)
24
+ }
25
+
26
+ if (!chainId) chainId = CHAIN_IDS[baseAsset.name] // mainnet
27
+
28
+ const isEthereumToken = _isEthereumToken(asset)
29
+ const to = isEthereumToken ? asset.contract.addresses.current : address
30
+ let value = currency2buffer(isEthereumToken ? baseAsset.currency.ZERO : amount)
31
+
32
+ // TODO: check: present on desktop missing on mobile. This insures we never have a buffer specifying 0.
33
+ // In ETH, a buffer of zero length and a buffer specifying 0 imply different things
34
+ if (value.equals(Buffer.from([0]))) value = Buffer.alloc(0)
35
+
36
+ if (!fromAddress) {
37
+ if (privateKey) fromAddress = ethUtil.bufferToHex(ethUtil.privateToAddress(privateKey))
38
+ else throw new Error('createTx: Must pass fromAddress or privateKey in options')
39
+ }
40
+
41
+ const txData = {
42
+ nonce: nonce === 0 ? Buffer.alloc(0) : ethUtil.intToBuffer(nonce), // mobile: { nonce: ethUtil.intToBuffer(nonce) }
43
+ gasPrice: currency2buffer(gasPrice.toBase()), // mobile: { gasPrice: currency2buffer(gasPrice) }
44
+ gasLimit: ethUtil.intToBuffer(gasLimit),
45
+ to,
46
+ value,
47
+ data: txInput,
48
+ chainId,
49
+ }
50
+
51
+ const txMeta = {
52
+ assetName: asset.name,
53
+ // TODO: We should move away from putting the PK into txMeta, it is a bad practice. It is a potential PK exposure risk if the wrong PK gets included here.
54
+ privateKey, // Used for importing private key
55
+ fee: baseAsset.currency.baseUnit(gasPrice.toBase().toNumber() * gasLimit),
56
+ }
57
+
58
+ return {
59
+ txData,
60
+ txMeta,
61
+ }
62
+ }
@@ -0,0 +1,4 @@
1
+ export { default as createUnsignedTx } from './create-unsigned-tx'
2
+ export { default as parseUnsignedTx } from './parse-unsigned-tx'
3
+ export { default as signUnsignedTx } from './sign-unsigned-tx'
4
+ export { default as createAndSignTx } from './create-and-sign-tx'
@@ -0,0 +1,44 @@
1
+ /* @flow */
2
+ import * as ethUtil from 'ethereumjs-util'
3
+ import assets from '@exodus/assets'
4
+ import { _isEthereumToken, buffer2currency } from '../utils'
5
+ import { CHAIN_IDS } from '../constants'
6
+
7
+ import type { UnsignedTransaction, ParsedTransaction } from '@exodus/models/lib/types'
8
+
9
+ export default function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransaction {
10
+ const {
11
+ txData,
12
+ txMeta: { assetName },
13
+ } = unsignedTx
14
+ const asset = assets[assetName]
15
+ const isEthereumToken = _isEthereumToken(asset)
16
+ const baseAsset = isEthereumToken ? assets.ethereum : asset
17
+
18
+ const gasPrice = buffer2currency({ asset: baseAsset, value: txData.gasPrice })
19
+ const gasLimit = ethUtil.bufferToInt(txData.gasLimit)
20
+
21
+ let { to, chainId, data } = txData
22
+ let amount
23
+ const fee = gasPrice.mul(gasLimit)
24
+ if (isEthereumToken) {
25
+ const parsed = asset.contract.transfer.parse(data)
26
+ to = parsed.to
27
+ amount = parsed.amount
28
+ } else {
29
+ amount = buffer2currency({ asset: baseAsset, value: txData.value })
30
+ }
31
+
32
+ if (chainId !== CHAIN_IDS[baseAsset.name]) {
33
+ throw new Error(`invalid chainId ${chainId} for asset ${assetName}`)
34
+ }
35
+
36
+ return {
37
+ baseAsset,
38
+ asset,
39
+ from: null, // TODO: how?
40
+ to,
41
+ amount,
42
+ fee,
43
+ }
44
+ }
@@ -0,0 +1,19 @@
1
+ /* @flow */
2
+ import EthereumTx from 'ethereumjs-tx'
3
+
4
+ import type { UnsignedTransaction, SignedTransaction } from '@exodus/models/lib/types'
5
+
6
+ export default function signUnsignedTx(
7
+ unsignedTx: UnsignedTransaction,
8
+ privateKey: Buffer
9
+ ): SignedTransaction {
10
+ const { txData } = unsignedTx
11
+
12
+ const tx = new EthereumTx(txData)
13
+ tx.sign(privateKey)
14
+
15
+ // serialize and get txId
16
+ const rawTx = tx.serialize()
17
+ const txId = tx.hash().toString('hex')
18
+ return { rawTx, txId }
19
+ }
package/src/utils.js ADDED
@@ -0,0 +1,28 @@
1
+ import baseX from 'base-x'
2
+ import * as ethUtil from 'ethereumjs-util'
3
+
4
+ const base10 = baseX('0123456789')
5
+ const base16 = baseX('0123456789abcdef')
6
+
7
+ export const _isEthereumToken = (asset) => asset.assetType === 'ETHEREUM_ERC20'
8
+
9
+ export function buffer2currency({ asset, value }) {
10
+ return asset.currency.baseUnit(base10.encode(value)).toDefault()
11
+ }
12
+
13
+ export function currency2buffer(value) {
14
+ const b10Value = value
15
+ .toBase()
16
+ .floor() // probably not necessary, but to be safe
17
+ .toString({ unit: false })
18
+
19
+ // Desktop: const hexValue = value.toBase()._number.toString(16)
20
+ const hexValue = base16.encode(base10.decode(b10Value))
21
+
22
+ if (hexValue.includes('.')) {
23
+ // <-- probably not necessary anymore
24
+ throw new RangeError(`${value.toBase().toString()} can not be converted to Buffer`)
25
+ }
26
+
27
+ return Buffer.from(ethUtil.padToEven(hexValue), 'hex')
28
+ }