@atomiqlabs/lp-lib 11.0.5 → 12.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/info/InfoHandler.js +3 -12
- package/dist/plugins/IPlugin.d.ts +34 -35
- package/dist/plugins/IPlugin.js +7 -8
- package/dist/plugins/PluginManager.d.ts +29 -30
- package/dist/plugins/PluginManager.js +160 -188
- package/dist/prices/BinanceSwapPrice.d.ts +1 -2
- package/dist/prices/BinanceSwapPrice.js +56 -70
- package/dist/prices/CoinGeckoSwapPrice.d.ts +2 -3
- package/dist/prices/CoinGeckoSwapPrice.js +30 -42
- package/dist/prices/OKXSwapPrice.d.ts +1 -2
- package/dist/prices/OKXSwapPrice.js +56 -70
- package/dist/storage/IIntermediaryStorage.d.ts +8 -5
- package/dist/storagemanager/IntermediaryStorageManager.d.ts +8 -5
- package/dist/storagemanager/IntermediaryStorageManager.js +52 -61
- package/dist/storagemanager/StorageManager.js +42 -59
- package/dist/swaps/FromBtcBaseSwap.d.ts +7 -8
- package/dist/swaps/FromBtcBaseSwap.js +2 -3
- package/dist/swaps/FromBtcBaseSwapHandler.d.ts +44 -31
- package/dist/swaps/FromBtcBaseSwapHandler.js +217 -196
- package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +1 -2
- package/dist/swaps/FromBtcLnBaseSwapHandler.js +13 -24
- package/dist/swaps/ISwapPrice.d.ts +4 -5
- package/dist/swaps/ISwapPrice.js +8 -30
- package/dist/swaps/SwapHandler.d.ts +26 -15
- package/dist/swaps/SwapHandler.js +107 -66
- package/dist/swaps/SwapHandlerSwap.d.ts +22 -11
- package/dist/swaps/SwapHandlerSwap.js +32 -8
- package/dist/swaps/ToBtcBaseSwap.d.ts +16 -17
- package/dist/swaps/ToBtcBaseSwap.js +4 -4
- package/dist/swaps/ToBtcBaseSwapHandler.d.ts +17 -17
- package/dist/swaps/ToBtcBaseSwapHandler.js +140 -155
- package/dist/swaps/frombtc_abstract/FromBtcAbs.d.ts +8 -15
- package/dist/swaps/frombtc_abstract/FromBtcAbs.js +131 -196
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.d.ts +3 -5
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.js +4 -4
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.d.ts +10 -8
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.js +330 -362
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.d.ts +10 -10
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.js +7 -4
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.d.ts +8 -8
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.js +330 -400
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +10 -4
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.js +36 -6
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.d.ts +8 -7
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.js +251 -273
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +5 -5
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.js +7 -5
- package/dist/swaps/tobtc_abstract/ToBtcAbs.d.ts +13 -12
- package/dist/swaps/tobtc_abstract/ToBtcAbs.js +261 -323
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.d.ts +4 -4
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.js +7 -6
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.d.ts +22 -21
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.js +398 -453
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +3 -2
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.js +10 -6
- package/dist/utils/Utils.d.ts +2 -3
- package/dist/utils/Utils.js +4 -14
- package/dist/utils/paramcoders/LegacyParamEncoder.js +3 -14
- package/dist/utils/paramcoders/ParamDecoder.js +53 -65
- package/dist/utils/paramcoders/SchemaVerifier.d.ts +4 -5
- package/dist/utils/paramcoders/SchemaVerifier.js +8 -9
- package/dist/utils/paramcoders/server/ServerParamDecoder.js +1 -1
- package/dist/utils/paramcoders/server/ServerParamEncoder.js +3 -14
- package/dist/wallets/IBitcoinWallet.d.ts +4 -5
- package/dist/wallets/ILightningWallet.d.ts +20 -21
- package/dist/wallets/ILightningWallet.js +1 -1
- package/package.json +4 -6
- package/src/plugins/IPlugin.ts +28 -29
- package/src/plugins/PluginManager.ts +21 -22
- package/src/prices/BinanceSwapPrice.ts +3 -4
- package/src/prices/CoinGeckoSwapPrice.ts +4 -5
- package/src/prices/OKXSwapPrice.ts +3 -4
- package/src/storage/IIntermediaryStorage.ts +4 -5
- package/src/storagemanager/IntermediaryStorageManager.ts +17 -9
- package/src/swaps/FromBtcBaseSwap.ts +9 -10
- package/src/swaps/FromBtcBaseSwapHandler.ts +133 -91
- package/src/swaps/FromBtcLnBaseSwapHandler.ts +2 -3
- package/src/swaps/ISwapPrice.ts +10 -20
- package/src/swaps/SwapHandler.ts +101 -35
- package/src/swaps/SwapHandlerSwap.ts +42 -17
- package/src/swaps/ToBtcBaseSwap.ts +20 -18
- package/src/swaps/ToBtcBaseSwapHandler.ts +33 -33
- package/src/swaps/frombtc_abstract/FromBtcAbs.ts +64 -97
- package/src/swaps/frombtc_abstract/FromBtcSwapAbs.ts +7 -8
- package/src/swaps/frombtc_trusted/FromBtcTrusted.ts +56 -55
- package/src/swaps/frombtc_trusted/FromBtcTrustedSwap.ts +28 -21
- package/src/swaps/frombtcln_abstract/FromBtcLnAbs.ts +81 -116
- package/src/swaps/frombtcln_abstract/FromBtcLnSwapAbs.ts +73 -9
- package/src/swaps/frombtcln_trusted/FromBtcLnTrusted.ts +39 -36
- package/src/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.ts +26 -12
- package/src/swaps/tobtc_abstract/ToBtcAbs.ts +82 -98
- package/src/swaps/tobtc_abstract/ToBtcSwapAbs.ts +25 -20
- package/src/swaps/tobtcln_abstract/ToBtcLnAbs.ts +106 -118
- package/src/swaps/tobtcln_abstract/ToBtcLnSwapAbs.ts +17 -9
- package/src/utils/Utils.ts +3 -4
- package/src/utils/paramcoders/ParamDecoder.ts +5 -5
- package/src/utils/paramcoders/SchemaVerifier.ts +10 -11
- package/src/utils/paramcoders/server/ServerParamDecoder.ts +1 -1
- package/src/wallets/IBitcoinWallet.ts +4 -5
- package/src/wallets/ILightningWallet.ts +21 -22
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {Express, Request, Response} from "express";
|
|
2
|
-
import * as BN from "bn.js";
|
|
3
2
|
import {ToBtcSwapAbs, ToBtcSwapState} from "./ToBtcSwapAbs";
|
|
4
3
|
import {MultichainData, SwapHandlerType} from "../SwapHandler";
|
|
5
4
|
import {ISwapPrice} from "../ISwapPrice";
|
|
@@ -11,8 +10,8 @@ import {
|
|
|
11
10
|
RefundEvent,
|
|
12
11
|
SwapCommitStatus,
|
|
13
12
|
SwapData,
|
|
14
|
-
BitcoinRpc,
|
|
15
|
-
BtcBlock
|
|
13
|
+
BitcoinRpc,
|
|
14
|
+
BtcBlock, BigIntBufferUtils
|
|
16
15
|
} from "@atomiqlabs/base";
|
|
17
16
|
import {expressHandlerWrapper, HEX_REGEX, isDefinedRuntimeError} from "../../utils/Utils";
|
|
18
17
|
import {PluginManager} from "../../plugins/PluginManager";
|
|
@@ -29,9 +28,9 @@ import {IBitcoinWallet} from "../../wallets/IBitcoinWallet";
|
|
|
29
28
|
const OUTPUT_SCRIPT_MAX_LENGTH = 200;
|
|
30
29
|
|
|
31
30
|
export type ToBtcConfig = ToBtcBaseConfig & {
|
|
32
|
-
sendSafetyFactor:
|
|
31
|
+
sendSafetyFactor: bigint,
|
|
33
32
|
|
|
34
|
-
minChainCltv:
|
|
33
|
+
minChainCltv: bigint,
|
|
35
34
|
|
|
36
35
|
networkFeeMultiplier: number,
|
|
37
36
|
minConfirmations: number,
|
|
@@ -44,10 +43,10 @@ export type ToBtcConfig = ToBtcBaseConfig & {
|
|
|
44
43
|
|
|
45
44
|
export type ToBtcRequestType = {
|
|
46
45
|
address: string,
|
|
47
|
-
amount:
|
|
46
|
+
amount: bigint,
|
|
48
47
|
confirmationTarget: number,
|
|
49
48
|
confirmations: number,
|
|
50
|
-
nonce:
|
|
49
|
+
nonce: bigint,
|
|
51
50
|
token: string,
|
|
52
51
|
offerer: string,
|
|
53
52
|
exactIn?: boolean
|
|
@@ -58,6 +57,7 @@ export type ToBtcRequestType = {
|
|
|
58
57
|
*/
|
|
59
58
|
export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState> {
|
|
60
59
|
readonly type = SwapHandlerType.TO_BTC;
|
|
60
|
+
readonly swapType = ChainSwapType.CHAIN_NONCED;
|
|
61
61
|
|
|
62
62
|
activeSubscriptions: {[txId: string]: ToBtcSwapAbs} = {};
|
|
63
63
|
bitcoinRpc: BitcoinRpc<BtcBlock>;
|
|
@@ -86,13 +86,14 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
86
86
|
*
|
|
87
87
|
* @param chainIdentifier
|
|
88
88
|
* @param address
|
|
89
|
+
* @param confirmations
|
|
89
90
|
* @param nonce
|
|
90
91
|
* @param amount
|
|
91
92
|
*/
|
|
92
|
-
private getHash(chainIdentifier: string, address: string, nonce:
|
|
93
|
+
private getHash(chainIdentifier: string, address: string, confirmations: number, nonce: bigint, amount: bigint): Buffer {
|
|
93
94
|
const parsedOutputScript = this.bitcoin.toOutputScript(address);
|
|
94
95
|
const {swapContract} = this.getChain(chainIdentifier);
|
|
95
|
-
return swapContract.getHashForOnchain(parsedOutputScript, amount, nonce);
|
|
96
|
+
return swapContract.getHashForOnchain(parsedOutputScript, amount, confirmations, nonce);
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
/**
|
|
@@ -113,9 +114,19 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
113
114
|
|
|
114
115
|
try {
|
|
115
116
|
this.swapLogger.debug(swap, "tryClaimSwap(): initiate claim of swap, height: "+blockHeader.getHeight()+" utxo: "+tx.txid+":"+vout);
|
|
116
|
-
const result = await swapContract.claimWithTxData(
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
const result = await swapContract.claimWithTxData(
|
|
118
|
+
signer,
|
|
119
|
+
swap.data,
|
|
120
|
+
{...tx, height: blockHeader.getHeight()},
|
|
121
|
+
swap.requiredConfirmations,
|
|
122
|
+
vout,
|
|
123
|
+
null,
|
|
124
|
+
null,
|
|
125
|
+
false,
|
|
126
|
+
{
|
|
127
|
+
waitForConfirmation: true
|
|
128
|
+
}
|
|
129
|
+
);
|
|
119
130
|
this.swapLogger.info(swap, "tryClaimSwap(): swap claimed successfully, height: "+blockHeader.getHeight()+" utxo: "+tx.txid+":"+vout+" address: "+swap.address);
|
|
120
131
|
if(swap.metadata!=null) swap.metadata.times.txClaimed = Date.now();
|
|
121
132
|
unlock();
|
|
@@ -139,14 +150,14 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
139
150
|
} else {
|
|
140
151
|
this.swapLogger.info(swap, "processPastSwap(state=SAVED): swap committed (detected from processPastSwap), address: "+swap.address);
|
|
141
152
|
await swap.setState(ToBtcSwapState.COMMITED);
|
|
142
|
-
await this.
|
|
153
|
+
await this.saveSwapData(swap);
|
|
143
154
|
}
|
|
144
155
|
return;
|
|
145
156
|
}
|
|
146
157
|
}
|
|
147
158
|
|
|
148
159
|
if(swap.state===ToBtcSwapState.NON_PAYABLE || swap.state===ToBtcSwapState.SAVED) {
|
|
149
|
-
if(swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
160
|
+
if(await swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
150
161
|
this.swapLogger.info(swap, "processPastSwap(state=NON_PAYABLE|SAVED): swap expired, cancelling, address: "+swap.address);
|
|
151
162
|
await this.removeSwapData(swap, ToBtcSwapState.CANCELED);
|
|
152
163
|
return;
|
|
@@ -194,7 +205,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
194
205
|
}
|
|
195
206
|
]);
|
|
196
207
|
|
|
197
|
-
for(let swap of queriedData) {
|
|
208
|
+
for(let {obj: swap} of queriedData) {
|
|
198
209
|
await this.processPastSwap(swap);
|
|
199
210
|
}
|
|
200
211
|
}
|
|
@@ -203,7 +214,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
203
214
|
tx.confirmations = tx.confirmations || 0;
|
|
204
215
|
|
|
205
216
|
//Check transaction has enough confirmations
|
|
206
|
-
const hasEnoughConfirmations = tx.confirmations>=swap.
|
|
217
|
+
const hasEnoughConfirmations = tx.confirmations>=swap.requiredConfirmations;
|
|
207
218
|
if(!hasEnoughConfirmations) {
|
|
208
219
|
return false;
|
|
209
220
|
}
|
|
@@ -212,7 +223,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
212
223
|
|
|
213
224
|
//Search for required transaction output (vout)
|
|
214
225
|
const outputScript = this.bitcoin.toOutputScript(swap.address);
|
|
215
|
-
const vout = tx.outs.find(e =>
|
|
226
|
+
const vout = tx.outs.find(e => BigInt(e.value)===swap.amount && Buffer.from(e.scriptPubKey.hex, "hex").equals(outputScript));
|
|
216
227
|
if(vout==null) {
|
|
217
228
|
this.swapLogger.warn(swap, "processBtcTx(): cannot find correct vout,"+
|
|
218
229
|
" required output script: "+outputScript.toString("hex")+
|
|
@@ -282,10 +293,10 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
282
293
|
* @throws DefinedRuntimeError will throw an error in case there isn't enough time for us to send a BTC payout tx
|
|
283
294
|
*/
|
|
284
295
|
protected checkExpiresTooSoon(swap: ToBtcSwapAbs): void {
|
|
285
|
-
const currentTimestamp =
|
|
286
|
-
const tsDelta = swap.data.getExpiry()
|
|
287
|
-
const minRequiredCLTV = this.getExpiryFromCLTV(swap.preferedConfirmationTarget, swap.
|
|
288
|
-
const hasRequiredCLTVDelta = tsDelta
|
|
296
|
+
const currentTimestamp = BigInt(Math.floor(Date.now()/1000));
|
|
297
|
+
const tsDelta = swap.data.getExpiry() - currentTimestamp;
|
|
298
|
+
const minRequiredCLTV = this.getExpiryFromCLTV(swap.preferedConfirmationTarget, swap.requiredConfirmations);
|
|
299
|
+
const hasRequiredCLTVDelta = tsDelta >= minRequiredCLTV;
|
|
289
300
|
if(!hasRequiredCLTVDelta) throw {
|
|
290
301
|
code: 90001,
|
|
291
302
|
msg: "TS delta too low",
|
|
@@ -304,8 +315,8 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
304
315
|
* @private
|
|
305
316
|
* @throws DefinedRuntimeError will throw an error in case the actual fee is higher than quoted fee
|
|
306
317
|
*/
|
|
307
|
-
protected checkCalculatedTxFee(quotedSatsPerVbyte:
|
|
308
|
-
const swapPaysEnoughNetworkFee = quotedSatsPerVbyte
|
|
318
|
+
protected checkCalculatedTxFee(quotedSatsPerVbyte: bigint, actualSatsPerVbyte: bigint): void {
|
|
319
|
+
const swapPaysEnoughNetworkFee = quotedSatsPerVbyte >= actualSatsPerVbyte;
|
|
309
320
|
if(!swapPaysEnoughNetworkFee) throw {
|
|
310
321
|
code: 90003,
|
|
311
322
|
msg: "Fee changed too much!",
|
|
@@ -332,15 +343,15 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
332
343
|
if(swap.metadata!=null) swap.metadata.times.payCLTVChecked = Date.now();
|
|
333
344
|
|
|
334
345
|
const satsPerVbyte = await this.bitcoin.getFeeRate();
|
|
335
|
-
this.checkCalculatedTxFee(swap.satsPerVbyte,
|
|
346
|
+
this.checkCalculatedTxFee(swap.satsPerVbyte, BigInt(satsPerVbyte));
|
|
336
347
|
if(swap.metadata!=null) swap.metadata.times.payChainFee = Date.now();
|
|
337
348
|
|
|
338
349
|
const signResult = await this.bitcoin.getSignedTransaction(
|
|
339
350
|
swap.address,
|
|
340
|
-
swap.amount
|
|
351
|
+
Number(swap.amount),
|
|
341
352
|
satsPerVbyte,
|
|
342
|
-
swap.
|
|
343
|
-
swap.satsPerVbyte
|
|
353
|
+
swap.nonce,
|
|
354
|
+
Number(swap.satsPerVbyte)
|
|
344
355
|
);
|
|
345
356
|
if(signResult==null) throw {
|
|
346
357
|
code: 90002,
|
|
@@ -349,17 +360,17 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
349
360
|
if(swap.metadata!=null) swap.metadata.times.paySignPSBT = Date.now();
|
|
350
361
|
|
|
351
362
|
this.swapLogger.debug(swap, "sendBitcoinPayment(): signed raw transaction: "+signResult.raw);
|
|
352
|
-
swap.txId = signResult.tx.
|
|
353
|
-
swap.setRealNetworkFee(
|
|
363
|
+
swap.txId = signResult.tx.id;
|
|
364
|
+
swap.setRealNetworkFee(BigInt(signResult.networkFee));
|
|
354
365
|
await swap.setState(ToBtcSwapState.BTC_SENDING);
|
|
355
|
-
await this.
|
|
366
|
+
await this.saveSwapData(swap);
|
|
356
367
|
|
|
357
368
|
await this.bitcoin.sendRawTransaction(signResult.raw);
|
|
358
369
|
if(swap.metadata!=null) swap.metadata.times.payTxSent = Date.now();
|
|
359
|
-
this.swapLogger.info(swap, "sendBitcoinPayment(): btc transaction generated, signed & broadcasted, txId: "+
|
|
370
|
+
this.swapLogger.info(swap, "sendBitcoinPayment(): btc transaction generated, signed & broadcasted, txId: "+swap.txId+" address: "+swap.address);
|
|
360
371
|
|
|
361
372
|
await swap.setState(ToBtcSwapState.BTC_SENT);
|
|
362
|
-
await this.
|
|
373
|
+
await this.saveSwapData(swap);
|
|
363
374
|
});
|
|
364
375
|
}
|
|
365
376
|
|
|
@@ -381,14 +392,14 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
381
392
|
} else {
|
|
382
393
|
this.swapLogger.info(swap, "processInitialized(state=BTC_SENDING): btc transaction found, advancing to BTC_SENT state, txId: "+swap.txId+" address: "+swap.address);
|
|
383
394
|
await swap.setState(ToBtcSwapState.BTC_SENT);
|
|
384
|
-
await this.
|
|
395
|
+
await this.saveSwapData(swap);
|
|
385
396
|
}
|
|
386
397
|
}
|
|
387
398
|
|
|
388
399
|
if(swap.state===ToBtcSwapState.SAVED) {
|
|
389
400
|
this.swapLogger.info(swap, "processInitialized(state=SAVED): advancing to COMMITED state, address: "+swap.address);
|
|
390
401
|
await swap.setState(ToBtcSwapState.COMMITED);
|
|
391
|
-
await this.
|
|
402
|
+
await this.saveSwapData(swap);
|
|
392
403
|
}
|
|
393
404
|
|
|
394
405
|
if(swap.state===ToBtcSwapState.COMMITED) {
|
|
@@ -405,7 +416,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
405
416
|
this.swapLogger.error(swap, "processInitialized(state=COMMITED): setting state to NON_PAYABLE due to send bitcoin payment error", e);
|
|
406
417
|
if(swap.metadata!=null) swap.metadata.payError = e;
|
|
407
418
|
await swap.setState(ToBtcSwapState.NON_PAYABLE);
|
|
408
|
-
await this.
|
|
419
|
+
await this.saveSwapData(swap);
|
|
409
420
|
} else {
|
|
410
421
|
this.swapLogger.error(swap, "processInitialized(state=COMMITED): send bitcoin payment error", e);
|
|
411
422
|
throw e;
|
|
@@ -420,30 +431,13 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
420
431
|
this.subscribeToPayment(swap);
|
|
421
432
|
}
|
|
422
433
|
|
|
423
|
-
protected async processInitializeEvent(chainIdentifier: string, event: InitializeEvent<SwapData>): Promise<void> {
|
|
424
|
-
if(event.swapType!==ChainSwapType.CHAIN_NONCED) return;
|
|
425
|
-
|
|
426
|
-
const paymentHash = event.paymentHash;
|
|
427
|
-
|
|
428
|
-
const swap = await this.storageManager.getData(paymentHash, event.sequence);
|
|
429
|
-
if(swap==null || swap.chainIdentifier!==chainIdentifier) return;
|
|
430
|
-
|
|
431
|
-
swap.txIds.init = (event as any).meta?.txId;
|
|
432
|
-
if(swap.metadata!=null) swap.metadata.times.txReceived = Date.now();
|
|
433
|
-
|
|
434
|
+
protected async processInitializeEvent(chainIdentifier: string, swap: ToBtcSwapAbs, event: InitializeEvent<SwapData>): Promise<void> {
|
|
434
435
|
this.swapLogger.info(swap, "SC: InitializeEvent: swap initialized by the client, address: "+swap.address);
|
|
435
436
|
|
|
436
437
|
await this.processInitialized(swap);
|
|
437
438
|
}
|
|
438
439
|
|
|
439
|
-
protected async processClaimEvent(chainIdentifier: string, event: ClaimEvent<SwapData>): Promise<void> {
|
|
440
|
-
const paymentHash = event.paymentHash;
|
|
441
|
-
|
|
442
|
-
const swap = await this.storageManager.getData(paymentHash, event.sequence);
|
|
443
|
-
if(swap==null || swap.chainIdentifier!==chainIdentifier) return;
|
|
444
|
-
|
|
445
|
-
swap.txIds.claim = (event as any).meta?.txId;
|
|
446
|
-
|
|
440
|
+
protected async processClaimEvent(chainIdentifier: string, swap: ToBtcSwapAbs, event: ClaimEvent<SwapData>): Promise<void> {
|
|
447
441
|
this.swapLogger.info(swap, "SC: ClaimEvent: swap successfully claimed to us, address: "+swap.address);
|
|
448
442
|
|
|
449
443
|
//Also remove transaction from active subscriptions
|
|
@@ -451,14 +445,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
451
445
|
await this.removeSwapData(swap, ToBtcSwapState.CLAIMED);
|
|
452
446
|
}
|
|
453
447
|
|
|
454
|
-
protected async processRefundEvent(chainIdentifier: string, event: RefundEvent<SwapData>): Promise<void> {
|
|
455
|
-
const paymentHash = event.paymentHash;
|
|
456
|
-
|
|
457
|
-
const swap = await this.storageManager.getData(paymentHash, event.sequence);
|
|
458
|
-
if(swap==null || swap.chainIdentifier!==chainIdentifier) return;
|
|
459
|
-
|
|
460
|
-
swap.txIds.refund = (event as any).meta?.txId;
|
|
461
|
-
|
|
448
|
+
protected async processRefundEvent(chainIdentifier: string, swap: ToBtcSwapAbs, event: RefundEvent<SwapData>): Promise<void> {
|
|
462
449
|
this.swapLogger.info(swap, "SC: RefundEvent: swap successfully refunded by the user, address: "+swap.address);
|
|
463
450
|
|
|
464
451
|
//Also remove transaction from active subscriptions
|
|
@@ -472,14 +459,14 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
472
459
|
* @param confirmationTarget
|
|
473
460
|
* @param confirmations
|
|
474
461
|
*/
|
|
475
|
-
protected getExpiryFromCLTV(confirmationTarget: number, confirmations: number):
|
|
462
|
+
protected getExpiryFromCLTV(confirmationTarget: number, confirmations: number): bigint {
|
|
476
463
|
//Blocks = 10 + (confirmations + confirmationTarget)*2
|
|
477
464
|
//Time = 3600 + (600*blocks*2)
|
|
478
|
-
const cltv = this.config.minChainCltv
|
|
479
|
-
|
|
465
|
+
const cltv = this.config.minChainCltv + (
|
|
466
|
+
BigInt(confirmations + confirmationTarget) * this.config.sendSafetyFactor
|
|
480
467
|
);
|
|
481
468
|
|
|
482
|
-
return this.config.gracePeriod
|
|
469
|
+
return this.config.gracePeriod + (this.config.bitcoinBlocktime * cltv * this.config.safetyFactor);
|
|
483
470
|
}
|
|
484
471
|
|
|
485
472
|
/**
|
|
@@ -488,17 +475,16 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
488
475
|
* @param nonce
|
|
489
476
|
* @throws {DefinedRuntimeError} will throw an error if the nonce is invalid
|
|
490
477
|
*/
|
|
491
|
-
private checkNonceValid(nonce:
|
|
492
|
-
if(nonce
|
|
478
|
+
private checkNonceValid(nonce: bigint): void {
|
|
479
|
+
if(nonce < 0 || nonce >= (2n ** 64n)) throw {
|
|
493
480
|
code: 20021,
|
|
494
481
|
msg: "Invalid request body (nonce - cannot be parsed)"
|
|
495
482
|
};
|
|
496
483
|
|
|
497
|
-
const
|
|
498
|
-
const firstPart = new BN(nonceBuffer.slice(0, 5), "be");
|
|
484
|
+
const firstPart = nonce >> 24n;
|
|
499
485
|
|
|
500
|
-
const maxAllowedValue =
|
|
501
|
-
if(firstPart
|
|
486
|
+
const maxAllowedValue = BigInt(Math.floor(Date.now()/1000)-600000000);
|
|
487
|
+
if(firstPart > maxAllowedValue) throw {
|
|
502
488
|
code: 20022,
|
|
503
489
|
msg: "Invalid request body (nonce - too high)"
|
|
504
490
|
};
|
|
@@ -568,9 +554,9 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
568
554
|
* @param swap
|
|
569
555
|
* @throws {DefinedRuntimeError} will throw an error if the swap is expired
|
|
570
556
|
*/
|
|
571
|
-
protected checkExpired(swap: ToBtcSwapAbs) {
|
|
557
|
+
protected async checkExpired(swap: ToBtcSwapAbs) {
|
|
572
558
|
const {swapContract, signer} = this.getChain(swap.chainIdentifier);
|
|
573
|
-
const isExpired = swapContract.isExpired(signer.getAddress(), swap.data);
|
|
559
|
+
const isExpired = await swapContract.isExpired(signer.getAddress(), swap.data);
|
|
574
560
|
if(isExpired) throw {
|
|
575
561
|
_httpStatus: 200,
|
|
576
562
|
code: 20010,
|
|
@@ -585,8 +571,8 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
585
571
|
* @param amount
|
|
586
572
|
* @throws {DefinedRuntimeError} will throw an error if there are not enough BTC funds
|
|
587
573
|
*/
|
|
588
|
-
private async checkAndGetNetworkFee(address: string, amount:
|
|
589
|
-
let chainFeeResp = await this.bitcoin.estimateFee(address, amount
|
|
574
|
+
private async checkAndGetNetworkFee(address: string, amount: bigint): Promise<{ networkFee: bigint, satsPerVbyte: bigint }> {
|
|
575
|
+
let chainFeeResp = await this.bitcoin.estimateFee(address, Number(amount), null, this.config.networkFeeMultiplier);
|
|
590
576
|
|
|
591
577
|
const hasEnoughFunds = chainFeeResp!=null;
|
|
592
578
|
if(!hasEnoughFunds) throw {
|
|
@@ -595,8 +581,8 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
595
581
|
};
|
|
596
582
|
|
|
597
583
|
return {
|
|
598
|
-
networkFee:
|
|
599
|
-
satsPerVbyte:
|
|
584
|
+
networkFee: BigInt(chainFeeResp.networkFee),
|
|
585
|
+
satsPerVbyte: BigInt(chainFeeResp.satsPerVbyte)
|
|
600
586
|
};
|
|
601
587
|
}
|
|
602
588
|
|
|
@@ -628,10 +614,10 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
628
614
|
*/
|
|
629
615
|
const parsedBody: ToBtcRequestType = await req.paramReader.getParams({
|
|
630
616
|
address: FieldTypeEnum.String,
|
|
631
|
-
amount: FieldTypeEnum.
|
|
617
|
+
amount: FieldTypeEnum.BigInt,
|
|
632
618
|
confirmationTarget: FieldTypeEnum.Number,
|
|
633
619
|
confirmations: FieldTypeEnum.Number,
|
|
634
|
-
nonce: FieldTypeEnum.
|
|
620
|
+
nonce: FieldTypeEnum.BigInt,
|
|
635
621
|
token: (val: string) => val!=null &&
|
|
636
622
|
typeof(val)==="string" &&
|
|
637
623
|
this.isTokenSupported(chainIdentifier, val) ? val : null,
|
|
@@ -678,7 +664,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
678
664
|
swapFee,
|
|
679
665
|
swapFeeInToken,
|
|
680
666
|
networkFeeInToken
|
|
681
|
-
} = await this.checkToBtcAmount(request, requestedAmount, fees, useToken, async (amount:
|
|
667
|
+
} = await this.checkToBtcAmount(request, requestedAmount, fees, useToken, async (amount: bigint) => {
|
|
682
668
|
metadata.times.amountsChecked = Date.now();
|
|
683
669
|
const resp = await this.checkAndGetNetworkFee(parsedBody.address, amount);
|
|
684
670
|
metadata.times.chainFeeCalculated = Date.now();
|
|
@@ -686,14 +672,14 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
686
672
|
}, abortController.signal, pricePrefetchPromise);
|
|
687
673
|
metadata.times.priceCalculated = Date.now();
|
|
688
674
|
|
|
689
|
-
const paymentHash = this.getHash(chainIdentifier, parsedBody.address, parsedBody.nonce, amountBD).toString("hex");
|
|
675
|
+
const paymentHash = this.getHash(chainIdentifier, parsedBody.address, parsedBody.confirmations, parsedBody.nonce, amountBD).toString("hex");
|
|
690
676
|
|
|
691
677
|
//Add grace period another time, so the user has 1 hour to commit
|
|
692
|
-
const expirySeconds = this.getExpiryFromCLTV(parsedBody.confirmationTarget, parsedBody.confirmations)
|
|
693
|
-
const currentTimestamp =
|
|
694
|
-
const minRequiredExpiry = currentTimestamp
|
|
678
|
+
const expirySeconds = this.getExpiryFromCLTV(parsedBody.confirmationTarget, parsedBody.confirmations) + this.config.gracePeriod;
|
|
679
|
+
const currentTimestamp = BigInt(Math.floor(Date.now()/1000));
|
|
680
|
+
const minRequiredExpiry = currentTimestamp + expirySeconds;
|
|
695
681
|
|
|
696
|
-
const sequence =
|
|
682
|
+
const sequence = BigIntBufferUtils.fromBuffer(randomBytes(8));
|
|
697
683
|
const payObject: SwapData = await swapContract.createSwapData(
|
|
698
684
|
ChainSwapType.CHAIN_NONCED,
|
|
699
685
|
parsedBody.offerer,
|
|
@@ -703,12 +689,10 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
703
689
|
paymentHash,
|
|
704
690
|
sequence,
|
|
705
691
|
minRequiredExpiry,
|
|
706
|
-
parsedBody.nonce,
|
|
707
|
-
parsedBody.confirmations,
|
|
708
692
|
true,
|
|
709
693
|
false,
|
|
710
|
-
|
|
711
|
-
|
|
694
|
+
0n,
|
|
695
|
+
0n
|
|
712
696
|
);
|
|
713
697
|
abortController.signal.throwIfAborted();
|
|
714
698
|
metadata.times.swapCreated = Date.now();
|
|
@@ -726,6 +710,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
726
710
|
networkFeeInToken,
|
|
727
711
|
networkFeeData.satsPerVbyte,
|
|
728
712
|
parsedBody.nonce,
|
|
713
|
+
parsedBody.confirmations,
|
|
729
714
|
parsedBody.confirmationTarget
|
|
730
715
|
);
|
|
731
716
|
createdSwap.data = payObject;
|
|
@@ -736,7 +721,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
736
721
|
createdSwap.feeRate = sigData.feeRate;
|
|
737
722
|
|
|
738
723
|
await PluginManager.swapCreate(createdSwap);
|
|
739
|
-
await this.
|
|
724
|
+
await this.saveSwapData(createdSwap);
|
|
740
725
|
|
|
741
726
|
this.swapLogger.info(createdSwap, "REST: /payInvoice: created swap address: "+createdSwap.address+" amount: "+amountBD.toString(10));
|
|
742
727
|
|
|
@@ -749,7 +734,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
749
734
|
satsPervByte: networkFeeData.satsPerVbyte.toString(10),
|
|
750
735
|
networkFee: networkFeeInToken.toString(10),
|
|
751
736
|
swapFee: swapFeeInToken.toString(10),
|
|
752
|
-
totalFee: swapFeeInToken
|
|
737
|
+
totalFee: (swapFeeInToken + networkFeeInToken).toString(10),
|
|
753
738
|
total: totalInToken.toString(10),
|
|
754
739
|
minRequiredExpiry: minRequiredExpiry.toString(10),
|
|
755
740
|
|
|
@@ -771,9 +756,8 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
771
756
|
const parsedBody = verifySchema({...req.body, ...req.query}, {
|
|
772
757
|
paymentHash: (val: string) => val!=null &&
|
|
773
758
|
typeof(val)==="string" &&
|
|
774
|
-
val.length===64 &&
|
|
775
759
|
HEX_REGEX.test(val) ? val: null,
|
|
776
|
-
sequence: FieldTypeEnum.
|
|
760
|
+
sequence: FieldTypeEnum.BigInt
|
|
777
761
|
});
|
|
778
762
|
if (parsedBody==null) throw {
|
|
779
763
|
code: 20100,
|
|
@@ -789,7 +773,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
789
773
|
msg: "Payment not found"
|
|
790
774
|
};
|
|
791
775
|
|
|
792
|
-
this.checkExpired(payment);
|
|
776
|
+
await this.checkExpired(payment);
|
|
793
777
|
|
|
794
778
|
if (payment.state === ToBtcSwapState.COMMITED) throw {
|
|
795
779
|
_httpStatus: 200,
|
|
@@ -815,7 +799,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
815
799
|
msg: "Not committed"
|
|
816
800
|
};
|
|
817
801
|
|
|
818
|
-
const refundResponse = await swapContract.getRefundSignature(signer, payment.data, this.config.
|
|
802
|
+
const refundResponse = await swapContract.getRefundSignature(signer, payment.data, this.config.refundAuthorizationTimeout);
|
|
819
803
|
|
|
820
804
|
//Double check the state after promise result
|
|
821
805
|
if (payment.state !== ToBtcSwapState.NON_PAYABLE) throw {
|
|
@@ -869,14 +853,14 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
869
853
|
}
|
|
870
854
|
|
|
871
855
|
async init() {
|
|
872
|
-
await this.
|
|
856
|
+
await this.loadData(ToBtcSwapAbs);
|
|
873
857
|
this.subscribeToEvents();
|
|
874
858
|
await PluginManager.serviceInitialize(this);
|
|
875
859
|
}
|
|
876
860
|
|
|
877
861
|
getInfoData(): any {
|
|
878
862
|
return {
|
|
879
|
-
minCltv: this.config.minChainCltv
|
|
863
|
+
minCltv: Number(this.config.minChainCltv),
|
|
880
864
|
|
|
881
865
|
minConfirmations: this.config.minConfirmations,
|
|
882
866
|
maxConfirmations: this.config.maxConfirmations,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import * as BN from "bn.js";
|
|
2
1
|
import {SwapData} from "@atomiqlabs/base";
|
|
3
2
|
import {SwapHandlerType} from "../..";
|
|
4
3
|
import {ToBtcBaseSwap} from "../ToBtcBaseSwap";
|
|
5
|
-
import {deserializeBN
|
|
4
|
+
import {deserializeBN} from "../../utils/Utils";
|
|
6
5
|
|
|
7
6
|
export enum ToBtcSwapState {
|
|
8
7
|
REFUNDED = -3,
|
|
@@ -18,8 +17,9 @@ export enum ToBtcSwapState {
|
|
|
18
17
|
export class ToBtcSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap<T, ToBtcSwapState> {
|
|
19
18
|
|
|
20
19
|
readonly address: string;
|
|
21
|
-
readonly satsPerVbyte:
|
|
22
|
-
readonly nonce:
|
|
20
|
+
readonly satsPerVbyte: bigint;
|
|
21
|
+
readonly nonce: bigint;
|
|
22
|
+
readonly requiredConfirmations: number;
|
|
23
23
|
readonly preferedConfirmationTarget: number;
|
|
24
24
|
|
|
25
25
|
txId: string;
|
|
@@ -27,13 +27,14 @@ export class ToBtcSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap<T
|
|
|
27
27
|
constructor(
|
|
28
28
|
chainIdentifier: string,
|
|
29
29
|
address: string,
|
|
30
|
-
amount:
|
|
31
|
-
swapFee:
|
|
32
|
-
swapFeeInToken:
|
|
33
|
-
networkFee:
|
|
34
|
-
networkFeeInToken:
|
|
35
|
-
satsPerVbyte:
|
|
36
|
-
nonce:
|
|
30
|
+
amount: bigint,
|
|
31
|
+
swapFee: bigint,
|
|
32
|
+
swapFeeInToken: bigint,
|
|
33
|
+
networkFee: bigint,
|
|
34
|
+
networkFeeInToken: bigint,
|
|
35
|
+
satsPerVbyte: bigint,
|
|
36
|
+
nonce: bigint,
|
|
37
|
+
requiredConfirmations: number,
|
|
37
38
|
preferedConfirmationTarget: number
|
|
38
39
|
);
|
|
39
40
|
constructor(obj: any);
|
|
@@ -41,13 +42,14 @@ export class ToBtcSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap<T
|
|
|
41
42
|
constructor(
|
|
42
43
|
chainIdOrObj: string | any,
|
|
43
44
|
address?: string,
|
|
44
|
-
amount?:
|
|
45
|
-
swapFee?:
|
|
46
|
-
swapFeeInToken?:
|
|
47
|
-
networkFee?:
|
|
48
|
-
networkFeeInToken?:
|
|
49
|
-
satsPerVbyte?:
|
|
50
|
-
nonce?:
|
|
45
|
+
amount?: bigint,
|
|
46
|
+
swapFee?: bigint,
|
|
47
|
+
swapFeeInToken?: bigint,
|
|
48
|
+
networkFee?: bigint,
|
|
49
|
+
networkFeeInToken?: bigint,
|
|
50
|
+
satsPerVbyte?: bigint,
|
|
51
|
+
nonce?: bigint,
|
|
52
|
+
requiredConfirmations?: number,
|
|
51
53
|
preferedConfirmationTarget?: number
|
|
52
54
|
) {
|
|
53
55
|
if(typeof(chainIdOrObj)==="string") {
|
|
@@ -56,12 +58,14 @@ export class ToBtcSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap<T
|
|
|
56
58
|
this.address = address;
|
|
57
59
|
this.satsPerVbyte = satsPerVbyte;
|
|
58
60
|
this.nonce = nonce;
|
|
61
|
+
this.requiredConfirmations = requiredConfirmations;
|
|
59
62
|
this.preferedConfirmationTarget = preferedConfirmationTarget;
|
|
60
63
|
} else {
|
|
61
64
|
super(chainIdOrObj);
|
|
62
65
|
this.address = chainIdOrObj.address;
|
|
63
|
-
this.satsPerVbyte =
|
|
64
|
-
this.nonce =
|
|
66
|
+
this.satsPerVbyte = BigInt(chainIdOrObj.satsPerVbyte);
|
|
67
|
+
this.nonce = BigInt(chainIdOrObj.nonce);
|
|
68
|
+
this.requiredConfirmations = chainIdOrObj.requiredConfirmations;
|
|
65
69
|
this.preferedConfirmationTarget = chainIdOrObj.preferedConfirmationTarget;
|
|
66
70
|
|
|
67
71
|
this.txId = chainIdOrObj.txId;
|
|
@@ -76,6 +80,7 @@ export class ToBtcSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap<T
|
|
|
76
80
|
const partialSerialized = super.serialize();
|
|
77
81
|
partialSerialized.address = this.address;
|
|
78
82
|
partialSerialized.satsPerVbyte = this.satsPerVbyte.toString(10);
|
|
83
|
+
partialSerialized.requiredConfirmations = this.requiredConfirmations;
|
|
79
84
|
partialSerialized.nonce = this.nonce.toString(10);
|
|
80
85
|
partialSerialized.preferedConfirmationTarget = this.preferedConfirmationTarget;
|
|
81
86
|
partialSerialized.txId = this.txId;
|