@exodus/bitcoin-api 2.3.13 → 2.3.15
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/package.json +2 -2
- package/src/move-funds.js +45 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoin-api",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.15",
|
|
4
4
|
"description": "Exodus bitcoin-api",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"@exodus/bitcoin-meta": "^1.0.1",
|
|
42
42
|
"jest-when": "^3.5.1"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "90be61265b73fc6f3238604aea72368cf684faa5"
|
|
45
45
|
}
|
package/src/move-funds.js
CHANGED
|
@@ -4,26 +4,39 @@ import { createInputs, createOutput, getNonWitnessTxs } from './tx-send'
|
|
|
4
4
|
import assert from 'minimalistic-assert'
|
|
5
5
|
import secp256k1 from 'secp256k1'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const isValidPrivateKey = (privateKey) => {
|
|
8
|
+
try {
|
|
9
|
+
wif.decode(privateKey)
|
|
10
|
+
return true
|
|
11
|
+
} catch (err) {
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const wifToPublicKey = ({ coinInfo, privateKeyWIF }) => {
|
|
8
17
|
assert(coinInfo, 'coinInfo is required')
|
|
9
18
|
assert(privateKeyWIF, 'privateKeyWIF is required')
|
|
10
19
|
const { versions } = coinInfo
|
|
11
20
|
|
|
12
21
|
const { privateKey, compressed } = wif.decode(privateKeyWIF, versions.private)
|
|
13
|
-
return secp256k1.publicKeyCreate(privateKey, compressed)
|
|
22
|
+
return { compressed, publicKey: secp256k1.publicKeyCreate(privateKey, compressed) }
|
|
14
23
|
}
|
|
15
|
-
|
|
16
24
|
export const getAddressesFromPrivateKeyFactory = ({ purposes, keys, coinInfo }) => {
|
|
17
25
|
assert(purposes, 'purposes is required')
|
|
18
26
|
assert(keys, 'keys is required')
|
|
19
27
|
assert(coinInfo, 'coinInfo is required')
|
|
28
|
+
|
|
20
29
|
return ({ privateKey }) => {
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
if (!isValidPrivateKey(privateKey)) {
|
|
31
|
+
return { invalid: true }
|
|
32
|
+
}
|
|
33
|
+
const { publicKey, compressed } = wifToPublicKey({ coinInfo, privateKeyWIF: privateKey })
|
|
34
|
+
const addresses = purposes.map((purpose) =>
|
|
23
35
|
keys.encodePublic(purpose === 49 ? secp256k1.publicKeyConvert(publicKey, true) : publicKey, {
|
|
24
36
|
purpose,
|
|
25
37
|
})
|
|
26
38
|
)
|
|
39
|
+
return { addresses, compressed }
|
|
27
40
|
}
|
|
28
41
|
}
|
|
29
42
|
|
|
@@ -44,6 +57,7 @@ export const moveFundsFactory = ({
|
|
|
44
57
|
signTx,
|
|
45
58
|
address,
|
|
46
59
|
getAddressesFromPrivateKey,
|
|
60
|
+
shouldExcludeVoutUtxo = () => false,
|
|
47
61
|
}) => {
|
|
48
62
|
assert(asset, 'asset is required')
|
|
49
63
|
assert(insightClient, 'insightClient is required')
|
|
@@ -51,6 +65,7 @@ export const moveFundsFactory = ({
|
|
|
51
65
|
assert(address, 'address is required')
|
|
52
66
|
assert(signTx, 'signTx is required')
|
|
53
67
|
assert(getAddressesFromPrivateKey, 'getAddressesFromPrivateKey is required')
|
|
68
|
+
assert(typeof shouldExcludeVoutUtxo === 'function', 'shouldExcludeVoutUtxo must be a function')
|
|
54
69
|
|
|
55
70
|
async function prepareSendFundsTx({
|
|
56
71
|
assetName,
|
|
@@ -73,21 +88,31 @@ export const moveFundsFactory = ({
|
|
|
73
88
|
// WIF format private key
|
|
74
89
|
const privateKey = input
|
|
75
90
|
|
|
76
|
-
|
|
91
|
+
const { addresses, compressed, invalid } = getAddressesFromPrivateKey({
|
|
92
|
+
privateKey,
|
|
93
|
+
formatProps,
|
|
94
|
+
MoveFundsError,
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (invalid) {
|
|
77
98
|
throw new MoveFundsError('private-key-invalid', formatProps)
|
|
78
99
|
}
|
|
79
100
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
101
|
+
const receiveAddresses = (
|
|
102
|
+
await assetClientInterface.getReceiveAddresses({
|
|
103
|
+
walletAccount,
|
|
104
|
+
assetName,
|
|
105
|
+
multiAddressMode: true,
|
|
106
|
+
})
|
|
107
|
+
).map(
|
|
108
|
+
(receiveAddress) =>
|
|
109
|
+
address.toLegacyAddress?.(receiveAddress.toString()) || receiveAddress.toString()
|
|
110
|
+
)
|
|
88
111
|
|
|
89
112
|
const findFromAddress = async () => {
|
|
90
|
-
for (const
|
|
113
|
+
for (const originalCurrentAddress of addresses) {
|
|
114
|
+
const currentAddress =
|
|
115
|
+
address.toLegacyAddress?.(originalCurrentAddress) || originalCurrentAddress
|
|
91
116
|
const selfSend = receiveAddresses.some(
|
|
92
117
|
(receiveAddress) => String(receiveAddress) === String(currentAddress)
|
|
93
118
|
)
|
|
@@ -95,7 +120,8 @@ export const moveFundsFactory = ({
|
|
|
95
120
|
throw new MoveFundsError('private-key-own-key', formatProps)
|
|
96
121
|
}
|
|
97
122
|
|
|
98
|
-
const
|
|
123
|
+
const collectedUtxos = await getUtxos({ asset, address: currentAddress })
|
|
124
|
+
const utxos = collectedUtxos.filter((utxo) => !shouldExcludeVoutUtxo({ output: utxo }))
|
|
99
125
|
|
|
100
126
|
if (!utxos.value.isZero) {
|
|
101
127
|
return { fromAddress: currentAddress, utxos }
|
|
@@ -121,7 +147,9 @@ export const moveFundsFactory = ({
|
|
|
121
147
|
const unsignedTx = {
|
|
122
148
|
txData: {
|
|
123
149
|
inputs: createInputs(assetName, utxos.toArray()),
|
|
124
|
-
outputs: [
|
|
150
|
+
outputs: [
|
|
151
|
+
createOutput(assetName, address.toLegacyAddress?.(toAddress) || toAddress, amount),
|
|
152
|
+
],
|
|
125
153
|
},
|
|
126
154
|
txMeta: {
|
|
127
155
|
addressPathsMap: utxos.getAddressPathsMap(),
|
|
@@ -188,15 +216,6 @@ export const moveFundsFactory = ({
|
|
|
188
216
|
return { fee, sizeKB }
|
|
189
217
|
}
|
|
190
218
|
|
|
191
|
-
function isValidPrivateKey(privateKey) {
|
|
192
|
-
try {
|
|
193
|
-
wif.decode(privateKey)
|
|
194
|
-
return true
|
|
195
|
-
} catch (err) {
|
|
196
|
-
return false
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
219
|
return {
|
|
201
220
|
prepareSendFundsTx,
|
|
202
221
|
sendFunds,
|