@atomiqlabs/sdk 8.6.4 → 8.6.6
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/dist/SmartChainAssets.d.ts +181 -181
- package/dist/SmartChainAssets.js +181 -181
- package/dist/bitcoin/coinselect2/accumulative.d.ts +6 -6
- package/dist/bitcoin/coinselect2/accumulative.js +51 -52
- package/dist/bitcoin/coinselect2/blackjack.d.ts +6 -6
- package/dist/bitcoin/coinselect2/blackjack.js +37 -38
- package/dist/bitcoin/coinselect2/index.d.ts +17 -19
- package/dist/bitcoin/coinselect2/index.js +69 -69
- package/dist/bitcoin/coinselect2/utils.d.ts +75 -77
- package/dist/bitcoin/coinselect2/utils.js +123 -123
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +128 -130
- package/dist/bitcoin/wallet/BitcoinWallet.js +322 -322
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +78 -78
- package/dist/bitcoin/wallet/IBitcoinWallet.js +20 -21
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +99 -101
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +176 -176
- package/dist/enums/FeeType.d.ts +15 -15
- package/dist/enums/FeeType.js +19 -19
- package/dist/enums/SwapAmountType.d.ts +15 -15
- package/dist/enums/SwapAmountType.js +19 -19
- package/dist/enums/SwapDirection.d.ts +15 -15
- package/dist/enums/SwapDirection.js +19 -19
- package/dist/enums/SwapSide.d.ts +15 -15
- package/dist/enums/SwapSide.js +19 -19
- package/dist/enums/SwapType.d.ts +75 -75
- package/dist/enums/SwapType.js +79 -79
- package/dist/errors/IntermediaryError.d.ts +13 -13
- package/dist/errors/IntermediaryError.js +27 -27
- package/dist/errors/RequestError.d.ts +32 -32
- package/dist/errors/RequestError.js +54 -54
- package/dist/errors/UserError.d.ts +8 -8
- package/dist/errors/UserError.js +16 -16
- package/dist/events/UnifiedSwapEventListener.d.ts +23 -23
- package/dist/events/UnifiedSwapEventListener.js +130 -130
- package/dist/http/HttpUtils.d.ts +27 -27
- package/dist/http/HttpUtils.js +90 -91
- package/dist/http/paramcoders/IParamReader.d.ts +8 -8
- package/dist/http/paramcoders/IParamReader.js +2 -2
- package/dist/http/paramcoders/ParamDecoder.d.ts +42 -44
- package/dist/http/paramcoders/ParamDecoder.js +137 -137
- package/dist/http/paramcoders/ParamEncoder.d.ts +18 -20
- package/dist/http/paramcoders/ParamEncoder.js +36 -36
- package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -26
- package/dist/http/paramcoders/SchemaVerifier.js +145 -145
- package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -11
- package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -57
- package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +11 -13
- package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -26
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +16 -16
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +173 -174
- package/dist/index.d.ts +85 -85
- package/dist/index.js +158 -158
- package/dist/intermediaries/Intermediary.d.ts +157 -157
- package/dist/intermediaries/Intermediary.js +142 -142
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +198 -199
- package/dist/intermediaries/IntermediaryDiscovery.js +406 -406
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +437 -438
- package/dist/intermediaries/apis/IntermediaryAPI.js +603 -602
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +155 -155
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +137 -137
- package/dist/lnurl/LNURL.d.ts +102 -102
- package/dist/lnurl/LNURL.js +321 -321
- package/dist/prices/RedundantSwapPrice.d.ts +110 -110
- package/dist/prices/RedundantSwapPrice.js +222 -222
- package/dist/prices/SingleSwapPrice.d.ts +34 -34
- package/dist/prices/SingleSwapPrice.js +44 -44
- package/dist/prices/SwapPriceWithChain.d.ts +107 -107
- package/dist/prices/SwapPriceWithChain.js +128 -128
- package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -28
- package/dist/prices/abstract/ICachedSwapPrice.js +62 -62
- package/dist/prices/abstract/IPriceProvider.d.ts +81 -81
- package/dist/prices/abstract/IPriceProvider.js +74 -74
- package/dist/prices/abstract/ISwapPrice.d.ts +168 -166
- package/dist/prices/abstract/ISwapPrice.js +279 -267
- package/dist/prices/providers/BinancePriceProvider.d.ts +23 -23
- package/dist/prices/providers/BinancePriceProvider.js +30 -30
- package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +23 -23
- package/dist/prices/providers/CoinGeckoPriceProvider.js +29 -29
- package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +25 -25
- package/dist/prices/providers/CoinPaprikaPriceProvider.js +29 -29
- package/dist/prices/providers/CustomPriceProvider.d.ts +24 -24
- package/dist/prices/providers/CustomPriceProvider.js +35 -35
- package/dist/prices/providers/KrakenPriceProvider.d.ts +38 -38
- package/dist/prices/providers/KrakenPriceProvider.js +45 -45
- package/dist/prices/providers/OKXPriceProvider.d.ts +34 -34
- package/dist/prices/providers/OKXPriceProvider.js +29 -29
- package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +17 -17
- package/dist/prices/providers/abstract/ExchangePriceProvider.js +21 -21
- package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -7
- package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -12
- package/dist/storage/IUnifiedStorage.d.ts +85 -85
- package/dist/storage/IUnifiedStorage.js +2 -2
- package/dist/storage/UnifiedSwapStorage.d.ts +114 -114
- package/dist/storage/UnifiedSwapStorage.js +116 -116
- package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +63 -63
- package/dist/storage-browser/IndexedDBUnifiedStorage.js +298 -298
- package/dist/storage-browser/LocalStorageManager.d.ts +49 -49
- package/dist/storage-browser/LocalStorageManager.js +93 -93
- package/dist/swapper/Swapper.d.ts +686 -687
- package/dist/swapper/Swapper.js +1603 -1603
- package/dist/swapper/SwapperFactory.d.ts +135 -135
- package/dist/swapper/SwapperFactory.js +162 -162
- package/dist/swapper/SwapperUtils.d.ts +200 -200
- package/dist/swapper/SwapperUtils.js +467 -467
- package/dist/swapper/SwapperWithChain.d.ts +404 -404
- package/dist/swapper/SwapperWithChain.js +469 -469
- package/dist/swapper/SwapperWithSigner.d.ts +322 -322
- package/dist/swapper/SwapperWithSigner.js +318 -318
- package/dist/swaps/IAddressSwap.d.ts +22 -22
- package/dist/swaps/IAddressSwap.js +13 -14
- package/dist/swaps/IBTCWalletSwap.d.ts +73 -73
- package/dist/swaps/IBTCWalletSwap.js +17 -18
- package/dist/swaps/IClaimableSwap.d.ts +49 -49
- package/dist/swaps/IClaimableSwap.js +14 -15
- package/dist/swaps/IClaimableSwapWrapper.d.ts +15 -15
- package/dist/swaps/IClaimableSwapWrapper.js +2 -2
- package/dist/swaps/IRefundableSwap.d.ts +43 -43
- package/dist/swaps/IRefundableSwap.js +13 -14
- package/dist/swaps/ISwap.d.ts +386 -387
- package/dist/swaps/ISwap.js +346 -341
- package/dist/swaps/ISwapWithGasDrop.d.ts +21 -21
- package/dist/swaps/ISwapWithGasDrop.js +11 -12
- package/dist/swaps/ISwapWrapper.d.ts +283 -284
- package/dist/swaps/ISwapWrapper.js +353 -353
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +98 -98
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +126 -126
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +133 -135
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +169 -169
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +114 -115
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +134 -134
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +98 -101
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +130 -130
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +162 -162
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +190 -190
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +58 -58
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +78 -78
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +529 -531
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +1285 -1285
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +181 -184
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +418 -417
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +581 -583
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +1371 -1371
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +225 -228
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +506 -506
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +458 -458
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +1126 -1126
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +190 -191
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +378 -377
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +403 -403
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +924 -924
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +62 -62
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +112 -112
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +125 -127
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +256 -256
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +241 -242
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +520 -520
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +73 -73
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +155 -155
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +127 -128
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +278 -278
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +630 -630
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1443 -1443
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +213 -207
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +756 -755
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +261 -261
- package/dist/swaps/trusted/ln/LnForGasSwap.js +511 -511
- package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +40 -40
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +82 -82
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +342 -342
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +715 -715
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +68 -69
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +92 -92
- package/dist/types/AmountData.d.ts +10 -10
- package/dist/types/AmountData.js +2 -2
- package/dist/types/CustomPriceFunction.d.ts +11 -11
- package/dist/types/CustomPriceFunction.js +2 -2
- package/dist/types/PriceInfoType.d.ts +28 -28
- package/dist/types/PriceInfoType.js +56 -57
- package/dist/types/SwapExecutionAction.d.ts +88 -88
- package/dist/types/SwapExecutionAction.js +2 -2
- package/dist/types/SwapStateInfo.d.ts +5 -5
- package/dist/types/SwapStateInfo.js +2 -2
- package/dist/types/SwapWithSigner.d.ts +17 -17
- package/dist/types/SwapWithSigner.js +42 -43
- package/dist/types/Token.d.ts +99 -99
- package/dist/types/Token.js +76 -76
- package/dist/types/TokenAmount.d.ts +69 -69
- package/dist/types/TokenAmount.js +59 -60
- package/dist/types/fees/Fee.d.ts +50 -50
- package/dist/types/fees/Fee.js +2 -2
- package/dist/types/fees/FeeBreakdown.d.ts +11 -11
- package/dist/types/fees/FeeBreakdown.js +2 -2
- package/dist/types/fees/PercentagePPM.d.ts +17 -17
- package/dist/types/fees/PercentagePPM.js +17 -18
- package/dist/types/lnurl/LNURLPay.d.ts +61 -61
- package/dist/types/lnurl/LNURLPay.js +30 -31
- package/dist/types/lnurl/LNURLWithdraw.d.ts +48 -48
- package/dist/types/lnurl/LNURLWithdraw.js +26 -27
- package/dist/types/wallets/LightningInvoiceCreateService.d.ts +24 -24
- package/dist/types/wallets/LightningInvoiceCreateService.js +14 -15
- package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +23 -23
- package/dist/types/wallets/MinimalBitcoinWalletInterface.js +2 -2
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +9 -9
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.js +2 -2
- package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -1
- package/dist/utils/AutomaticClockDriftCorrection.js +69 -70
- package/dist/utils/BitcoinUtils.d.ts +12 -14
- package/dist/utils/BitcoinUtils.js +101 -102
- package/dist/utils/BitcoinWalletUtils.d.ts +7 -7
- package/dist/utils/BitcoinWalletUtils.js +13 -14
- package/dist/utils/Logger.d.ts +7 -7
- package/dist/utils/Logger.js +11 -12
- package/dist/utils/RetryUtils.d.ts +22 -22
- package/dist/utils/RetryUtils.js +66 -67
- package/dist/utils/SwapUtils.d.ts +88 -88
- package/dist/utils/SwapUtils.js +72 -72
- package/dist/utils/TimeoutUtils.d.ts +17 -17
- package/dist/utils/TimeoutUtils.js +54 -55
- package/dist/utils/TokenUtils.d.ts +19 -19
- package/dist/utils/TokenUtils.js +36 -37
- package/dist/utils/TypeUtils.d.ts +7 -7
- package/dist/utils/TypeUtils.js +2 -2
- package/dist/utils/Utils.d.ts +56 -58
- package/dist/utils/Utils.js +193 -194
- package/package.json +1 -1
- package/src/intermediaries/apis/IntermediaryAPI.ts +4 -2
- package/src/prices/abstract/ISwapPrice.ts +19 -6
- package/src/swaps/ISwap.ts +17 -6
- package/src/swaps/ISwapWrapper.ts +4 -3
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +4 -2
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +4 -1
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +2 -2
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +4 -2
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +6 -6
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -5
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +4 -1
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +10 -2
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -1
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +1 -1
|
@@ -1,322 +1,322 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BitcoinWallet =
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const btcNetworkMapping = {
|
|
35
|
-
[base_1.BitcoinNetwork.MAINNET]: utils_1.NETWORK,
|
|
36
|
-
[base_1.BitcoinNetwork.TESTNET]: utils_1.TEST_NETWORK,
|
|
37
|
-
[base_1.BitcoinNetwork.TESTNET4]: utils_1.TEST_NETWORK,
|
|
38
|
-
[base_1.BitcoinNetwork.REGTEST]: {
|
|
39
|
-
...utils_1.TEST_NETWORK,
|
|
40
|
-
bech32: "bcrt"
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
const logger = (0, Logger_1.getLogger)("BitcoinWallet: ");
|
|
44
|
-
/**
|
|
45
|
-
* Abstract base class for Bitcoin wallet implementations, using bitcoin rpc with address index
|
|
46
|
-
* as a backend for fetching balances, UTXOs, etc.
|
|
47
|
-
*
|
|
48
|
-
* @category Bitcoin
|
|
49
|
-
*/
|
|
50
|
-
class BitcoinWallet {
|
|
51
|
-
constructor(mempoolApi, network, feeMultiplier = 1.25, feeOverride) {
|
|
52
|
-
this.rpc = mempoolApi;
|
|
53
|
-
this.network = typeof (network) === "object" ? network : BitcoinWallet.bitcoinNetworkToObject(network);
|
|
54
|
-
this.feeMultiplier = feeMultiplier;
|
|
55
|
-
this.feeOverride = feeOverride;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* @inheritDoc
|
|
59
|
-
*/
|
|
60
|
-
async getFeeRate() {
|
|
61
|
-
if (this.feeOverride != null) {
|
|
62
|
-
return this.feeOverride;
|
|
63
|
-
}
|
|
64
|
-
return Math.floor((await this.rpc.getFeeRate()) * this.feeMultiplier);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Internal helper function for sending a raw transaction through the underlying RPC
|
|
68
|
-
*
|
|
69
|
-
* @param rawHex Serialized bitcoin transaction in hexadecimal format
|
|
70
|
-
* @returns txId Transaction ID of the submitted bitcoin transaction
|
|
71
|
-
*
|
|
72
|
-
* @protected
|
|
73
|
-
*/
|
|
74
|
-
_sendTransaction(rawHex) {
|
|
75
|
-
return this.rpc.sendRawTransaction(rawHex);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Internal helper function for fetching the balance of the wallet given a specific bitcoin wallet address
|
|
79
|
-
*
|
|
80
|
-
* @param address
|
|
81
|
-
* @protected
|
|
82
|
-
*/
|
|
83
|
-
_getBalance(address) {
|
|
84
|
-
return this.rpc.getAddressBalances(address);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Internal helper function for fetching the UTXO set of a given wallet address
|
|
88
|
-
*
|
|
89
|
-
* @param sendingAddress
|
|
90
|
-
* @param sendingAddressType
|
|
91
|
-
* @protected
|
|
92
|
-
*/
|
|
93
|
-
async _getUtxoPool(sendingAddress, sendingAddressType) {
|
|
94
|
-
const utxos = await this.rpc.getAddressUTXOs(sendingAddress);
|
|
95
|
-
let totalSpendable = 0;
|
|
96
|
-
const outputScript = (0, BitcoinUtils_1.toOutputScript)(this.network, sendingAddress);
|
|
97
|
-
const utxoPool = [];
|
|
98
|
-
for (let utxo of utxos) {
|
|
99
|
-
const value = Number(utxo.value);
|
|
100
|
-
totalSpendable += value;
|
|
101
|
-
utxoPool.push({
|
|
102
|
-
vout: utxo.vout,
|
|
103
|
-
txId: utxo.txid,
|
|
104
|
-
value: value,
|
|
105
|
-
type: sendingAddressType,
|
|
106
|
-
outputScript: outputScript,
|
|
107
|
-
address: sendingAddress,
|
|
108
|
-
cpfp: !utxo.confirmed ? await this.rpc.getCPFPData(utxo.txid).then((result) => {
|
|
109
|
-
if (result == null)
|
|
110
|
-
return;
|
|
111
|
-
return {
|
|
112
|
-
txVsize: result.adjustedVsize,
|
|
113
|
-
txEffectiveFeeRate: result.effectiveFeePerVsize
|
|
114
|
-
};
|
|
115
|
-
}) : undefined,
|
|
116
|
-
confirmed: utxo.confirmed
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
logger.debug("_getUtxoPool(): Total spendable value: " + totalSpendable + " num utxos: " + utxoPool.length);
|
|
120
|
-
return utxoPool;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
*
|
|
124
|
-
* @param sendingAccounts
|
|
125
|
-
* @param recipient
|
|
126
|
-
* @param amount
|
|
127
|
-
* @param feeRate
|
|
128
|
-
* @protected
|
|
129
|
-
*/
|
|
130
|
-
async _getPsbt(sendingAccounts, recipient, amount, feeRate) {
|
|
131
|
-
const psbt = new btc_signer_1.Transaction({ PSBTVersion: 0 });
|
|
132
|
-
psbt.addOutput({
|
|
133
|
-
amount: BigInt(amount),
|
|
134
|
-
script: (0, BitcoinUtils_1.toOutputScript)(this.network, recipient)
|
|
135
|
-
});
|
|
136
|
-
return this._fundPsbt(sendingAccounts, psbt, feeRate);
|
|
137
|
-
}
|
|
138
|
-
async _fundPsbt(sendingAccounts, psbt, feeRate) {
|
|
139
|
-
if (feeRate == null)
|
|
140
|
-
feeRate = await this.getFeeRate();
|
|
141
|
-
const utxoPool = (await Promise.all(sendingAccounts.map(acc => this._getUtxoPool(acc.address, acc.addressType)))).flat();
|
|
142
|
-
logger.debug("_fundPsbt(): fee rate: " + feeRate + " utxo pool: ", utxoPool);
|
|
143
|
-
const accountPubkeys = {};
|
|
144
|
-
sendingAccounts.forEach(acc => accountPubkeys[acc.address] = acc.pubkey);
|
|
145
|
-
const requiredInputs = [];
|
|
146
|
-
for (let i = 0; i < psbt.inputsLength; i++) {
|
|
147
|
-
const input = psbt.getInput(i);
|
|
148
|
-
if (input.index == null || input.txid == null)
|
|
149
|
-
throw new Error("Inputs need txid & index!");
|
|
150
|
-
let amount;
|
|
151
|
-
let script;
|
|
152
|
-
if (input.witnessUtxo != null) {
|
|
153
|
-
amount = input.witnessUtxo.amount;
|
|
154
|
-
script = input.witnessUtxo.script;
|
|
155
|
-
}
|
|
156
|
-
else if (input.nonWitnessUtxo != null) {
|
|
157
|
-
amount = input.nonWitnessUtxo.outputs[input.index].amount;
|
|
158
|
-
script = input.nonWitnessUtxo.outputs[input.index].script;
|
|
159
|
-
}
|
|
160
|
-
else
|
|
161
|
-
throw new Error("Either witnessUtxo or nonWitnessUtxo has to be defined!");
|
|
162
|
-
requiredInputs.push({
|
|
163
|
-
txId: buffer_1.Buffer.from(input.txid).toString('hex'),
|
|
164
|
-
vout: input.index,
|
|
165
|
-
value: Number(amount),
|
|
166
|
-
type: (0, BitcoinUtils_1.toCoinselectAddressType)(script)
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
const targets = [];
|
|
170
|
-
for (let i = 0; i < psbt.outputsLength; i++) {
|
|
171
|
-
const output = psbt.getOutput(i);
|
|
172
|
-
if (output.amount == null || output.script == null)
|
|
173
|
-
throw new Error("Outputs need amount & script defined!");
|
|
174
|
-
targets.push({
|
|
175
|
-
value: Number(output.amount),
|
|
176
|
-
script: buffer_1.Buffer.from(output.script)
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
logger.debug("_fundPsbt(): Coinselect targets: ", targets);
|
|
180
|
-
let coinselectResult = (0, coinselect2_1.coinSelect)(utxoPool, targets, feeRate, sendingAccounts[0].addressType, requiredInputs);
|
|
181
|
-
logger.debug("_fundPsbt(): Coinselect result: ", coinselectResult);
|
|
182
|
-
if (coinselectResult.inputs == null || coinselectResult.outputs == null) {
|
|
183
|
-
return {
|
|
184
|
-
fee: coinselectResult.fee
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
// Remove in/outs that are already in the PSBT
|
|
188
|
-
coinselectResult.inputs.splice(0, psbt.inputsLength);
|
|
189
|
-
coinselectResult.outputs.splice(0, psbt.outputsLength);
|
|
190
|
-
const inputAddressIndexes = {};
|
|
191
|
-
coinselectResult.inputs.forEach((input, index) => {
|
|
192
|
-
inputAddressIndexes[input.address] ??= [];
|
|
193
|
-
inputAddressIndexes[input.address].push(index);
|
|
194
|
-
});
|
|
195
|
-
const formattedInputs = await Promise.all(coinselectResult.inputs.map(async (input) => {
|
|
196
|
-
switch (input.type) {
|
|
197
|
-
case "p2tr":
|
|
198
|
-
const parsed = (0, btc_signer_1.p2tr)(buffer_1.Buffer.from(accountPubkeys[input.address], "hex"));
|
|
199
|
-
return {
|
|
200
|
-
txid: input.txId,
|
|
201
|
-
index: input.vout,
|
|
202
|
-
witnessUtxo: {
|
|
203
|
-
script: input.outputScript,
|
|
204
|
-
amount: BigInt(input.value)
|
|
205
|
-
},
|
|
206
|
-
tapInternalKey: parsed.tapInternalKey,
|
|
207
|
-
tapMerkleRoot: parsed.tapMerkleRoot,
|
|
208
|
-
tapLeafScript: parsed.tapLeafScript
|
|
209
|
-
};
|
|
210
|
-
case "p2wpkh":
|
|
211
|
-
return {
|
|
212
|
-
txid: input.txId,
|
|
213
|
-
index: input.vout,
|
|
214
|
-
witnessUtxo: {
|
|
215
|
-
script: input.outputScript,
|
|
216
|
-
amount: BigInt(input.value)
|
|
217
|
-
},
|
|
218
|
-
sighashType: 0x01
|
|
219
|
-
};
|
|
220
|
-
case "p2sh-p2wpkh":
|
|
221
|
-
return {
|
|
222
|
-
txid: input.txId,
|
|
223
|
-
index: input.vout,
|
|
224
|
-
witnessUtxo: {
|
|
225
|
-
script: input.outputScript,
|
|
226
|
-
amount: BigInt(input.value)
|
|
227
|
-
},
|
|
228
|
-
redeemScript: (0, btc_signer_1.p2wpkh)(buffer_1.Buffer.from(accountPubkeys[input.address], "hex"), this.network).script,
|
|
229
|
-
sighashType: 0x01
|
|
230
|
-
};
|
|
231
|
-
case "p2pkh":
|
|
232
|
-
const tx = await this.rpc.getTransaction(input.txId);
|
|
233
|
-
if (tx == null)
|
|
234
|
-
throw new Error("Cannot fetch existing tx " + input.txId);
|
|
235
|
-
return {
|
|
236
|
-
txid: input.txId,
|
|
237
|
-
index: input.vout,
|
|
238
|
-
nonWitnessUtxo: tx.raw,
|
|
239
|
-
sighashType: 0x01
|
|
240
|
-
};
|
|
241
|
-
default:
|
|
242
|
-
throw new Error("Invalid input type: " + input.type);
|
|
243
|
-
}
|
|
244
|
-
}));
|
|
245
|
-
formattedInputs.forEach(input => psbt.addInput(input));
|
|
246
|
-
coinselectResult.outputs.forEach(output => {
|
|
247
|
-
if (output.script == null && output.address == null) {
|
|
248
|
-
//Change output
|
|
249
|
-
psbt.addOutput({
|
|
250
|
-
script: (0, BitcoinUtils_1.toOutputScript)(this.network, sendingAccounts[0].address),
|
|
251
|
-
amount: BigInt(Math.floor(output.value))
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
psbt.addOutput({
|
|
256
|
-
script: output.script ?? (0, BitcoinUtils_1.toOutputScript)(this.network, output.address),
|
|
257
|
-
amount: BigInt(output.value)
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
return {
|
|
262
|
-
psbt,
|
|
263
|
-
fee: coinselectResult.fee,
|
|
264
|
-
inputAddressIndexes
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
async _getSpendableBalance(sendingAccounts, psbt, feeRate) {
|
|
268
|
-
feeRate ??= await this.getFeeRate();
|
|
269
|
-
const utxoPool = (await Promise.all(sendingAccounts.map(acc => this._getUtxoPool(acc.address, acc.addressType)))).flat();
|
|
270
|
-
const requiredInputs = [];
|
|
271
|
-
if (psbt != null)
|
|
272
|
-
for (let i = 0; i < psbt.inputsLength; i++) {
|
|
273
|
-
const input = psbt.getInput(i);
|
|
274
|
-
if (input.index == null || input.txid == null)
|
|
275
|
-
throw new Error("Inputs need txid & index!");
|
|
276
|
-
let amount;
|
|
277
|
-
let script;
|
|
278
|
-
if (input.witnessUtxo != null) {
|
|
279
|
-
amount = input.witnessUtxo.amount;
|
|
280
|
-
script = input.witnessUtxo.script;
|
|
281
|
-
}
|
|
282
|
-
else if (input.nonWitnessUtxo != null) {
|
|
283
|
-
amount = input.nonWitnessUtxo.outputs[input.index].amount;
|
|
284
|
-
script = input.nonWitnessUtxo.outputs[input.index].script;
|
|
285
|
-
}
|
|
286
|
-
else
|
|
287
|
-
throw new Error("Either witnessUtxo or nonWitnessUtxo has to be defined!");
|
|
288
|
-
requiredInputs.push({
|
|
289
|
-
txId: buffer_1.Buffer.from(input.txid).toString('hex'),
|
|
290
|
-
vout: input.index,
|
|
291
|
-
value: Number(amount),
|
|
292
|
-
type: (0, BitcoinUtils_1.toCoinselectAddressType)(script)
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
const additionalOutputs = [];
|
|
296
|
-
if (psbt != null)
|
|
297
|
-
for (let i = 0; i < psbt.outputsLength; i++) {
|
|
298
|
-
const output = psbt.getOutput(i);
|
|
299
|
-
if (output.amount == null || output.script == null)
|
|
300
|
-
throw new Error("Outputs need amount & script!");
|
|
301
|
-
additionalOutputs.push({
|
|
302
|
-
value: Number(output.amount),
|
|
303
|
-
script: buffer_1.Buffer.from(output.script)
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
const target = btc_signer_1.OutScript.encode({
|
|
307
|
-
type: "wsh",
|
|
308
|
-
hash: (0, Utils_1.randomBytes)(32)
|
|
309
|
-
});
|
|
310
|
-
let coinselectResult = (0, coinselect2_1.maxSendable)(utxoPool, { script: buffer_1.Buffer.from(target), type: "p2wsh" }, feeRate, requiredInputs, additionalOutputs);
|
|
311
|
-
logger.debug("_getSpendableBalance(): Max spendable result: ", coinselectResult);
|
|
312
|
-
return {
|
|
313
|
-
feeRate: feeRate,
|
|
314
|
-
balance: BigInt(Math.floor(coinselectResult.value)),
|
|
315
|
-
totalFee: coinselectResult.fee
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
static bitcoinNetworkToObject(network) {
|
|
319
|
-
return btcNetworkMapping[network];
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
exports.BitcoinWallet = BitcoinWallet;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BitcoinWallet = void 0;
|
|
4
|
+
exports.identifyAddressType = identifyAddressType;
|
|
5
|
+
const coinselect2_1 = require("../coinselect2");
|
|
6
|
+
const utils_1 = require("@scure/btc-signer/utils");
|
|
7
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
8
|
+
const buffer_1 = require("buffer");
|
|
9
|
+
const Utils_1 = require("../../utils/Utils");
|
|
10
|
+
const BitcoinUtils_1 = require("../../utils/BitcoinUtils");
|
|
11
|
+
const Logger_1 = require("../../utils/Logger");
|
|
12
|
+
const base_1 = require("@atomiqlabs/base");
|
|
13
|
+
/**
|
|
14
|
+
* Identifies the address type of a Bitcoin address
|
|
15
|
+
*
|
|
16
|
+
* @category Bitcoin
|
|
17
|
+
*/
|
|
18
|
+
function identifyAddressType(address, network) {
|
|
19
|
+
switch ((0, btc_signer_1.Address)(network).decode(address).type) {
|
|
20
|
+
case "pkh":
|
|
21
|
+
return "p2pkh";
|
|
22
|
+
case "wpkh":
|
|
23
|
+
return "p2wpkh";
|
|
24
|
+
case "tr":
|
|
25
|
+
return "p2tr";
|
|
26
|
+
case "sh":
|
|
27
|
+
return "p2sh-p2wpkh";
|
|
28
|
+
case "wsh":
|
|
29
|
+
return "p2wsh";
|
|
30
|
+
default:
|
|
31
|
+
throw new Error("Unknown address type of " + address);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const btcNetworkMapping = {
|
|
35
|
+
[base_1.BitcoinNetwork.MAINNET]: utils_1.NETWORK,
|
|
36
|
+
[base_1.BitcoinNetwork.TESTNET]: utils_1.TEST_NETWORK,
|
|
37
|
+
[base_1.BitcoinNetwork.TESTNET4]: utils_1.TEST_NETWORK,
|
|
38
|
+
[base_1.BitcoinNetwork.REGTEST]: {
|
|
39
|
+
...utils_1.TEST_NETWORK,
|
|
40
|
+
bech32: "bcrt"
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const logger = (0, Logger_1.getLogger)("BitcoinWallet: ");
|
|
44
|
+
/**
|
|
45
|
+
* Abstract base class for Bitcoin wallet implementations, using bitcoin rpc with address index
|
|
46
|
+
* as a backend for fetching balances, UTXOs, etc.
|
|
47
|
+
*
|
|
48
|
+
* @category Bitcoin
|
|
49
|
+
*/
|
|
50
|
+
class BitcoinWallet {
|
|
51
|
+
constructor(mempoolApi, network, feeMultiplier = 1.25, feeOverride) {
|
|
52
|
+
this.rpc = mempoolApi;
|
|
53
|
+
this.network = typeof (network) === "object" ? network : BitcoinWallet.bitcoinNetworkToObject(network);
|
|
54
|
+
this.feeMultiplier = feeMultiplier;
|
|
55
|
+
this.feeOverride = feeOverride;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* @inheritDoc
|
|
59
|
+
*/
|
|
60
|
+
async getFeeRate() {
|
|
61
|
+
if (this.feeOverride != null) {
|
|
62
|
+
return this.feeOverride;
|
|
63
|
+
}
|
|
64
|
+
return Math.floor((await this.rpc.getFeeRate()) * this.feeMultiplier);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Internal helper function for sending a raw transaction through the underlying RPC
|
|
68
|
+
*
|
|
69
|
+
* @param rawHex Serialized bitcoin transaction in hexadecimal format
|
|
70
|
+
* @returns txId Transaction ID of the submitted bitcoin transaction
|
|
71
|
+
*
|
|
72
|
+
* @protected
|
|
73
|
+
*/
|
|
74
|
+
_sendTransaction(rawHex) {
|
|
75
|
+
return this.rpc.sendRawTransaction(rawHex);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Internal helper function for fetching the balance of the wallet given a specific bitcoin wallet address
|
|
79
|
+
*
|
|
80
|
+
* @param address
|
|
81
|
+
* @protected
|
|
82
|
+
*/
|
|
83
|
+
_getBalance(address) {
|
|
84
|
+
return this.rpc.getAddressBalances(address);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Internal helper function for fetching the UTXO set of a given wallet address
|
|
88
|
+
*
|
|
89
|
+
* @param sendingAddress
|
|
90
|
+
* @param sendingAddressType
|
|
91
|
+
* @protected
|
|
92
|
+
*/
|
|
93
|
+
async _getUtxoPool(sendingAddress, sendingAddressType) {
|
|
94
|
+
const utxos = await this.rpc.getAddressUTXOs(sendingAddress);
|
|
95
|
+
let totalSpendable = 0;
|
|
96
|
+
const outputScript = (0, BitcoinUtils_1.toOutputScript)(this.network, sendingAddress);
|
|
97
|
+
const utxoPool = [];
|
|
98
|
+
for (let utxo of utxos) {
|
|
99
|
+
const value = Number(utxo.value);
|
|
100
|
+
totalSpendable += value;
|
|
101
|
+
utxoPool.push({
|
|
102
|
+
vout: utxo.vout,
|
|
103
|
+
txId: utxo.txid,
|
|
104
|
+
value: value,
|
|
105
|
+
type: sendingAddressType,
|
|
106
|
+
outputScript: outputScript,
|
|
107
|
+
address: sendingAddress,
|
|
108
|
+
cpfp: !utxo.confirmed ? await this.rpc.getCPFPData(utxo.txid).then((result) => {
|
|
109
|
+
if (result == null)
|
|
110
|
+
return;
|
|
111
|
+
return {
|
|
112
|
+
txVsize: result.adjustedVsize,
|
|
113
|
+
txEffectiveFeeRate: result.effectiveFeePerVsize
|
|
114
|
+
};
|
|
115
|
+
}) : undefined,
|
|
116
|
+
confirmed: utxo.confirmed
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
logger.debug("_getUtxoPool(): Total spendable value: " + totalSpendable + " num utxos: " + utxoPool.length);
|
|
120
|
+
return utxoPool;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
*
|
|
124
|
+
* @param sendingAccounts
|
|
125
|
+
* @param recipient
|
|
126
|
+
* @param amount
|
|
127
|
+
* @param feeRate
|
|
128
|
+
* @protected
|
|
129
|
+
*/
|
|
130
|
+
async _getPsbt(sendingAccounts, recipient, amount, feeRate) {
|
|
131
|
+
const psbt = new btc_signer_1.Transaction({ PSBTVersion: 0 });
|
|
132
|
+
psbt.addOutput({
|
|
133
|
+
amount: BigInt(amount),
|
|
134
|
+
script: (0, BitcoinUtils_1.toOutputScript)(this.network, recipient)
|
|
135
|
+
});
|
|
136
|
+
return this._fundPsbt(sendingAccounts, psbt, feeRate);
|
|
137
|
+
}
|
|
138
|
+
async _fundPsbt(sendingAccounts, psbt, feeRate) {
|
|
139
|
+
if (feeRate == null)
|
|
140
|
+
feeRate = await this.getFeeRate();
|
|
141
|
+
const utxoPool = (await Promise.all(sendingAccounts.map(acc => this._getUtxoPool(acc.address, acc.addressType)))).flat();
|
|
142
|
+
logger.debug("_fundPsbt(): fee rate: " + feeRate + " utxo pool: ", utxoPool);
|
|
143
|
+
const accountPubkeys = {};
|
|
144
|
+
sendingAccounts.forEach(acc => accountPubkeys[acc.address] = acc.pubkey);
|
|
145
|
+
const requiredInputs = [];
|
|
146
|
+
for (let i = 0; i < psbt.inputsLength; i++) {
|
|
147
|
+
const input = psbt.getInput(i);
|
|
148
|
+
if (input.index == null || input.txid == null)
|
|
149
|
+
throw new Error("Inputs need txid & index!");
|
|
150
|
+
let amount;
|
|
151
|
+
let script;
|
|
152
|
+
if (input.witnessUtxo != null) {
|
|
153
|
+
amount = input.witnessUtxo.amount;
|
|
154
|
+
script = input.witnessUtxo.script;
|
|
155
|
+
}
|
|
156
|
+
else if (input.nonWitnessUtxo != null) {
|
|
157
|
+
amount = input.nonWitnessUtxo.outputs[input.index].amount;
|
|
158
|
+
script = input.nonWitnessUtxo.outputs[input.index].script;
|
|
159
|
+
}
|
|
160
|
+
else
|
|
161
|
+
throw new Error("Either witnessUtxo or nonWitnessUtxo has to be defined!");
|
|
162
|
+
requiredInputs.push({
|
|
163
|
+
txId: buffer_1.Buffer.from(input.txid).toString('hex'),
|
|
164
|
+
vout: input.index,
|
|
165
|
+
value: Number(amount),
|
|
166
|
+
type: (0, BitcoinUtils_1.toCoinselectAddressType)(script)
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
const targets = [];
|
|
170
|
+
for (let i = 0; i < psbt.outputsLength; i++) {
|
|
171
|
+
const output = psbt.getOutput(i);
|
|
172
|
+
if (output.amount == null || output.script == null)
|
|
173
|
+
throw new Error("Outputs need amount & script defined!");
|
|
174
|
+
targets.push({
|
|
175
|
+
value: Number(output.amount),
|
|
176
|
+
script: buffer_1.Buffer.from(output.script)
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
logger.debug("_fundPsbt(): Coinselect targets: ", targets);
|
|
180
|
+
let coinselectResult = (0, coinselect2_1.coinSelect)(utxoPool, targets, feeRate, sendingAccounts[0].addressType, requiredInputs);
|
|
181
|
+
logger.debug("_fundPsbt(): Coinselect result: ", coinselectResult);
|
|
182
|
+
if (coinselectResult.inputs == null || coinselectResult.outputs == null) {
|
|
183
|
+
return {
|
|
184
|
+
fee: coinselectResult.fee
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// Remove in/outs that are already in the PSBT
|
|
188
|
+
coinselectResult.inputs.splice(0, psbt.inputsLength);
|
|
189
|
+
coinselectResult.outputs.splice(0, psbt.outputsLength);
|
|
190
|
+
const inputAddressIndexes = {};
|
|
191
|
+
coinselectResult.inputs.forEach((input, index) => {
|
|
192
|
+
inputAddressIndexes[input.address] ??= [];
|
|
193
|
+
inputAddressIndexes[input.address].push(index);
|
|
194
|
+
});
|
|
195
|
+
const formattedInputs = await Promise.all(coinselectResult.inputs.map(async (input) => {
|
|
196
|
+
switch (input.type) {
|
|
197
|
+
case "p2tr":
|
|
198
|
+
const parsed = (0, btc_signer_1.p2tr)(buffer_1.Buffer.from(accountPubkeys[input.address], "hex"));
|
|
199
|
+
return {
|
|
200
|
+
txid: input.txId,
|
|
201
|
+
index: input.vout,
|
|
202
|
+
witnessUtxo: {
|
|
203
|
+
script: input.outputScript,
|
|
204
|
+
amount: BigInt(input.value)
|
|
205
|
+
},
|
|
206
|
+
tapInternalKey: parsed.tapInternalKey,
|
|
207
|
+
tapMerkleRoot: parsed.tapMerkleRoot,
|
|
208
|
+
tapLeafScript: parsed.tapLeafScript
|
|
209
|
+
};
|
|
210
|
+
case "p2wpkh":
|
|
211
|
+
return {
|
|
212
|
+
txid: input.txId,
|
|
213
|
+
index: input.vout,
|
|
214
|
+
witnessUtxo: {
|
|
215
|
+
script: input.outputScript,
|
|
216
|
+
amount: BigInt(input.value)
|
|
217
|
+
},
|
|
218
|
+
sighashType: 0x01
|
|
219
|
+
};
|
|
220
|
+
case "p2sh-p2wpkh":
|
|
221
|
+
return {
|
|
222
|
+
txid: input.txId,
|
|
223
|
+
index: input.vout,
|
|
224
|
+
witnessUtxo: {
|
|
225
|
+
script: input.outputScript,
|
|
226
|
+
amount: BigInt(input.value)
|
|
227
|
+
},
|
|
228
|
+
redeemScript: (0, btc_signer_1.p2wpkh)(buffer_1.Buffer.from(accountPubkeys[input.address], "hex"), this.network).script,
|
|
229
|
+
sighashType: 0x01
|
|
230
|
+
};
|
|
231
|
+
case "p2pkh":
|
|
232
|
+
const tx = await this.rpc.getTransaction(input.txId);
|
|
233
|
+
if (tx == null)
|
|
234
|
+
throw new Error("Cannot fetch existing tx " + input.txId);
|
|
235
|
+
return {
|
|
236
|
+
txid: input.txId,
|
|
237
|
+
index: input.vout,
|
|
238
|
+
nonWitnessUtxo: tx.raw,
|
|
239
|
+
sighashType: 0x01
|
|
240
|
+
};
|
|
241
|
+
default:
|
|
242
|
+
throw new Error("Invalid input type: " + input.type);
|
|
243
|
+
}
|
|
244
|
+
}));
|
|
245
|
+
formattedInputs.forEach(input => psbt.addInput(input));
|
|
246
|
+
coinselectResult.outputs.forEach(output => {
|
|
247
|
+
if (output.script == null && output.address == null) {
|
|
248
|
+
//Change output
|
|
249
|
+
psbt.addOutput({
|
|
250
|
+
script: (0, BitcoinUtils_1.toOutputScript)(this.network, sendingAccounts[0].address),
|
|
251
|
+
amount: BigInt(Math.floor(output.value))
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
psbt.addOutput({
|
|
256
|
+
script: output.script ?? (0, BitcoinUtils_1.toOutputScript)(this.network, output.address),
|
|
257
|
+
amount: BigInt(output.value)
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
return {
|
|
262
|
+
psbt,
|
|
263
|
+
fee: coinselectResult.fee,
|
|
264
|
+
inputAddressIndexes
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
async _getSpendableBalance(sendingAccounts, psbt, feeRate) {
|
|
268
|
+
feeRate ??= await this.getFeeRate();
|
|
269
|
+
const utxoPool = (await Promise.all(sendingAccounts.map(acc => this._getUtxoPool(acc.address, acc.addressType)))).flat();
|
|
270
|
+
const requiredInputs = [];
|
|
271
|
+
if (psbt != null)
|
|
272
|
+
for (let i = 0; i < psbt.inputsLength; i++) {
|
|
273
|
+
const input = psbt.getInput(i);
|
|
274
|
+
if (input.index == null || input.txid == null)
|
|
275
|
+
throw new Error("Inputs need txid & index!");
|
|
276
|
+
let amount;
|
|
277
|
+
let script;
|
|
278
|
+
if (input.witnessUtxo != null) {
|
|
279
|
+
amount = input.witnessUtxo.amount;
|
|
280
|
+
script = input.witnessUtxo.script;
|
|
281
|
+
}
|
|
282
|
+
else if (input.nonWitnessUtxo != null) {
|
|
283
|
+
amount = input.nonWitnessUtxo.outputs[input.index].amount;
|
|
284
|
+
script = input.nonWitnessUtxo.outputs[input.index].script;
|
|
285
|
+
}
|
|
286
|
+
else
|
|
287
|
+
throw new Error("Either witnessUtxo or nonWitnessUtxo has to be defined!");
|
|
288
|
+
requiredInputs.push({
|
|
289
|
+
txId: buffer_1.Buffer.from(input.txid).toString('hex'),
|
|
290
|
+
vout: input.index,
|
|
291
|
+
value: Number(amount),
|
|
292
|
+
type: (0, BitcoinUtils_1.toCoinselectAddressType)(script)
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
const additionalOutputs = [];
|
|
296
|
+
if (psbt != null)
|
|
297
|
+
for (let i = 0; i < psbt.outputsLength; i++) {
|
|
298
|
+
const output = psbt.getOutput(i);
|
|
299
|
+
if (output.amount == null || output.script == null)
|
|
300
|
+
throw new Error("Outputs need amount & script!");
|
|
301
|
+
additionalOutputs.push({
|
|
302
|
+
value: Number(output.amount),
|
|
303
|
+
script: buffer_1.Buffer.from(output.script)
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
const target = btc_signer_1.OutScript.encode({
|
|
307
|
+
type: "wsh",
|
|
308
|
+
hash: (0, Utils_1.randomBytes)(32)
|
|
309
|
+
});
|
|
310
|
+
let coinselectResult = (0, coinselect2_1.maxSendable)(utxoPool, { script: buffer_1.Buffer.from(target), type: "p2wsh" }, feeRate, requiredInputs, additionalOutputs);
|
|
311
|
+
logger.debug("_getSpendableBalance(): Max spendable result: ", coinselectResult);
|
|
312
|
+
return {
|
|
313
|
+
feeRate: feeRate,
|
|
314
|
+
balance: BigInt(Math.floor(coinselectResult.value)),
|
|
315
|
+
totalFee: coinselectResult.fee
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
static bitcoinNetworkToObject(network) {
|
|
319
|
+
return btcNetworkMapping[network];
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
exports.BitcoinWallet = BitcoinWallet;
|