@exodus/bitcoin-api 2.20.1 → 2.21.1
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/CHANGELOG.md +24 -0
- package/package.json +4 -4
- package/src/fee/utxo-selector.js +2 -2
- package/src/index.js +2 -0
- package/src/move-funds.js +5 -1
- package/src/psbt-utils.js +61 -0
- package/src/tx-log/bitcoin-monitor.js +6 -0
- package/src/tx-send/batch-tx.js +206 -0
- package/src/tx-send/index.js +13 -5
- package/src/tx-sign/default-entropy.cjs +6 -0
- package/src/tx-sign/taproot.js +5 -3
- package/src/tx-sign/default-entropy.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.21.1](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.21.0...@exodus/bitcoin-api@2.21.1) (2024-07-24)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* bump @exodus/bip322-js to remove warning ([#2929](https://github.com/ExodusMovement/assets/issues/2929)) ([74c20ad](https://github.com/ExodusMovement/assets/commit/74c20ad32ebed2df4eb0f498d11b7319e80b037a))
|
|
12
|
+
* retrieve `multiAddressMode` from config ([#2944](https://github.com/ExodusMovement/assets/issues/2944)) ([6bd70fb](https://github.com/ExodusMovement/assets/commit/6bd70fbc9e9ce6343ebf6bc8303bf13741cff307))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## [2.21.0](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.20.1...@exodus/bitcoin-api@2.21.0) (2024-07-19)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **BTC:** create batch tx from array of recipients ([#2881](https://github.com/ExodusMovement/assets/issues/2881)) ([440d5d5](https://github.com/ExodusMovement/assets/commit/440d5d5879c902ef10ff7644c92a5092bb868872))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* **bitcoin-api:** stop ws connection on monitor stop ([#2851](https://github.com/ExodusMovement/assets/issues/2851)) ([e52f4c2](https://github.com/ExodusMovement/assets/commit/e52f4c23e7635cc3116c876ad35fbbab4a70c32b))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
6
30
|
## [2.20.1](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.20.0...@exodus/bitcoin-api@2.20.1) (2024-07-15)
|
|
7
31
|
|
|
8
32
|
**Note:** Version bump only for package @exodus/bitcoin-api
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoin-api",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.21.1",
|
|
4
4
|
"description": "Exodus bitcoin-api",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
"access": "restricted"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"test": "run -T jest",
|
|
17
|
+
"test": "run -T exodus-test --jest --esbuild",
|
|
18
18
|
"lint": "run -T eslint .",
|
|
19
19
|
"lint:fix": "yarn lint --fix"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@exodus/asset-lib": "^4.1.0",
|
|
23
23
|
"@exodus/basic-utils": "^2.1.0",
|
|
24
|
-
"@exodus/bip322-js": "^1.1.0-exodus.
|
|
24
|
+
"@exodus/bip322-js": "^1.1.0-exodus.6",
|
|
25
25
|
"@exodus/bip44-constants": "^195.0.0",
|
|
26
26
|
"@exodus/bitcoin-lib": "^2.4.1",
|
|
27
27
|
"@exodus/bitcoinjs-lib": "^6.1.5-exodus.2",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"type": "git",
|
|
67
67
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "3878129a053ebf9877c9d601858b8b2f2c7be70f"
|
|
70
70
|
}
|
package/src/fee/utxo-selector.js
CHANGED
|
@@ -27,6 +27,7 @@ export const selectUtxos = ({
|
|
|
27
27
|
amount,
|
|
28
28
|
feeRate,
|
|
29
29
|
receiveAddress, // it could be null
|
|
30
|
+
receiveAddresses = [],
|
|
30
31
|
isSendAll,
|
|
31
32
|
getFeeEstimator,
|
|
32
33
|
disableReplacement = false,
|
|
@@ -44,10 +45,9 @@ export const selectUtxos = ({
|
|
|
44
45
|
inscriptionIds,
|
|
45
46
|
})
|
|
46
47
|
|
|
47
|
-
const receiveAddresses = []
|
|
48
48
|
if (inscriptionIds) {
|
|
49
49
|
receiveAddresses.push(...inscriptionIds.map(() => resolvedReceiveAddresses))
|
|
50
|
-
} else {
|
|
50
|
+
} else if (receiveAddresses.length === 0) {
|
|
51
51
|
receiveAddresses.push(resolvedReceiveAddresses)
|
|
52
52
|
}
|
|
53
53
|
|
package/src/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export * from './utxos-utils'
|
|
|
14
14
|
export * from './tx-log'
|
|
15
15
|
export * from './unconfirmed-ancestor-data'
|
|
16
16
|
export * from './parse-unsigned-tx'
|
|
17
|
+
export { getCreateBatchTransaction } from './tx-send/batch-tx'
|
|
18
|
+
export { createPsbtToUnsignedTx } from './psbt-utils'
|
|
17
19
|
export * from './insight-api-client/util'
|
|
18
20
|
export * from './move-funds'
|
|
19
21
|
export { createEncodeMultisigContract } from './multisig-address'
|
package/src/move-funds.js
CHANGED
|
@@ -97,10 +97,14 @@ export const moveFundsFactory = ({
|
|
|
97
97
|
throw new MoveFundsError('private-key-invalid', formatProps)
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
const config = await assetClientInterface.getAssetConfig({
|
|
101
|
+
assetName,
|
|
102
|
+
walletAccount,
|
|
103
|
+
})
|
|
100
104
|
const recieveAddressesObjects = await assetClientInterface.getReceiveAddresses({
|
|
101
105
|
walletAccount,
|
|
102
106
|
assetName,
|
|
103
|
-
multiAddressMode: true,
|
|
107
|
+
multiAddressMode: config.multiAddressMode ?? true,
|
|
104
108
|
})
|
|
105
109
|
|
|
106
110
|
const receiveAddresses = recieveAddressesObjects.map(
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import BipPath from 'bip32-path'
|
|
2
|
+
import lodash from 'lodash'
|
|
3
|
+
|
|
4
|
+
export const createPsbtToUnsignedTx =
|
|
5
|
+
({ assetClientInterface, assetName }) =>
|
|
6
|
+
async ({ psbt, walletAccount, purpose = 86 }) => {
|
|
7
|
+
const addressPathsMap = {}
|
|
8
|
+
const inputsToSign = []
|
|
9
|
+
|
|
10
|
+
const addressOpts = {
|
|
11
|
+
walletAccount: walletAccount.toString(),
|
|
12
|
+
assetName,
|
|
13
|
+
purpose,
|
|
14
|
+
chainIndex: 0,
|
|
15
|
+
addressIndex: 0,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Need to have all input derivations
|
|
19
|
+
for (const i of lodash.range(psbt.inputCount)) {
|
|
20
|
+
const input = psbt.data.inputs[i]
|
|
21
|
+
|
|
22
|
+
const derivation = input.tapBip32Derivation
|
|
23
|
+
if (!derivation) {
|
|
24
|
+
throw new Error('Invalid input in psbt, no derivation for input found')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const [chainIndex, addressIndex] = BipPath.fromString(derivation[0].path).toPathArray()
|
|
28
|
+
|
|
29
|
+
addressOpts.chainIndex = chainIndex
|
|
30
|
+
addressOpts.addressIndex = addressIndex
|
|
31
|
+
|
|
32
|
+
const address = await assetClientInterface.getAddress(addressOpts)
|
|
33
|
+
|
|
34
|
+
addressPathsMap[address.toString()] = derivation[0].path
|
|
35
|
+
inputsToSign.push({ address: address.toString() })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// If we have output derivations then it's our change
|
|
39
|
+
for (const i of lodash.range(psbt.txOutputs.length)) {
|
|
40
|
+
const output = psbt.data.outputs[i]
|
|
41
|
+
|
|
42
|
+
const derivation = output.tapBip32Derivation
|
|
43
|
+
if (!derivation) continue
|
|
44
|
+
const [chainIndex, addressIndex] = BipPath.fromString(derivation[0].path).toPathArray()
|
|
45
|
+
|
|
46
|
+
addressOpts.chainIndex = chainIndex
|
|
47
|
+
addressOpts.addressIndex = addressIndex
|
|
48
|
+
const address = await assetClientInterface.getAddress(addressOpts)
|
|
49
|
+
|
|
50
|
+
addressPathsMap[address.toString()] = derivation[0].path
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
txData: { psbtBuffer: psbt.toBuffer() },
|
|
55
|
+
txMeta: {
|
|
56
|
+
addressPathsMap,
|
|
57
|
+
inputsToSign,
|
|
58
|
+
accountIndex: walletAccount.index,
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -62,6 +62,12 @@ export class Monitor extends BaseMonitor {
|
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
this.addHook('after-tick-multiple-wallet-accounts', () => this.#subscribeToNewAddresses())
|
|
65
|
+
this.addHook('before-stop', () => {
|
|
66
|
+
if (this.#ws) {
|
|
67
|
+
this.#ws.close()
|
|
68
|
+
this.#ws = null
|
|
69
|
+
}
|
|
70
|
+
})
|
|
65
71
|
this.addHook('after-stop', async () =>
|
|
66
72
|
Promise.all(Object.keys(this.#runningByWalletAccount).map(this.#waitForWalletToFinish))
|
|
67
73
|
)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import BIP32 from '@exodus/bip32'
|
|
3
|
+
import { Psbt } from '@exodus/bitcoinjs-lib'
|
|
4
|
+
import BipPath from 'bip32-path'
|
|
5
|
+
// Using this notation so it can be mocked by jest
|
|
6
|
+
import doShuffle from 'lodash/shuffle'
|
|
7
|
+
import assert from 'minimalistic-assert'
|
|
8
|
+
|
|
9
|
+
import { selectUtxos } from '../fee/utxo-selector'
|
|
10
|
+
import { getUnconfirmedTxAncestorMap } from '../unconfirmed-ancestor-data'
|
|
11
|
+
import { getUsableUtxos, getUtxos } from '../utxos-utils'
|
|
12
|
+
|
|
13
|
+
const DUST_VALUES = {
|
|
14
|
+
P2WPKH: 294,
|
|
15
|
+
P2TR: 330,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const getCreateBatchTransaction = ({
|
|
19
|
+
getFeeEstimator,
|
|
20
|
+
assetClientInterface,
|
|
21
|
+
changeAddressType,
|
|
22
|
+
}) => {
|
|
23
|
+
assert(assetClientInterface, `assetClientInterface must be supplied in sendTx`)
|
|
24
|
+
|
|
25
|
+
return async ({ assetName, walletAccount, recipients, options = {} }) => {
|
|
26
|
+
const stuff = await assetClientInterface.getAssetsForNetwork({ baseAssetName: assetName })
|
|
27
|
+
const asset = stuff[assetName]
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
feeData = await assetClientInterface.getFeeConfig({ assetName }),
|
|
31
|
+
taprootInputWitnessSize,
|
|
32
|
+
} = options
|
|
33
|
+
|
|
34
|
+
const accountState = await assetClientInterface.getAccountState({ assetName, walletAccount })
|
|
35
|
+
|
|
36
|
+
const txSet = await assetClientInterface.getTxLog({ assetName, walletAccount })
|
|
37
|
+
const unconfirmedTxAncestor = getUnconfirmedTxAncestorMap({ accountState })
|
|
38
|
+
const usableUtxos = getUsableUtxos({
|
|
39
|
+
asset,
|
|
40
|
+
utxos: getUtxos({ accountState, asset }),
|
|
41
|
+
feeData,
|
|
42
|
+
txSet,
|
|
43
|
+
unconfirmedTxAncestor,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const amount = recipients.reduce((acc, curr) => acc.add(curr.amount), asset.currency.ZERO)
|
|
47
|
+
const receiveAddresses = recipients.map((recipient) => recipient.address)
|
|
48
|
+
|
|
49
|
+
const { selectedUtxos, fee } = selectUtxos({
|
|
50
|
+
asset,
|
|
51
|
+
usableUtxos,
|
|
52
|
+
amount,
|
|
53
|
+
feeRate: feeData.feePerKB,
|
|
54
|
+
receiveAddresses,
|
|
55
|
+
getFeeEstimator: (asset, { feePerKB, ...options }) =>
|
|
56
|
+
getFeeEstimator(asset, feePerKB, options),
|
|
57
|
+
unconfirmedTxAncestor,
|
|
58
|
+
taprootInputWitnessSize,
|
|
59
|
+
changeAddressType,
|
|
60
|
+
allowUnconfirmedRbfEnabledUtxos: false,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
if (!selectedUtxos) throw new Error('Not enough funds.')
|
|
64
|
+
|
|
65
|
+
const addressPathsMap = selectedUtxos.getAddressPathsMap()
|
|
66
|
+
|
|
67
|
+
const psbt = new Psbt({ network: asset.coinInfo.toBitcoinJS() })
|
|
68
|
+
|
|
69
|
+
for (const utxo of doShuffle(selectedUtxos.toArray())) {
|
|
70
|
+
const path = addressPathsMap[utxo.address]
|
|
71
|
+
if (!path) {
|
|
72
|
+
throw new Error(`Path missing for input address ${utxo.address}`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const [chainIndex, addressIndex] = BipPath.fromString(path).toPathArray()
|
|
76
|
+
const addressOpts = {
|
|
77
|
+
walletAccount,
|
|
78
|
+
assetName,
|
|
79
|
+
chainIndex: 0,
|
|
80
|
+
addressIndex: 0,
|
|
81
|
+
}
|
|
82
|
+
addressOpts.chainIndex = chainIndex
|
|
83
|
+
addressOpts.addressIndex = addressIndex
|
|
84
|
+
addressOpts.purpose = utxo.address.meta.purpose
|
|
85
|
+
|
|
86
|
+
const [address, xpub] = await Promise.all([
|
|
87
|
+
assetClientInterface.getAddress(addressOpts),
|
|
88
|
+
assetClientInterface.getExtendedPublicKey(addressOpts),
|
|
89
|
+
])
|
|
90
|
+
assert(String(address) === String(utxo.address))
|
|
91
|
+
|
|
92
|
+
const hdkey = BIP32.fromXPub(xpub)
|
|
93
|
+
const masterFingerprint = Buffer.alloc(4)
|
|
94
|
+
masterFingerprint.writeUint32BE(hdkey.fingerprint)
|
|
95
|
+
|
|
96
|
+
const input = {
|
|
97
|
+
hash: utxo.txId,
|
|
98
|
+
index: utxo.vout,
|
|
99
|
+
witnessUtxo: {
|
|
100
|
+
value: parseInt(utxo.value.toBaseString(), 10),
|
|
101
|
+
script: Buffer.from(utxo.script, 'hex'),
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (address.meta.spendingInfo) {
|
|
106
|
+
const { witness, redeem } = address.meta.spendingInfo
|
|
107
|
+
input.tapLeafScript = [
|
|
108
|
+
{
|
|
109
|
+
leafVersion: redeem.redeemVersion,
|
|
110
|
+
script: redeem.output,
|
|
111
|
+
controlBlock: witness[witness.length - 1],
|
|
112
|
+
},
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
psbt.addInput(input)
|
|
117
|
+
|
|
118
|
+
const pubkey = hdkey.derive(path).publicKey.slice(1)
|
|
119
|
+
const index = psbt.data.inputs.length - 1
|
|
120
|
+
psbt.data.inputs[index].tapBip32Derivation = [
|
|
121
|
+
{
|
|
122
|
+
path,
|
|
123
|
+
leafHashes: [],
|
|
124
|
+
masterFingerprint,
|
|
125
|
+
pubkey,
|
|
126
|
+
},
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const change = selectedUtxos.value.sub(amount).sub(fee)
|
|
131
|
+
if (change.gte(asset.currency.baseUnit(DUST_VALUES[changeAddressType]))) {
|
|
132
|
+
const changeAddress = await assetClientInterface.getNextChangeAddress({
|
|
133
|
+
assetName,
|
|
134
|
+
walletAccount,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const output = { address: String(changeAddress), amount: change }
|
|
138
|
+
|
|
139
|
+
const path = changeAddress.meta.path
|
|
140
|
+
|
|
141
|
+
const xpub = await assetClientInterface.getExtendedPublicKey({ walletAccount, assetName })
|
|
142
|
+
const hdkey = BIP32.fromXPub(xpub)
|
|
143
|
+
const masterFingerprint = Buffer.alloc(4)
|
|
144
|
+
masterFingerprint.writeUint32BE(hdkey.fingerprint)
|
|
145
|
+
|
|
146
|
+
const pubkey = hdkey.derive(path).publicKey.slice(1)
|
|
147
|
+
output.tapBip32Derivation = [
|
|
148
|
+
{
|
|
149
|
+
path,
|
|
150
|
+
leafHashes: [],
|
|
151
|
+
masterFingerprint,
|
|
152
|
+
pubkey,
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
recipients.push(output)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const recipient of doShuffle(recipients)) {
|
|
160
|
+
psbt.addOutput({
|
|
161
|
+
address: recipient.address,
|
|
162
|
+
value: parseInt(recipient.amount.toBaseString(), 10),
|
|
163
|
+
unknownKeyVals: [],
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const index = psbt.data.outputs.length - 1
|
|
167
|
+
if (recipient.tapBip32Derivation) {
|
|
168
|
+
psbt.data.outputs[index].tapBip32Derivation = recipient.tapBip32Derivation
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (recipient.name) {
|
|
172
|
+
psbt.data.outputs[index].unknownKeyVals.push({
|
|
173
|
+
key: Buffer.from('name', 'utf8'),
|
|
174
|
+
value: Buffer.from(recipient.name, 'utf8'),
|
|
175
|
+
})
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (recipient.email) {
|
|
179
|
+
psbt.data.outputs[index].unknownKeyVals.push({
|
|
180
|
+
key: Buffer.from('email', 'utf8'),
|
|
181
|
+
value: Buffer.from(recipient.email, 'utf8'),
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (recipient.description) {
|
|
186
|
+
psbt.data.outputs[index].unknownKeyVals.push({
|
|
187
|
+
key: Buffer.from('description', 'utf8'),
|
|
188
|
+
value: Buffer.from(recipient.description, 'utf8'),
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (recipient.fiatAmount) {
|
|
193
|
+
psbt.data.outputs[index].unknownKeyVals.push({
|
|
194
|
+
key: Buffer.from('fiatAmount', 'utf8'),
|
|
195
|
+
value: Buffer.from(recipient.fiatAmount.toDefaultString(), 'utf8'),
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const blockHeight = await asset.baseAsset.insightClient.fetchBlockHeight()
|
|
201
|
+
|
|
202
|
+
psbt.setLocktime(blockHeight)
|
|
203
|
+
|
|
204
|
+
return psbt
|
|
205
|
+
}
|
|
206
|
+
}
|
package/src/tx-send/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import assert from 'minimalistic-assert'
|
|
2
|
-
|
|
3
|
-
import doShuffle from 'lodash/shuffle'
|
|
2
|
+
import lodash from 'lodash'
|
|
4
3
|
|
|
5
4
|
import { UtxoCollection, Address } from '@exodus/models'
|
|
6
5
|
import { retry } from '@exodus/simple-retry'
|
|
@@ -268,7 +267,8 @@ export const getPrepareSendTransaction =
|
|
|
268
267
|
)
|
|
269
268
|
|
|
270
269
|
const shuffle = (list) => {
|
|
271
|
-
|
|
270
|
+
// Using full lodash.shuffle notation so it can be mocked with spyOn in tests
|
|
271
|
+
return inscriptionIds ? list : lodash.shuffle(list) // don't shuffle when sending ordinal!!!!
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
assert(
|
|
@@ -335,7 +335,11 @@ export const getPrepareSendTransaction =
|
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
const sendAmount = bumpTxId || transferOrdinalsUtxos ? asset.currency.ZERO : amount
|
|
338
|
-
const receiveAddress = bumpTxId
|
|
338
|
+
const receiveAddress = bumpTxId
|
|
339
|
+
? replaceableTxs.length > 0
|
|
340
|
+
? null
|
|
341
|
+
: changeAddressType
|
|
342
|
+
: address
|
|
339
343
|
const feeRate = feeData.feePerKB
|
|
340
344
|
const resolvedIsSendAll = (!rbfEnabled && feePerKB) || transferOrdinalsUtxos ? false : isSendAll
|
|
341
345
|
|
|
@@ -631,10 +635,14 @@ export const createAndBroadcastTXFactory =
|
|
|
631
635
|
},
|
|
632
636
|
})
|
|
633
637
|
|
|
638
|
+
const config = await assetClientInterface.getAssetConfig({
|
|
639
|
+
assetName,
|
|
640
|
+
walletAccount,
|
|
641
|
+
})
|
|
634
642
|
const walletAddressObjects = await assetClientInterface.getReceiveAddresses({
|
|
635
643
|
walletAccount,
|
|
636
644
|
assetName,
|
|
637
|
-
multiAddressMode: true,
|
|
645
|
+
multiAddressMode: config.multiAddressMode ?? true,
|
|
638
646
|
})
|
|
639
647
|
// There are two cases of bumping, replacing or chaining a self-send.
|
|
640
648
|
// If we have a bumpTxId, but we aren't replacing, then it is a self-send.
|
package/src/tx-sign/taproot.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { crypto } from '@exodus/bitcoinjs-lib'
|
|
2
2
|
import assert from 'minimalistic-assert'
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import defaultEntropy from './default-entropy.cjs'
|
|
5
5
|
import { ecc } from '../bitcoinjs-lib/ecc'
|
|
6
6
|
import { getECPair } from '../bitcoinjs-lib'
|
|
7
7
|
|
|
@@ -59,7 +59,8 @@ export function toAsyncSigner({ keyPair, isTaprootKeySpend, network }) {
|
|
|
59
59
|
|
|
60
60
|
// eslint-disable-next-line @exodus/mutable/no-param-reassign-prop-only
|
|
61
61
|
keyPair.signSchnorr = async (h) => {
|
|
62
|
-
|
|
62
|
+
// defaultEntropy.getSchnorrEntropy() is mockable with jest.spyOn
|
|
63
|
+
const sig = ecc.signSchnorr(h, keyPair.privateKey, defaultEntropy.getSchnorrEntropy())
|
|
63
64
|
return Buffer.from(sig)
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -94,7 +95,8 @@ export async function toAsyncBufferSigner({ signer, purpose, keyId, isTaprootKey
|
|
|
94
95
|
keyId,
|
|
95
96
|
signatureType: 'schnorr',
|
|
96
97
|
tweak,
|
|
97
|
-
|
|
98
|
+
// defaultEntropy.getSchnorrEntropy() is mockable with jest.spyOn
|
|
99
|
+
extraEntropy: defaultEntropy.getSchnorrEntropy(),
|
|
98
100
|
})
|
|
99
101
|
},
|
|
100
102
|
publicKey,
|