@atomiqlabs/sdk 8.4.4 → 8.6.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/README.md +8 -8
- package/dist/enums/SwapSide.d.ts +15 -0
- package/dist/enums/SwapSide.js +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +2 -2
- package/dist/intermediaries/apis/IntermediaryAPI.js +2 -2
- package/dist/storage/UnifiedSwapStorage.d.ts +2 -0
- package/dist/swapper/Swapper.d.ts +36 -24
- package/dist/swapper/Swapper.js +20 -26
- package/dist/swapper/SwapperWithChain.d.ts +14 -18
- package/dist/swapper/SwapperWithChain.js +2 -2
- package/dist/swapper/SwapperWithSigner.d.ts +9 -13
- package/dist/swaps/IBTCWalletSwap.d.ts +1 -1
- package/dist/swaps/ISwap.js +4 -2
- package/dist/swaps/ISwapWithGasDrop.d.ts +1 -1
- package/dist/swaps/ISwapWrapper.d.ts +12 -12
- package/dist/swaps/ISwapWrapper.js +22 -14
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +3 -3
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +8 -8
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +5 -5
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +23 -2
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +20 -17
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +4 -4
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +44 -3
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +13 -17
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +3 -3
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +20 -2
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +15 -8
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +7 -7
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +52 -6
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +20 -30
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +6 -0
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +8 -6
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +12 -3
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +32 -1
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +8 -5
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +3 -3
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +4 -4
- package/dist/types/Token.d.ts +65 -25
- package/dist/types/Token.js +28 -13
- package/dist/types/TokenAmount.d.ts +2 -2
- package/dist/types/fees/Fee.d.ts +3 -3
- package/dist/utils/Utils.d.ts +1 -0
- package/dist/utils/Utils.js +17 -1
- package/package.json +1 -1
- package/src/enums/SwapSide.ts +16 -0
- package/src/index.ts +1 -0
- package/src/intermediaries/apis/IntermediaryAPI.ts +4 -4
- package/src/storage/UnifiedSwapStorage.ts +2 -0
- package/src/swapper/Swapper.ts +56 -40
- package/src/swapper/SwapperWithChain.ts +15 -10
- package/src/swapper/SwapperWithSigner.ts +8 -3
- package/src/swaps/IBTCWalletSwap.ts +1 -1
- package/src/swaps/ISwap.ts +5 -3
- package/src/swaps/ISwapWithGasDrop.ts +1 -1
- package/src/swaps/ISwapWrapper.ts +24 -23
- package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +3 -3
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +8 -8
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +5 -5
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +48 -22
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +4 -4
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +57 -21
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +3 -3
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +57 -22
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +7 -7
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +1 -1
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +80 -37
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +1 -1
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +12 -3
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +21 -9
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +53 -11
- package/src/swaps/trusted/ln/LnForGasSwap.ts +3 -3
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +4 -4
- package/src/types/Token.ts +98 -32
- package/src/types/TokenAmount.ts +5 -7
- package/src/types/fees/Fee.ts +3 -3
- package/src/utils/Utils.ts +18 -2
|
@@ -25,11 +25,17 @@ import {UnifiedSwapStorage} from "../../../../storage/UnifiedSwapStorage";
|
|
|
25
25
|
import {ISwap} from "../../../ISwap";
|
|
26
26
|
import {AmountData} from "../../../../types/AmountData";
|
|
27
27
|
import {tryWithRetries} from "../../../../utils/RetryUtils";
|
|
28
|
-
import {AllOptional
|
|
28
|
+
import {AllOptional} from "../../../../utils/TypeUtils";
|
|
29
29
|
import {ToBTCSwapState} from "../IToBTCSwap";
|
|
30
30
|
|
|
31
31
|
export type ToBTCOptions = {
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Ignored by the LP anyway
|
|
34
|
+
*/
|
|
32
35
|
confirmationTarget?: number,
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Default 2 confirmations should be enough for any currently supported amount by atomiq
|
|
38
|
+
*/
|
|
33
39
|
confirmations?: number
|
|
34
40
|
}
|
|
35
41
|
|
|
@@ -154,7 +160,10 @@ export class ToBTCWrapper<T extends ChainType> extends IToBTCWrapper<T, ToBTCDef
|
|
|
154
160
|
resp: ToBTCResponseType,
|
|
155
161
|
amountData: AmountData,
|
|
156
162
|
lp: Intermediary,
|
|
157
|
-
options:
|
|
163
|
+
options: {
|
|
164
|
+
confirmations: number,
|
|
165
|
+
confirmationTarget: number
|
|
166
|
+
},
|
|
158
167
|
data: T["Data"],
|
|
159
168
|
hash: string
|
|
160
169
|
): void {
|
|
@@ -220,7 +229,7 @@ export class ToBTCWrapper<T extends ChainType> extends IToBTCWrapper<T, ToBTCDef
|
|
|
220
229
|
intermediary: Intermediary
|
|
221
230
|
}[] {
|
|
222
231
|
if(!this.isInitialized) throw new Error("Not initialized, call init() first!");
|
|
223
|
-
const _options
|
|
232
|
+
const _options = {
|
|
224
233
|
confirmationTarget: options?.confirmationTarget ?? 3,
|
|
225
234
|
confirmations: options?.confirmations ?? 2
|
|
226
235
|
};
|
|
@@ -193,6 +193,8 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
193
193
|
extends ISwap<T, SpvFromBTCTypeDefinition<T>>
|
|
194
194
|
implements IBTCWalletSwap, ISwapWithGasDrop<T>, IClaimableSwap<T, SpvFromBTCTypeDefinition<T>, SpvFromBTCSwapState> {
|
|
195
195
|
|
|
196
|
+
protected readonly currentVersion: number = 2;
|
|
197
|
+
|
|
196
198
|
readonly TYPE: SwapType.SPV_VAULT_FROM_BTC = SwapType.SPV_VAULT_FROM_BTC;
|
|
197
199
|
|
|
198
200
|
/**
|
|
@@ -240,6 +242,8 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
240
242
|
|
|
241
243
|
private readonly gasPricingInfo?: PriceInfoType;
|
|
242
244
|
|
|
245
|
+
private posted?: boolean;
|
|
246
|
+
|
|
243
247
|
/**
|
|
244
248
|
* @internal
|
|
245
249
|
*/
|
|
@@ -337,6 +341,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
337
341
|
this._frontTxId = initOrObject.frontTxId;
|
|
338
342
|
this.gasPricingInfo = deserializePriceInfoType(initOrObject.gasPricingInfo);
|
|
339
343
|
this.btcTxConfirmedAt = initOrObject.btcTxConfirmedAt;
|
|
344
|
+
this.posted = initOrObject.posted;
|
|
340
345
|
if(initOrObject.data!=null) this._data = new this.wrapper._spvWithdrawalDataDeserializer(initOrObject.data);
|
|
341
346
|
}
|
|
342
347
|
this.tryCalculateSwapFee();
|
|
@@ -347,7 +352,12 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
347
352
|
* @inheritDoc
|
|
348
353
|
* @internal
|
|
349
354
|
*/
|
|
350
|
-
protected upgradeVersion() {
|
|
355
|
+
protected upgradeVersion() {
|
|
356
|
+
if(this.version===1) {
|
|
357
|
+
this.posted = this.initiated;
|
|
358
|
+
this.version = 2;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
351
361
|
|
|
352
362
|
/**
|
|
353
363
|
* @inheritDoc
|
|
@@ -582,7 +592,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
582
592
|
*
|
|
583
593
|
* @internal
|
|
584
594
|
*/
|
|
585
|
-
protected getOutputWithoutFee(): TokenAmount<
|
|
595
|
+
protected getOutputWithoutFee(): TokenAmount<SCToken<T["ChainId"]>, true> {
|
|
586
596
|
return toTokenAmount(
|
|
587
597
|
(this.outputTotalSwap * (100_000n + this.callerFeeShare + this.frontingFeeShare + this.executionFeeShare) / 100_000n) + (this.swapFee ?? 0n),
|
|
588
598
|
this.wrapper._tokens[this.outputSwapToken], this.wrapper._prices, this.pricingInfo
|
|
@@ -704,21 +714,21 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
704
714
|
/**
|
|
705
715
|
* @inheritDoc
|
|
706
716
|
*/
|
|
707
|
-
getOutput(): TokenAmount<
|
|
717
|
+
getOutput(): TokenAmount<SCToken<T["ChainId"]>, true> {
|
|
708
718
|
return toTokenAmount(this.outputTotalSwap, this.wrapper._tokens[this.outputSwapToken], this.wrapper._prices, this.pricingInfo);
|
|
709
719
|
}
|
|
710
720
|
|
|
711
721
|
/**
|
|
712
722
|
* @inheritDoc
|
|
713
723
|
*/
|
|
714
|
-
getGasDropOutput(): TokenAmount<
|
|
724
|
+
getGasDropOutput(): TokenAmount<SCToken<T["ChainId"]>, true> {
|
|
715
725
|
return toTokenAmount(this.outputTotalGas, this.wrapper._tokens[this.outputGasToken], this.wrapper._prices, this.gasPricingInfo);
|
|
716
726
|
}
|
|
717
727
|
|
|
718
728
|
/**
|
|
719
729
|
* @inheritDoc
|
|
720
730
|
*/
|
|
721
|
-
getInputWithoutFee(): TokenAmount<
|
|
731
|
+
getInputWithoutFee(): TokenAmount<BtcToken<false>, true> {
|
|
722
732
|
return toTokenAmount(this.getInputAmountWithoutFee(), BitcoinTokens.BTC, this.wrapper._prices, this.pricingInfo);
|
|
723
733
|
}
|
|
724
734
|
|
|
@@ -732,7 +742,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
732
742
|
/**
|
|
733
743
|
* @inheritDoc
|
|
734
744
|
*/
|
|
735
|
-
getInput(): TokenAmount<
|
|
745
|
+
getInput(): TokenAmount<BtcToken<false>, true> {
|
|
736
746
|
return toTokenAmount(this.btcAmount, BitcoinTokens.BTC, this.wrapper._prices, this.pricingInfo);
|
|
737
747
|
}
|
|
738
748
|
|
|
@@ -973,6 +983,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
973
983
|
|
|
974
984
|
this._data = data;
|
|
975
985
|
this.initiated = true;
|
|
986
|
+
this.posted = true;
|
|
976
987
|
await this._saveAndEmit(SpvFromBTCSwapState.SIGNED);
|
|
977
988
|
|
|
978
989
|
try {
|
|
@@ -996,7 +1007,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
996
1007
|
/**
|
|
997
1008
|
* @inheritDoc
|
|
998
1009
|
*/
|
|
999
|
-
async estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<
|
|
1010
|
+
async estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<BtcToken<false>, true> | null> {
|
|
1000
1011
|
const bitcoinWallet: IBitcoinWallet = toBitcoinWallet(_bitcoinWallet, this.wrapper._btcRpc, this.wrapper._options.bitcoinNetwork);
|
|
1001
1012
|
const txFee = await bitcoinWallet.getFundedPsbtFee((await this.getPsbt()).psbt, feeRate);
|
|
1002
1013
|
if(txFee==null) return null;
|
|
@@ -1186,7 +1197,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1186
1197
|
if(
|
|
1187
1198
|
this._state!==SpvFromBTCSwapState.POSTED &&
|
|
1188
1199
|
this._state!==SpvFromBTCSwapState.BROADCASTED &&
|
|
1189
|
-
!(this._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && this.
|
|
1200
|
+
!(this._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && this.posted)
|
|
1190
1201
|
) throw new Error("Must be in POSTED or BROADCASTED state!");
|
|
1191
1202
|
if(this._data==null) throw new Error("Expected swap to have withdrawal data filled!");
|
|
1192
1203
|
|
|
@@ -1529,6 +1540,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1529
1540
|
executionFeeShare: this.executionFeeShare.toString(10),
|
|
1530
1541
|
genesisSmartChainBlockHeight: this._genesisSmartChainBlockHeight,
|
|
1531
1542
|
gasPricingInfo: serializePriceInfoType(this.gasPricingInfo),
|
|
1543
|
+
posted: this.posted,
|
|
1532
1544
|
|
|
1533
1545
|
senderAddress: this._senderAddress,
|
|
1534
1546
|
claimTxId: this._claimTxId,
|
|
@@ -1704,7 +1716,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1704
1716
|
}
|
|
1705
1717
|
}
|
|
1706
1718
|
|
|
1707
|
-
if(this._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && !this.
|
|
1719
|
+
if(this._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && !this.posted) {
|
|
1708
1720
|
if(this.expiry<Date.now()) {
|
|
1709
1721
|
this._state = SpvFromBTCSwapState.QUOTE_EXPIRED;
|
|
1710
1722
|
if(save) await this._saveAndEmit();
|
|
@@ -32,13 +32,47 @@ import {ISwap} from "../ISwap";
|
|
|
32
32
|
import {IClaimableSwapWrapper} from "../IClaimableSwapWrapper";
|
|
33
33
|
import {AmountData} from "../../types/AmountData";
|
|
34
34
|
import {tryWithRetries} from "../../utils/RetryUtils";
|
|
35
|
-
import {AllOptional
|
|
35
|
+
import {AllOptional} from "../../utils/TypeUtils";
|
|
36
|
+
import {fromHumanReadableString} from "../../utils/TokenUtils";
|
|
37
|
+
import {UserError} from "../../errors/UserError";
|
|
36
38
|
|
|
37
39
|
export type SpvFromBTCOptions = {
|
|
38
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Optional additional native token to receive as an output of the swap (e.g. STRK on Starknet or cBTC on Citrea).
|
|
42
|
+
*
|
|
43
|
+
* When passed as a `bigint` it is specified in base units of the token and in `string` it is the human readable
|
|
44
|
+
* decimal format.
|
|
45
|
+
*/
|
|
46
|
+
gasAmount?: bigint | string,
|
|
47
|
+
/**
|
|
48
|
+
* The LP enforces a minimum bitcoin fee rate in sats/vB for the swap transaction. With this config you can optionally
|
|
49
|
+
* limit how high of a minimum fee rate would you accept.
|
|
50
|
+
*
|
|
51
|
+
* By default the maximum allowed fee rate is calculated dynamically based on current bitcoin fee rate as:
|
|
52
|
+
*
|
|
53
|
+
* `maxAllowedBitcoinFeeRate` = 10 + `currentBitcoinFeeRate` * 1.5
|
|
54
|
+
*/
|
|
55
|
+
maxAllowedBitcoinFeeRate?: number,
|
|
56
|
+
/**
|
|
57
|
+
* A flag to attach 0 watchtower fee to the swap, this would make the settlement unattractive for the watchtowers
|
|
58
|
+
* and therefore automatic settlement for such swaps will not be possible, you will have to settle manually
|
|
59
|
+
* with {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim} functions.
|
|
60
|
+
*/
|
|
39
61
|
unsafeZeroWatchtowerFee?: boolean,
|
|
62
|
+
/**
|
|
63
|
+
* A safety factor to use when estimating the watchtower fee to attach to the swap (this has to cover the gas fee
|
|
64
|
+
* of watchtowers settling the swap). A higher multiple here would mean that a swap is more attractive for
|
|
65
|
+
* watchtowers to settle automatically.
|
|
66
|
+
*
|
|
67
|
+
* Uses a `1.25` multiple by default (i.e. the current network fee is multiplied by 1.25 and then used to estimate
|
|
68
|
+
* the settlement gas fee cost)
|
|
69
|
+
*/
|
|
40
70
|
feeSafetyFactor?: number,
|
|
41
|
-
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @deprecated Use `maxAllowedBitcoinFeeRate` instead!
|
|
74
|
+
*/
|
|
75
|
+
maxAllowedNetworkFeeRate?: number,
|
|
42
76
|
};
|
|
43
77
|
|
|
44
78
|
export type SpvFromBTCWrapperOptions = ISwapWrapperOptions & {
|
|
@@ -275,7 +309,10 @@ export class SpvFromBTCWrapper<
|
|
|
275
309
|
*/
|
|
276
310
|
private async preFetchCallerFeeShare(
|
|
277
311
|
amountData: AmountData,
|
|
278
|
-
options:
|
|
312
|
+
options: {
|
|
313
|
+
unsafeZeroWatchtowerFee: boolean,
|
|
314
|
+
feeSafetyFactor: number
|
|
315
|
+
},
|
|
279
316
|
pricePrefetch: Promise<bigint | undefined>,
|
|
280
317
|
nativeTokenPricePrefetch: Promise<bigint | undefined> | undefined,
|
|
281
318
|
abortController: AbortController
|
|
@@ -355,7 +392,9 @@ export class SpvFromBTCWrapper<
|
|
|
355
392
|
resp: SpvFromBTCPrepareResponseType,
|
|
356
393
|
amountData: AmountData,
|
|
357
394
|
lp: Intermediary,
|
|
358
|
-
options:
|
|
395
|
+
options: {
|
|
396
|
+
gasAmount: bigint
|
|
397
|
+
},
|
|
359
398
|
callerFeeShare: bigint,
|
|
360
399
|
bitcoinFeeRatePromise: Promise<number | undefined>,
|
|
361
400
|
abortSignal: AbortSignal
|
|
@@ -438,7 +477,7 @@ export class SpvFromBTCWrapper<
|
|
|
438
477
|
throw new IntermediaryError("Invalid amount0 multiplier used, rawAmount diff too high");
|
|
439
478
|
if(resp.total !== adjustedAmount) throw new IntermediaryError("Invalid total returned");
|
|
440
479
|
}
|
|
441
|
-
if(options.gasAmount
|
|
480
|
+
if(options.gasAmount===0n) {
|
|
442
481
|
if(resp.totalGas !== 0n) throw new IntermediaryError("Invalid gas total returned");
|
|
443
482
|
} else {
|
|
444
483
|
//Check the difference between amount adjusted due to scaling to raw amount
|
|
@@ -548,13 +587,16 @@ export class SpvFromBTCWrapper<
|
|
|
548
587
|
quote: Promise<SpvFromBTCSwap<T>>,
|
|
549
588
|
intermediary: Intermediary
|
|
550
589
|
}[] {
|
|
551
|
-
const _options
|
|
552
|
-
gasAmount: options?.gasAmount
|
|
590
|
+
const _options = {
|
|
591
|
+
gasAmount: this.parseGasAmount(options?.gasAmount),
|
|
553
592
|
unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
|
|
554
593
|
feeSafetyFactor: options?.feeSafetyFactor ?? 1.25,
|
|
555
|
-
|
|
594
|
+
maxAllowedBitcoinFeeRate: options?.maxAllowedBitcoinFeeRate ?? options?.maxAllowedNetworkFeeRate ?? Infinity
|
|
556
595
|
};
|
|
557
596
|
|
|
597
|
+
if(amountData.token===this._chain.getNativeCurrencyAddress() && _options.gasAmount!==0n)
|
|
598
|
+
throw new UserError("Cannot specify `gasAmount` for swaps to a native token!");
|
|
599
|
+
|
|
558
600
|
const _abortController = extendAbortController(abortSignal);
|
|
559
601
|
const pricePrefetchPromise: Promise<bigint | undefined> = this.preFetchPrice(amountData, _abortController.signal);
|
|
560
602
|
const usdPricePrefetchPromise: Promise<number | undefined> = this.preFetchUsdPrice(_abortController.signal);
|
|
@@ -564,8 +606,8 @@ export class SpvFromBTCWrapper<
|
|
|
564
606
|
undefined :
|
|
565
607
|
this.preFetchPrice({token: nativeTokenAddress}, _abortController.signal);
|
|
566
608
|
const callerFeePrefetchPromise = this.preFetchCallerFeeShare(amountData, _options, pricePrefetchPromise, gasTokenPricePrefetchPromise, _abortController);
|
|
567
|
-
const bitcoinFeeRatePromise: Promise<number | undefined> = _options.
|
|
568
|
-
Promise.resolve(_options.
|
|
609
|
+
const bitcoinFeeRatePromise: Promise<number | undefined> = _options.maxAllowedBitcoinFeeRate!=Infinity ?
|
|
610
|
+
Promise.resolve(_options.maxAllowedBitcoinFeeRate) :
|
|
569
611
|
this._btcRpc.getFeeRate().then(x => this._options.maxBtcFeeOffset + (x*this._options.maxBtcFeeMultiplier)).catch(e => {
|
|
570
612
|
_abortController.abort(e);
|
|
571
613
|
return undefined;
|
|
@@ -318,7 +318,7 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
318
318
|
/**
|
|
319
319
|
* @inheritDoc
|
|
320
320
|
*/
|
|
321
|
-
getOutput(): TokenAmount<
|
|
321
|
+
getOutput(): TokenAmount<SCToken<T["ChainId"]>, true> {
|
|
322
322
|
return toTokenAmount(
|
|
323
323
|
this.outputAmount, this.wrapper._tokens[this.wrapper._chain.getNativeCurrencyAddress()],
|
|
324
324
|
this.wrapper._prices, this.pricingInfo
|
|
@@ -335,7 +335,7 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
335
335
|
/**
|
|
336
336
|
* @inheritDoc
|
|
337
337
|
*/
|
|
338
|
-
getInput(): TokenAmount<
|
|
338
|
+
getInput(): TokenAmount<BtcToken<true>, true> {
|
|
339
339
|
const parsed = bolt11Decode(this.pr);
|
|
340
340
|
const msats = parsed.millisatoshis;
|
|
341
341
|
if(msats==null) throw new Error("Swap lightning invoice has no msat amount field!");
|
|
@@ -346,7 +346,7 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
346
346
|
/**
|
|
347
347
|
* @inheritDoc
|
|
348
348
|
*/
|
|
349
|
-
getInputWithoutFee(): TokenAmount<
|
|
349
|
+
getInputWithoutFee(): TokenAmount<BtcToken<true>, true> {
|
|
350
350
|
const parsed = bolt11Decode(this.pr);
|
|
351
351
|
const msats = parsed.millisatoshis;
|
|
352
352
|
if(msats==null) throw new Error("Swap lightning invoice has no msat amount field!");
|
|
@@ -362,7 +362,7 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
362
362
|
/**
|
|
363
363
|
* @inheritDoc
|
|
364
364
|
*/
|
|
365
|
-
getOutput(): TokenAmount<
|
|
365
|
+
getOutput(): TokenAmount<SCToken<T["ChainId"]>, true> {
|
|
366
366
|
return toTokenAmount(
|
|
367
367
|
this.outputAmount, this.wrapper._tokens[this.wrapper._chain.getNativeCurrencyAddress()],
|
|
368
368
|
this.wrapper._prices, this.pricingInfo
|
|
@@ -379,14 +379,14 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
379
379
|
/**
|
|
380
380
|
* @inheritDoc
|
|
381
381
|
*/
|
|
382
|
-
getInput(): TokenAmount<
|
|
382
|
+
getInput(): TokenAmount<BtcToken<false>, true> {
|
|
383
383
|
return toTokenAmount(this.inputAmount, BitcoinTokens.BTC, this.wrapper._prices, this.pricingInfo);
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
/**
|
|
387
387
|
* @inheritDoc
|
|
388
388
|
*/
|
|
389
|
-
getInputWithoutFee(): TokenAmount<
|
|
389
|
+
getInputWithoutFee(): TokenAmount<BtcToken<false>, true> {
|
|
390
390
|
return toTokenAmount(
|
|
391
391
|
this.inputAmount - (this.swapFeeBtc ?? 0n), BitcoinTokens.BTC,
|
|
392
392
|
this.wrapper._prices, this.pricingInfo
|
|
@@ -526,7 +526,7 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
526
526
|
/**
|
|
527
527
|
* @inheritDoc
|
|
528
528
|
*/
|
|
529
|
-
async estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<
|
|
529
|
+
async estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<BtcToken<false>, true> | null> {
|
|
530
530
|
const bitcoinWallet: IBitcoinWallet = toBitcoinWallet(_bitcoinWallet, this.wrapper._btcRpc, this.wrapper._options.bitcoinNetwork);
|
|
531
531
|
const txFee = await bitcoinWallet.getTransactionFee(this.address, this.inputAmount, feeRate);
|
|
532
532
|
if(txFee==null) return null;
|
package/src/types/Token.ts
CHANGED
|
@@ -1,15 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type for all token types (BTC or smart chain)
|
|
3
|
+
*
|
|
4
|
+
* @category Tokens
|
|
5
|
+
*/
|
|
6
|
+
export type Token<ChainIdentifier extends string = string> = {
|
|
7
|
+
/**
|
|
8
|
+
* Chain identifier for the token's chain
|
|
9
|
+
*/
|
|
10
|
+
chainId: ChainIdentifier | "BITCOIN" | "LIGHTNING",
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Ticker of the token
|
|
14
|
+
*/
|
|
15
|
+
ticker: string,
|
|
16
|
+
/**
|
|
17
|
+
* Full name of the token
|
|
18
|
+
*/
|
|
19
|
+
name: string,
|
|
20
|
+
/**
|
|
21
|
+
* Actual decimal places of the tokens
|
|
22
|
+
*/
|
|
23
|
+
decimals: number,
|
|
24
|
+
/**
|
|
25
|
+
* The decimal places that should be rendered and displayed to the user
|
|
26
|
+
*/
|
|
27
|
+
displayDecimals?: number,
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Address of the token contract, or `""` for Bitcoin
|
|
31
|
+
*/
|
|
32
|
+
address: string,
|
|
33
|
+
|
|
34
|
+
// legacy compatibility
|
|
35
|
+
/**
|
|
36
|
+
* Legacy chain identifier distinguishing between Smart Chain and Bitcoin tokens
|
|
37
|
+
*/
|
|
38
|
+
chain: "SC" | "BTC",
|
|
39
|
+
/**
|
|
40
|
+
* Legacy lightning flag, determines whether a Bitcoin token is an Lightning or on-chain one
|
|
41
|
+
*/
|
|
42
|
+
lightning?: boolean,
|
|
43
|
+
|
|
44
|
+
// helpers
|
|
45
|
+
/**
|
|
46
|
+
* Equality check between tokens
|
|
47
|
+
*/
|
|
48
|
+
equals: (other: Token) => boolean,
|
|
49
|
+
/**
|
|
50
|
+
* Returns the
|
|
51
|
+
*/
|
|
52
|
+
toString: () => string
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Type guard for a {@link Token} type, encompassing all tokens (BTC or smart chain)
|
|
57
|
+
*
|
|
58
|
+
* @category Tokens
|
|
59
|
+
*/
|
|
60
|
+
export function isToken(obj: any): obj is Token {
|
|
61
|
+
return typeof (obj) === "object" &&
|
|
62
|
+
(obj.chain === "SC" || obj.chain === "BTC") &&
|
|
63
|
+
typeof (obj.ticker) === "string" &&
|
|
64
|
+
typeof (obj.decimals) === "number" &&
|
|
65
|
+
typeof (obj.name) === "string";
|
|
66
|
+
}
|
|
67
|
+
|
|
1
68
|
/**
|
|
2
69
|
* Bitcoin token type (BTC on on-chain or lightning)
|
|
3
70
|
*
|
|
4
71
|
* @category Tokens
|
|
5
72
|
*/
|
|
6
|
-
export type BtcToken<L = boolean> = {
|
|
7
|
-
|
|
8
|
-
lightning: L,
|
|
73
|
+
export type BtcToken<L = boolean> = Token & {
|
|
74
|
+
chainId: L extends true ? "LIGHTNING" : "BITCOIN",
|
|
9
75
|
ticker: "BTC",
|
|
10
|
-
decimals: 8,
|
|
11
76
|
name: L extends true ? "Bitcoin (lightning L2)" : "Bitcoin (on-chain L1)",
|
|
12
|
-
|
|
77
|
+
decimals: 8,
|
|
78
|
+
displayDecimals: 8,
|
|
79
|
+
|
|
80
|
+
address: "",
|
|
81
|
+
|
|
82
|
+
// legacy compatibility
|
|
83
|
+
chain: "BTC",
|
|
84
|
+
lightning: L,
|
|
85
|
+
|
|
86
|
+
toString: () => L extends true ? "BTC-LN" : "BTC"
|
|
13
87
|
};
|
|
14
88
|
|
|
15
89
|
/**
|
|
@@ -37,17 +111,27 @@ export const BitcoinTokens: {
|
|
|
37
111
|
} = {
|
|
38
112
|
BTC: {
|
|
39
113
|
chain: "BTC",
|
|
114
|
+
chainId: "BITCOIN",
|
|
40
115
|
lightning: false,
|
|
41
116
|
ticker: "BTC",
|
|
42
117
|
decimals: 8,
|
|
43
|
-
|
|
118
|
+
displayDecimals: 8,
|
|
119
|
+
name: "Bitcoin (on-chain L1)",
|
|
120
|
+
address: "",
|
|
121
|
+
equals: (other: Token) => other.chainId==="BITCOIN" && other.ticker==="BTC",
|
|
122
|
+
toString: () => "BTC"
|
|
44
123
|
},
|
|
45
124
|
BTCLN: {
|
|
46
125
|
chain: "BTC",
|
|
126
|
+
chainId: "LIGHTNING",
|
|
47
127
|
lightning: true,
|
|
48
128
|
ticker: "BTC",
|
|
49
129
|
decimals: 8,
|
|
50
|
-
|
|
130
|
+
displayDecimals: 8,
|
|
131
|
+
name: "Bitcoin (lightning L2)",
|
|
132
|
+
address: "",
|
|
133
|
+
equals: (other: Token) => other.chainId==="LIGHTNING" && other.ticker==="BTC",
|
|
134
|
+
toString: () => "BTC-LN"
|
|
51
135
|
}
|
|
52
136
|
};
|
|
53
137
|
|
|
@@ -56,42 +140,24 @@ export const BitcoinTokens: {
|
|
|
56
140
|
*
|
|
57
141
|
* @category Tokens
|
|
58
142
|
*/
|
|
59
|
-
export type SCToken<ChainIdentifier extends string = string> = {
|
|
60
|
-
chain: "SC",
|
|
143
|
+
export type SCToken<ChainIdentifier extends string = string> = Token<ChainIdentifier> & {
|
|
61
144
|
chainId: ChainIdentifier,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
name: string
|
|
67
|
-
}
|
|
145
|
+
chain: "SC"
|
|
146
|
+
|
|
147
|
+
toString: () => `${ChainIdentifier}-${string}`
|
|
148
|
+
};
|
|
68
149
|
|
|
69
150
|
/**
|
|
70
151
|
* Type guard for {@link SCToken} (token on the smart chain)
|
|
71
152
|
* @category Tokens
|
|
72
153
|
*/
|
|
73
|
-
export function isSCToken(obj: any): obj is SCToken {
|
|
154
|
+
export function isSCToken<ChainIdentifier extends string = string>(obj: any, chainIdentifier?: ChainIdentifier[]): obj is SCToken<ChainIdentifier> {
|
|
74
155
|
return typeof (obj) === "object" &&
|
|
75
156
|
obj.chain === "SC" &&
|
|
76
157
|
typeof (obj.chainId) === "string" &&
|
|
158
|
+
(chainIdentifier==null || chainIdentifier.includes(obj.chainId)) &&
|
|
77
159
|
typeof (obj.address) === "string" &&
|
|
78
160
|
typeof (obj.ticker) === "string" &&
|
|
79
161
|
typeof (obj.decimals) === "number" &&
|
|
80
162
|
typeof (obj.name) === "string";
|
|
81
163
|
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Union type for all token types (BTC or smart chain)
|
|
85
|
-
*
|
|
86
|
-
* @category Tokens
|
|
87
|
-
*/
|
|
88
|
-
export type Token<ChainIdentifier extends string = string> = BtcToken | SCToken<ChainIdentifier>;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Type guard for an union {@link Token} type, encompassing all tokens (BTC or smart chain)
|
|
92
|
-
*
|
|
93
|
-
* @category Tokens
|
|
94
|
-
*/
|
|
95
|
-
export function isToken(obj: any): obj is Token {
|
|
96
|
-
return isBtcToken(obj) || isSCToken(obj);
|
|
97
|
-
}
|
package/src/types/TokenAmount.ts
CHANGED
|
@@ -9,8 +9,7 @@ import {toDecimal} from "../utils/Utils";
|
|
|
9
9
|
* @category Tokens
|
|
10
10
|
*/
|
|
11
11
|
export type TokenAmount<
|
|
12
|
-
|
|
13
|
-
T extends Token<ChainIdentifier> = Token<ChainIdentifier>,
|
|
12
|
+
T extends Token = Token,
|
|
14
13
|
Known extends boolean = boolean
|
|
15
14
|
> = {
|
|
16
15
|
/**
|
|
@@ -74,15 +73,14 @@ export type TokenAmount<
|
|
|
74
73
|
* @internal
|
|
75
74
|
*/
|
|
76
75
|
export function toTokenAmount<
|
|
77
|
-
|
|
78
|
-
T extends Token<ChainIdentifier> = Token<ChainIdentifier>,
|
|
76
|
+
T extends Token = Token,
|
|
79
77
|
Known extends boolean = boolean
|
|
80
78
|
>(
|
|
81
79
|
amount: Known extends true ? bigint : null,
|
|
82
80
|
token: T,
|
|
83
81
|
prices: ISwapPrice,
|
|
84
82
|
pricingInfo?: PriceInfoType
|
|
85
|
-
): TokenAmount<
|
|
83
|
+
): TokenAmount<T, Known> {
|
|
86
84
|
if (amount == null) return {
|
|
87
85
|
rawAmount: undefined,
|
|
88
86
|
amount: "",
|
|
@@ -93,7 +91,7 @@ export function toTokenAmount<
|
|
|
93
91
|
usdValue: () => Promise.resolve(NaN),
|
|
94
92
|
toString: () => "??? " + token.ticker,
|
|
95
93
|
isUnknown: true
|
|
96
|
-
} as TokenAmount<
|
|
94
|
+
} as TokenAmount<T>;
|
|
97
95
|
const amountStr = toDecimal(amount, token.decimals, undefined, token.displayDecimals);
|
|
98
96
|
const _amount = parseFloat(amountStr);
|
|
99
97
|
|
|
@@ -131,5 +129,5 @@ export function toTokenAmount<
|
|
|
131
129
|
},
|
|
132
130
|
toString: () => amountStr + " " + token.ticker,
|
|
133
131
|
isUnknown: false
|
|
134
|
-
} as TokenAmount<
|
|
132
|
+
} as TokenAmount<T>;
|
|
135
133
|
}
|
package/src/types/fees/Fee.ts
CHANGED
|
@@ -16,11 +16,11 @@ export type Fee<
|
|
|
16
16
|
/**
|
|
17
17
|
* Fee value equivalent in source token
|
|
18
18
|
*/
|
|
19
|
-
amountInSrcToken: TokenAmount<
|
|
19
|
+
amountInSrcToken: TokenAmount<TSrc, true>,
|
|
20
20
|
/**
|
|
21
21
|
* Fee value equivalent in destination token
|
|
22
22
|
*/
|
|
23
|
-
amountInDstToken: TokenAmount<
|
|
23
|
+
amountInDstToken: TokenAmount<TDst, true>,
|
|
24
24
|
/**
|
|
25
25
|
* Fetches the current USD value of the fee
|
|
26
26
|
*
|
|
@@ -49,7 +49,7 @@ export type Fee<
|
|
|
49
49
|
* base_fee + amount * percentage_fee
|
|
50
50
|
*/
|
|
51
51
|
composition?: {
|
|
52
|
-
base: TokenAmount
|
|
52
|
+
base: TokenAmount,
|
|
53
53
|
percentage: PercentagePPM
|
|
54
54
|
}
|
|
55
55
|
}
|
package/src/utils/Utils.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {Buffer} from "buffer";
|
|
2
2
|
import {randomBytes as randomBytesNoble} from "@noble/hashes/utils";
|
|
3
3
|
import {sha256} from "@noble/hashes/sha2";
|
|
4
|
-
import {BigIntBufferUtils} from "@atomiqlabs/base";
|
|
4
|
+
import {BigIntBufferUtils, ChainType} from "@atomiqlabs/base";
|
|
5
|
+
import {IFromBTCLNWrapper} from "../swaps/escrow_swaps/frombtc/IFromBTCLNWrapper";
|
|
6
|
+
import {UserError} from "../errors/UserError";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Returns a promise that rejects if the passed promise resolves to `undefined` or `null`
|
|
@@ -179,4 +181,18 @@ export function toDecimal(amount: bigint, decimalCount: number, cut?: boolean, d
|
|
|
179
181
|
if (displayDecimals === 0) return amountStr.substring(0, splitPoint);
|
|
180
182
|
if (displayDecimals != null && cutTo > displayDecimals) cutTo = displayDecimals;
|
|
181
183
|
return amountStr.substring(0, splitPoint) + "." + decimalPart.substring(0, cutTo);
|
|
182
|
-
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function parseHashValueExact32Bytes(value?: Buffer | string, variableName?: string): Buffer | undefined {
|
|
187
|
+
let hash: Buffer | undefined;
|
|
188
|
+
if(typeof(value)==="string") {
|
|
189
|
+
if(value.length!==64)
|
|
190
|
+
throw new UserError(`Invalid ${variableName} length, must be exactly 64 hexadecimal characters!`)
|
|
191
|
+
hash = Buffer.from(value, "hex");
|
|
192
|
+
} else {
|
|
193
|
+
hash = value;
|
|
194
|
+
}
|
|
195
|
+
if(hash!=null && hash.length!==32)
|
|
196
|
+
throw new UserError(`Invalid ${variableName} length, must be exactly 32 bytes!`);
|
|
197
|
+
return hash;
|
|
198
|
+
}
|