@atomiqlabs/lp-lib 16.2.0 → 16.2.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/LICENSE +201 -201
- package/dist/fees/IBtcFeeEstimator.d.ts +3 -3
- package/dist/fees/IBtcFeeEstimator.js +2 -2
- package/dist/index.d.ts +42 -42
- package/dist/index.js +58 -58
- package/dist/info/InfoHandler.d.ts +17 -17
- package/dist/info/InfoHandler.js +60 -60
- package/dist/plugins/IPlugin.d.ts +144 -144
- package/dist/plugins/IPlugin.js +34 -34
- package/dist/plugins/PluginManager.d.ts +113 -113
- package/dist/plugins/PluginManager.js +274 -274
- package/dist/prices/BinanceSwapPrice.d.ts +29 -29
- package/dist/prices/BinanceSwapPrice.js +79 -79
- package/dist/prices/CoinGeckoSwapPrice.d.ts +33 -33
- package/dist/prices/CoinGeckoSwapPrice.js +51 -51
- package/dist/prices/ISwapPrice.d.ts +43 -43
- package/dist/prices/ISwapPrice.js +55 -55
- package/dist/prices/OKXSwapPrice.d.ts +29 -29
- package/dist/prices/OKXSwapPrice.js +79 -79
- package/dist/storage/IIntermediaryStorage.d.ts +18 -18
- package/dist/storage/IIntermediaryStorage.js +2 -2
- package/dist/storagemanager/IntermediaryStorageManager.d.ts +19 -19
- package/dist/storagemanager/IntermediaryStorageManager.js +111 -111
- package/dist/storagemanager/StorageManager.d.ts +13 -13
- package/dist/storagemanager/StorageManager.js +64 -64
- package/dist/swaps/SwapHandler.d.ts +171 -171
- package/dist/swaps/SwapHandler.js +217 -217
- package/dist/swaps/SwapHandlerSwap.d.ts +79 -79
- package/dist/swaps/SwapHandlerSwap.js +78 -78
- package/dist/swaps/assertions/AmountAssertions.d.ts +28 -28
- package/dist/swaps/assertions/AmountAssertions.js +74 -74
- package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +76 -76
- package/dist/swaps/assertions/FromBtcAmountAssertions.js +185 -185
- package/dist/swaps/assertions/LightningAssertions.d.ts +44 -44
- package/dist/swaps/assertions/LightningAssertions.js +86 -86
- package/dist/swaps/assertions/ToBtcAmountAssertions.d.ts +53 -53
- package/dist/swaps/assertions/ToBtcAmountAssertions.js +150 -150
- package/dist/swaps/escrow/EscrowHandler.d.ts +50 -50
- package/dist/swaps/escrow/EscrowHandler.js +151 -151
- package/dist/swaps/escrow/EscrowHandlerSwap.d.ts +35 -35
- package/dist/swaps/escrow/EscrowHandlerSwap.js +69 -69
- package/dist/swaps/escrow/FromBtcBaseSwap.d.ts +14 -14
- package/dist/swaps/escrow/FromBtcBaseSwap.js +32 -32
- package/dist/swaps/escrow/FromBtcBaseSwapHandler.d.ts +102 -102
- package/dist/swaps/escrow/FromBtcBaseSwapHandler.js +210 -210
- package/dist/swaps/escrow/ToBtcBaseSwap.d.ts +36 -36
- package/dist/swaps/escrow/ToBtcBaseSwap.js +67 -67
- package/dist/swaps/escrow/ToBtcBaseSwapHandler.d.ts +53 -53
- package/dist/swaps/escrow/ToBtcBaseSwapHandler.js +81 -81
- package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.d.ts +84 -84
- package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.js +322 -322
- package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.d.ts +21 -21
- package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.js +50 -50
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.d.ts +108 -108
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +695 -695
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +33 -33
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.js +91 -91
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.d.ts +112 -112
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.js +708 -708
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.d.ts +55 -55
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.js +120 -120
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.d.ts +170 -170
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.js +745 -745
- package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.d.ts +28 -28
- package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.js +64 -64
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.d.ts +178 -178
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.js +900 -899
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +24 -24
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.js +58 -58
- package/dist/swaps/spv_vault_swap/SpvVault.d.ts +44 -44
- package/dist/swaps/spv_vault_swap/SpvVault.js +145 -145
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +68 -68
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +158 -158
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.d.ts +68 -68
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +561 -561
- package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +63 -63
- package/dist/swaps/spv_vault_swap/SpvVaults.js +491 -491
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.d.ts +52 -52
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.js +662 -662
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.d.ts +52 -52
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.js +118 -118
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.d.ts +77 -77
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.js +504 -504
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +34 -34
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.js +81 -81
- package/dist/utils/BitcoinUtils.d.ts +4 -4
- package/dist/utils/BitcoinUtils.js +61 -61
- package/dist/utils/Utils.d.ts +32 -32
- package/dist/utils/Utils.js +129 -129
- package/dist/utils/paramcoders/IParamReader.d.ts +5 -5
- package/dist/utils/paramcoders/IParamReader.js +2 -2
- package/dist/utils/paramcoders/IParamWriter.d.ts +4 -4
- package/dist/utils/paramcoders/IParamWriter.js +2 -2
- package/dist/utils/paramcoders/LegacyParamEncoder.d.ts +10 -10
- package/dist/utils/paramcoders/LegacyParamEncoder.js +22 -22
- package/dist/utils/paramcoders/ParamDecoder.d.ts +25 -25
- package/dist/utils/paramcoders/ParamDecoder.js +222 -222
- package/dist/utils/paramcoders/ParamEncoder.d.ts +9 -9
- package/dist/utils/paramcoders/ParamEncoder.js +22 -22
- package/dist/utils/paramcoders/SchemaVerifier.d.ts +21 -21
- package/dist/utils/paramcoders/SchemaVerifier.js +84 -84
- package/dist/utils/paramcoders/server/ServerParamDecoder.d.ts +8 -8
- package/dist/utils/paramcoders/server/ServerParamDecoder.js +107 -107
- package/dist/utils/paramcoders/server/ServerParamEncoder.d.ts +11 -11
- package/dist/utils/paramcoders/server/ServerParamEncoder.js +65 -65
- package/dist/wallets/IBitcoinWallet.d.ts +149 -149
- package/dist/wallets/IBitcoinWallet.js +97 -97
- package/dist/wallets/ILightningWallet.d.ts +136 -136
- package/dist/wallets/ILightningWallet.js +37 -37
- package/dist/wallets/ISpvVaultSigner.d.ts +7 -7
- package/dist/wallets/ISpvVaultSigner.js +2 -2
- package/package.json +36 -36
- package/src/fees/IBtcFeeEstimator.ts +6 -6
- package/src/index.ts +53 -53
- package/src/info/InfoHandler.ts +103 -103
- package/src/plugins/IPlugin.ts +174 -174
- package/src/plugins/PluginManager.ts +354 -354
- package/src/prices/BinanceSwapPrice.ts +101 -101
- package/src/prices/CoinGeckoSwapPrice.ts +75 -75
- package/src/prices/ISwapPrice.ts +88 -88
- package/src/prices/OKXSwapPrice.ts +101 -101
- package/src/storage/IIntermediaryStorage.ts +19 -19
- package/src/storagemanager/IntermediaryStorageManager.ts +118 -118
- package/src/storagemanager/StorageManager.ts +78 -78
- package/src/swaps/SwapHandler.ts +323 -323
- package/src/swaps/SwapHandlerSwap.ts +141 -141
- package/src/swaps/assertions/AmountAssertions.ts +77 -77
- package/src/swaps/assertions/FromBtcAmountAssertions.ts +251 -251
- package/src/swaps/assertions/LightningAssertions.ts +103 -103
- package/src/swaps/assertions/ToBtcAmountAssertions.ts +203 -203
- package/src/swaps/escrow/EscrowHandler.ts +172 -172
- package/src/swaps/escrow/EscrowHandlerSwap.ts +86 -86
- package/src/swaps/escrow/FromBtcBaseSwap.ts +38 -38
- package/src/swaps/escrow/FromBtcBaseSwapHandler.ts +286 -286
- package/src/swaps/escrow/ToBtcBaseSwap.ts +85 -85
- package/src/swaps/escrow/ToBtcBaseSwapHandler.ts +129 -129
- package/src/swaps/escrow/frombtc_abstract/FromBtcAbs.ts +457 -457
- package/src/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.ts +61 -61
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +873 -873
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.ts +141 -141
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +866 -866
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.ts +196 -196
- package/src/swaps/escrow/tobtc_abstract/ToBtcAbs.ts +920 -920
- package/src/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.ts +108 -108
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.ts +1150 -1149
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.ts +80 -80
- package/src/swaps/spv_vault_swap/SpvVault.ts +178 -178
- package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +228 -228
- package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +718 -718
- package/src/swaps/spv_vault_swap/SpvVaults.ts +567 -567
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrusted.ts +762 -762
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.ts +185 -185
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.ts +603 -603
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.ts +121 -121
- package/src/utils/BitcoinUtils.ts +59 -59
- package/src/utils/Utils.ts +150 -150
- package/src/utils/paramcoders/IParamReader.ts +7 -7
- package/src/utils/paramcoders/IParamWriter.ts +8 -8
- package/src/utils/paramcoders/LegacyParamEncoder.ts +27 -27
- package/src/utils/paramcoders/ParamDecoder.ts +218 -218
- package/src/utils/paramcoders/ParamEncoder.ts +29 -29
- package/src/utils/paramcoders/SchemaVerifier.ts +96 -96
- package/src/utils/paramcoders/server/ServerParamDecoder.ts +118 -118
- package/src/utils/paramcoders/server/ServerParamEncoder.ts +75 -75
- package/src/wallets/IBitcoinWallet.ts +237 -237
- package/src/wallets/ILightningWallet.ts +200 -200
- package/src/wallets/ISpvVaultSigner.ts +10 -10
|
@@ -1,238 +1,238 @@
|
|
|
1
|
-
import {BtcTx} from "@atomiqlabs/base";
|
|
2
|
-
import {Command} from "@atomiqlabs/server-base";
|
|
3
|
-
import {Address, OutScript, Transaction} from "@scure/btc-signer";
|
|
4
|
-
import {BTC_NETWORK} from "@scure/btc-signer/utils";
|
|
5
|
-
|
|
6
|
-
export type BitcoinUtxo = {
|
|
7
|
-
address: string,
|
|
8
|
-
type: "p2wpkh" | "p2sh-p2wpkh" | "p2tr",
|
|
9
|
-
confirmations: number,
|
|
10
|
-
outputScript: Buffer,
|
|
11
|
-
value: number,
|
|
12
|
-
txId: string,
|
|
13
|
-
vout: number
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type SignPsbtResponse = {
|
|
17
|
-
psbt: Transaction,
|
|
18
|
-
tx: Transaction,
|
|
19
|
-
raw: string,
|
|
20
|
-
txId: string,
|
|
21
|
-
networkFee: number
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export abstract class IBitcoinWallet {
|
|
25
|
-
|
|
26
|
-
readonly network: BTC_NETWORK;
|
|
27
|
-
|
|
28
|
-
protected constructor(network: BTC_NETWORK) {
|
|
29
|
-
this.network = network;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
toOutputScript(address: string): Buffer {
|
|
33
|
-
const outputScript = Address(this.network).decode(address);
|
|
34
|
-
switch(outputScript.type) {
|
|
35
|
-
case "pkh":
|
|
36
|
-
case "sh":
|
|
37
|
-
case "wpkh":
|
|
38
|
-
case "wsh":
|
|
39
|
-
return Buffer.from(OutScript.encode({
|
|
40
|
-
type: outputScript.type,
|
|
41
|
-
hash: outputScript.hash
|
|
42
|
-
}));
|
|
43
|
-
case "tr":
|
|
44
|
-
return Buffer.from(OutScript.encode({
|
|
45
|
-
type: "tr",
|
|
46
|
-
pubkey: outputScript.pubkey
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
throw new Error("Unrecognized address type");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getSignedTransaction(destination: string, amount: number, feeRate?: number, nonce?: bigint, maxAllowedFeeRate?: number): Promise<SignPsbtResponse> {
|
|
53
|
-
return this.getSignedMultiTransaction([{address: destination, amount}], feeRate, nonce, maxAllowedFeeRate);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async getSignedMultiTransaction(
|
|
57
|
-
destinations: {address: string, amount: number}[], feeRate?: number, nonce?: bigint, maxAllowedFeeRate?: number
|
|
58
|
-
): Promise<SignPsbtResponse> {
|
|
59
|
-
let locktime = 0;
|
|
60
|
-
let sequence = 0xFFFFFFFD;
|
|
61
|
-
//Apply nonce
|
|
62
|
-
if(nonce!=null) {
|
|
63
|
-
const locktimeBN = nonce >> 24n;
|
|
64
|
-
locktime = Number(locktimeBN) + 500000000;
|
|
65
|
-
if(locktime > (Date.now()/1000 - 24*60*60)) throw new Error("Invalid escrow nonce (locktime)!");
|
|
66
|
-
|
|
67
|
-
const sequenceBN = nonce & 0xFFFFFFn;
|
|
68
|
-
sequence = 0xFE000000 + Number(sequenceBN);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let psbt = new Transaction({lockTime: locktime});
|
|
72
|
-
destinations.forEach(dst => psbt.addOutput({
|
|
73
|
-
script: this.toOutputScript(dst.address),
|
|
74
|
-
amount: BigInt(dst.amount)
|
|
75
|
-
}));
|
|
76
|
-
|
|
77
|
-
await this.fundPsbt(psbt, feeRate, maxAllowedFeeRate);
|
|
78
|
-
|
|
79
|
-
//Apply nonce
|
|
80
|
-
for(let i=0;i<psbt.inputsLength;i++) {
|
|
81
|
-
psbt.updateInput(i, {sequence});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return await this.signPsbt(psbt);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async estimateFee(destination: string, amount: number, feeRate?: number, feeRateMultiplier?: number): Promise<{satsPerVbyte: number, networkFee: number}> {
|
|
88
|
-
feeRate ??= await this.getFeeRate();
|
|
89
|
-
if(feeRateMultiplier!=null) feeRate = feeRate * feeRateMultiplier;
|
|
90
|
-
|
|
91
|
-
let psbt = new Transaction();
|
|
92
|
-
psbt.addOutput({
|
|
93
|
-
script: this.toOutputScript(destination),
|
|
94
|
-
amount: BigInt(amount)
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
return await this.estimatePsbtFee(psbt, feeRate);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
drainAll(destination: string | Buffer, inputs: Omit<BitcoinUtxo, "address">[], feeRate?: number): Promise<SignPsbtResponse> {
|
|
101
|
-
throw new Error("Not implemented");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
burnAll(inputs: Omit<BitcoinUtxo, "address">[]): Promise<SignPsbtResponse> {
|
|
105
|
-
let psbt = new Transaction();
|
|
106
|
-
inputs.forEach(input => psbt.addInput({
|
|
107
|
-
txid: input.txId,
|
|
108
|
-
index: input.vout,
|
|
109
|
-
witnessUtxo: {
|
|
110
|
-
script: input.outputScript,
|
|
111
|
-
amount: BigInt(input.value)
|
|
112
|
-
},
|
|
113
|
-
sighashType: 0x01,
|
|
114
|
-
sequence: 0
|
|
115
|
-
}));
|
|
116
|
-
psbt.addOutput({
|
|
117
|
-
script: Buffer.concat([Buffer.from([0x6a, 20]), Buffer.from("BURN, BABY, BURN! AQ", "ascii")]),
|
|
118
|
-
amount: 0n
|
|
119
|
-
});
|
|
120
|
-
return this.signPsbt(psbt);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Initializes the wallet, called before any actions on the wallet
|
|
125
|
-
*/
|
|
126
|
-
abstract init(): Promise<void>;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Returns whether the wallet is ready
|
|
130
|
-
*/
|
|
131
|
-
abstract isReady(): boolean;
|
|
132
|
-
/**
|
|
133
|
-
* Returns the status defined string to be displayed in the status message
|
|
134
|
-
*/
|
|
135
|
-
abstract getStatus(): string;
|
|
136
|
-
/**
|
|
137
|
-
* Additional status information to be displayed in the status message
|
|
138
|
-
*/
|
|
139
|
-
abstract getStatusInfo(): Promise<Record<string, string>>;
|
|
140
|
-
/**
|
|
141
|
-
* Returns the commands that will be exposed
|
|
142
|
-
*/
|
|
143
|
-
abstract getCommands(): Command<any>[];
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Returns the address type of the wallet
|
|
147
|
-
*/
|
|
148
|
-
abstract getAddressType(): "p2wpkh" | "p2sh-p2wpkh" | "p2tr";
|
|
149
|
-
/**
|
|
150
|
-
* Returns an unused address suitable for receiving
|
|
151
|
-
*/
|
|
152
|
-
abstract getAddress(): Promise<string>;
|
|
153
|
-
/**
|
|
154
|
-
* Adds previously returned address (with getAddress call), to the pool of unused addresses
|
|
155
|
-
* @param address
|
|
156
|
-
*/
|
|
157
|
-
abstract addUnusedAddress(address: string): Promise<void>;
|
|
158
|
-
/**
|
|
159
|
-
* Returns the wallet balance, separated between confirmed and unconfirmed balance (both in sats)
|
|
160
|
-
*/
|
|
161
|
-
abstract getBalance(): Promise<{confirmed: number, unconfirmed: number}>;
|
|
162
|
-
/**
|
|
163
|
-
* Returns the total spendable wallet balance in sats
|
|
164
|
-
*/
|
|
165
|
-
abstract getSpendableBalance(): Promise<number>;
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Returns all wallet transactions confirmed after the specified blockheight (includes also unconfirmed
|
|
169
|
-
* wallet transaction!!)
|
|
170
|
-
*
|
|
171
|
-
* @param startHeight
|
|
172
|
-
*/
|
|
173
|
-
abstract getWalletTransactions(startHeight?: number): Promise<BtcTx[]>;
|
|
174
|
-
/**
|
|
175
|
-
* Returns the in-wallet transaction as identified by its transaction ID
|
|
176
|
-
*
|
|
177
|
-
* @param txId
|
|
178
|
-
*/
|
|
179
|
-
abstract getWalletTransaction(txId: string): Promise<BtcTx | null>;
|
|
180
|
-
/**
|
|
181
|
-
* Subscribes to wallet transactions, should fire when transaction enters mempool, and then also
|
|
182
|
-
* for the first confirmation of the transactions
|
|
183
|
-
*
|
|
184
|
-
* @param callback
|
|
185
|
-
* @param abortSignal
|
|
186
|
-
*/
|
|
187
|
-
abstract subscribeToWalletTransactions(callback: (tx: BtcTx) => void, abortSignal?: AbortSignal): void;
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Estimates a network fee (in sats), for sending a specific PSBT, the provided PSBT might not contain
|
|
191
|
-
* any inputs, hence the fee returned should also reflect the transaction size increase by adding
|
|
192
|
-
* wallet UTXOs as inputs
|
|
193
|
-
*
|
|
194
|
-
* @param psbt
|
|
195
|
-
* @param feeRate
|
|
196
|
-
*/
|
|
197
|
-
abstract estimatePsbtFee(psbt: Transaction, feeRate?: number): Promise<{satsPerVbyte: number, networkFee: number}>;
|
|
198
|
-
/**
|
|
199
|
-
* Funds the provided PSBT (adds wallet UTXOs)
|
|
200
|
-
*
|
|
201
|
-
* @param psbt
|
|
202
|
-
* @param feeRate
|
|
203
|
-
* @param maxAllowedFeeRate
|
|
204
|
-
*/
|
|
205
|
-
abstract fundPsbt(psbt: Transaction, feeRate?: number, maxAllowedFeeRate?: number): Promise<Transaction>;
|
|
206
|
-
/**
|
|
207
|
-
* Signs the provided PSBT
|
|
208
|
-
*
|
|
209
|
-
* @param psbt
|
|
210
|
-
*/
|
|
211
|
-
abstract signPsbt(psbt: Transaction): Promise<SignPsbtResponse>;
|
|
212
|
-
/**
|
|
213
|
-
* Broadcasts a raw bitcoin hex encoded transaction
|
|
214
|
-
*
|
|
215
|
-
* @param tx
|
|
216
|
-
*/
|
|
217
|
-
abstract sendRawTransaction(tx: string): Promise<void>;
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Returns bitcoin network fee in sats/vB
|
|
221
|
-
*/
|
|
222
|
-
abstract getFeeRate(): Promise<number>;
|
|
223
|
-
/**
|
|
224
|
-
* Returns the blockheight of the bitcoin chain
|
|
225
|
-
*/
|
|
226
|
-
abstract getBlockheight(): Promise<number>;
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Post a task to be executed on the sequential thread of the wallet, in case wallets requires
|
|
230
|
-
* the UTXOs staying consistent during operation, it is recommended to implement this function
|
|
231
|
-
*
|
|
232
|
-
* @param executor
|
|
233
|
-
*/
|
|
234
|
-
execute(executor: () => Promise<void>): Promise<void> {
|
|
235
|
-
return executor();
|
|
236
|
-
}
|
|
237
|
-
|
|
1
|
+
import {BtcTx} from "@atomiqlabs/base";
|
|
2
|
+
import {Command} from "@atomiqlabs/server-base";
|
|
3
|
+
import {Address, OutScript, Transaction} from "@scure/btc-signer";
|
|
4
|
+
import {BTC_NETWORK} from "@scure/btc-signer/utils";
|
|
5
|
+
|
|
6
|
+
export type BitcoinUtxo = {
|
|
7
|
+
address: string,
|
|
8
|
+
type: "p2wpkh" | "p2sh-p2wpkh" | "p2tr",
|
|
9
|
+
confirmations: number,
|
|
10
|
+
outputScript: Buffer,
|
|
11
|
+
value: number,
|
|
12
|
+
txId: string,
|
|
13
|
+
vout: number
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type SignPsbtResponse = {
|
|
17
|
+
psbt: Transaction,
|
|
18
|
+
tx: Transaction,
|
|
19
|
+
raw: string,
|
|
20
|
+
txId: string,
|
|
21
|
+
networkFee: number
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export abstract class IBitcoinWallet {
|
|
25
|
+
|
|
26
|
+
readonly network: BTC_NETWORK;
|
|
27
|
+
|
|
28
|
+
protected constructor(network: BTC_NETWORK) {
|
|
29
|
+
this.network = network;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
toOutputScript(address: string): Buffer {
|
|
33
|
+
const outputScript = Address(this.network).decode(address);
|
|
34
|
+
switch(outputScript.type) {
|
|
35
|
+
case "pkh":
|
|
36
|
+
case "sh":
|
|
37
|
+
case "wpkh":
|
|
38
|
+
case "wsh":
|
|
39
|
+
return Buffer.from(OutScript.encode({
|
|
40
|
+
type: outputScript.type,
|
|
41
|
+
hash: outputScript.hash
|
|
42
|
+
}));
|
|
43
|
+
case "tr":
|
|
44
|
+
return Buffer.from(OutScript.encode({
|
|
45
|
+
type: "tr",
|
|
46
|
+
pubkey: outputScript.pubkey
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
throw new Error("Unrecognized address type");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getSignedTransaction(destination: string, amount: number, feeRate?: number, nonce?: bigint, maxAllowedFeeRate?: number): Promise<SignPsbtResponse> {
|
|
53
|
+
return this.getSignedMultiTransaction([{address: destination, amount}], feeRate, nonce, maxAllowedFeeRate);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async getSignedMultiTransaction(
|
|
57
|
+
destinations: {address: string, amount: number}[], feeRate?: number, nonce?: bigint, maxAllowedFeeRate?: number
|
|
58
|
+
): Promise<SignPsbtResponse> {
|
|
59
|
+
let locktime = 0;
|
|
60
|
+
let sequence = 0xFFFFFFFD;
|
|
61
|
+
//Apply nonce
|
|
62
|
+
if(nonce!=null) {
|
|
63
|
+
const locktimeBN = nonce >> 24n;
|
|
64
|
+
locktime = Number(locktimeBN) + 500000000;
|
|
65
|
+
if(locktime > (Date.now()/1000 - 24*60*60)) throw new Error("Invalid escrow nonce (locktime)!");
|
|
66
|
+
|
|
67
|
+
const sequenceBN = nonce & 0xFFFFFFn;
|
|
68
|
+
sequence = 0xFE000000 + Number(sequenceBN);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let psbt = new Transaction({lockTime: locktime});
|
|
72
|
+
destinations.forEach(dst => psbt.addOutput({
|
|
73
|
+
script: this.toOutputScript(dst.address),
|
|
74
|
+
amount: BigInt(dst.amount)
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
await this.fundPsbt(psbt, feeRate, maxAllowedFeeRate);
|
|
78
|
+
|
|
79
|
+
//Apply nonce
|
|
80
|
+
for(let i=0;i<psbt.inputsLength;i++) {
|
|
81
|
+
psbt.updateInput(i, {sequence});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return await this.signPsbt(psbt);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async estimateFee(destination: string, amount: number, feeRate?: number, feeRateMultiplier?: number): Promise<{satsPerVbyte: number, networkFee: number}> {
|
|
88
|
+
feeRate ??= await this.getFeeRate();
|
|
89
|
+
if(feeRateMultiplier!=null) feeRate = feeRate * feeRateMultiplier;
|
|
90
|
+
|
|
91
|
+
let psbt = new Transaction();
|
|
92
|
+
psbt.addOutput({
|
|
93
|
+
script: this.toOutputScript(destination),
|
|
94
|
+
amount: BigInt(amount)
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return await this.estimatePsbtFee(psbt, feeRate);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
drainAll(destination: string | Buffer, inputs: Omit<BitcoinUtxo, "address">[], feeRate?: number): Promise<SignPsbtResponse> {
|
|
101
|
+
throw new Error("Not implemented");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
burnAll(inputs: Omit<BitcoinUtxo, "address">[]): Promise<SignPsbtResponse> {
|
|
105
|
+
let psbt = new Transaction();
|
|
106
|
+
inputs.forEach(input => psbt.addInput({
|
|
107
|
+
txid: input.txId,
|
|
108
|
+
index: input.vout,
|
|
109
|
+
witnessUtxo: {
|
|
110
|
+
script: input.outputScript,
|
|
111
|
+
amount: BigInt(input.value)
|
|
112
|
+
},
|
|
113
|
+
sighashType: 0x01,
|
|
114
|
+
sequence: 0
|
|
115
|
+
}));
|
|
116
|
+
psbt.addOutput({
|
|
117
|
+
script: Buffer.concat([Buffer.from([0x6a, 20]), Buffer.from("BURN, BABY, BURN! AQ", "ascii")]),
|
|
118
|
+
amount: 0n
|
|
119
|
+
});
|
|
120
|
+
return this.signPsbt(psbt);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Initializes the wallet, called before any actions on the wallet
|
|
125
|
+
*/
|
|
126
|
+
abstract init(): Promise<void>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns whether the wallet is ready
|
|
130
|
+
*/
|
|
131
|
+
abstract isReady(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Returns the status defined string to be displayed in the status message
|
|
134
|
+
*/
|
|
135
|
+
abstract getStatus(): string;
|
|
136
|
+
/**
|
|
137
|
+
* Additional status information to be displayed in the status message
|
|
138
|
+
*/
|
|
139
|
+
abstract getStatusInfo(): Promise<Record<string, string>>;
|
|
140
|
+
/**
|
|
141
|
+
* Returns the commands that will be exposed
|
|
142
|
+
*/
|
|
143
|
+
abstract getCommands(): Command<any>[];
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Returns the address type of the wallet
|
|
147
|
+
*/
|
|
148
|
+
abstract getAddressType(): "p2wpkh" | "p2sh-p2wpkh" | "p2tr";
|
|
149
|
+
/**
|
|
150
|
+
* Returns an unused address suitable for receiving
|
|
151
|
+
*/
|
|
152
|
+
abstract getAddress(): Promise<string>;
|
|
153
|
+
/**
|
|
154
|
+
* Adds previously returned address (with getAddress call), to the pool of unused addresses
|
|
155
|
+
* @param address
|
|
156
|
+
*/
|
|
157
|
+
abstract addUnusedAddress(address: string): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Returns the wallet balance, separated between confirmed and unconfirmed balance (both in sats)
|
|
160
|
+
*/
|
|
161
|
+
abstract getBalance(): Promise<{confirmed: number, unconfirmed: number}>;
|
|
162
|
+
/**
|
|
163
|
+
* Returns the total spendable wallet balance in sats
|
|
164
|
+
*/
|
|
165
|
+
abstract getSpendableBalance(): Promise<number>;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Returns all wallet transactions confirmed after the specified blockheight (includes also unconfirmed
|
|
169
|
+
* wallet transaction!!)
|
|
170
|
+
*
|
|
171
|
+
* @param startHeight
|
|
172
|
+
*/
|
|
173
|
+
abstract getWalletTransactions(startHeight?: number): Promise<BtcTx[]>;
|
|
174
|
+
/**
|
|
175
|
+
* Returns the in-wallet transaction as identified by its transaction ID
|
|
176
|
+
*
|
|
177
|
+
* @param txId
|
|
178
|
+
*/
|
|
179
|
+
abstract getWalletTransaction(txId: string): Promise<BtcTx | null>;
|
|
180
|
+
/**
|
|
181
|
+
* Subscribes to wallet transactions, should fire when transaction enters mempool, and then also
|
|
182
|
+
* for the first confirmation of the transactions
|
|
183
|
+
*
|
|
184
|
+
* @param callback
|
|
185
|
+
* @param abortSignal
|
|
186
|
+
*/
|
|
187
|
+
abstract subscribeToWalletTransactions(callback: (tx: BtcTx) => void, abortSignal?: AbortSignal): void;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Estimates a network fee (in sats), for sending a specific PSBT, the provided PSBT might not contain
|
|
191
|
+
* any inputs, hence the fee returned should also reflect the transaction size increase by adding
|
|
192
|
+
* wallet UTXOs as inputs
|
|
193
|
+
*
|
|
194
|
+
* @param psbt
|
|
195
|
+
* @param feeRate
|
|
196
|
+
*/
|
|
197
|
+
abstract estimatePsbtFee(psbt: Transaction, feeRate?: number): Promise<{satsPerVbyte: number, networkFee: number}>;
|
|
198
|
+
/**
|
|
199
|
+
* Funds the provided PSBT (adds wallet UTXOs)
|
|
200
|
+
*
|
|
201
|
+
* @param psbt
|
|
202
|
+
* @param feeRate
|
|
203
|
+
* @param maxAllowedFeeRate
|
|
204
|
+
*/
|
|
205
|
+
abstract fundPsbt(psbt: Transaction, feeRate?: number, maxAllowedFeeRate?: number): Promise<Transaction>;
|
|
206
|
+
/**
|
|
207
|
+
* Signs the provided PSBT
|
|
208
|
+
*
|
|
209
|
+
* @param psbt
|
|
210
|
+
*/
|
|
211
|
+
abstract signPsbt(psbt: Transaction): Promise<SignPsbtResponse>;
|
|
212
|
+
/**
|
|
213
|
+
* Broadcasts a raw bitcoin hex encoded transaction
|
|
214
|
+
*
|
|
215
|
+
* @param tx
|
|
216
|
+
*/
|
|
217
|
+
abstract sendRawTransaction(tx: string): Promise<void>;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Returns bitcoin network fee in sats/vB
|
|
221
|
+
*/
|
|
222
|
+
abstract getFeeRate(): Promise<number>;
|
|
223
|
+
/**
|
|
224
|
+
* Returns the blockheight of the bitcoin chain
|
|
225
|
+
*/
|
|
226
|
+
abstract getBlockheight(): Promise<number>;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Post a task to be executed on the sequential thread of the wallet, in case wallets requires
|
|
230
|
+
* the UTXOs staying consistent during operation, it is recommended to implement this function
|
|
231
|
+
*
|
|
232
|
+
* @param executor
|
|
233
|
+
*/
|
|
234
|
+
execute(executor: () => Promise<void>): Promise<void> {
|
|
235
|
+
return executor();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
238
|
}
|