@atomiqlabs/sdk 8.8.3 → 8.9.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/api/index.d.ts +1 -0
- package/api/index.js +3 -0
- package/dist/ApiList.d.ts +37 -0
- package/dist/ApiList.js +30 -0
- package/dist/api/ApiEndpoints.d.ts +393 -0
- package/dist/api/ApiEndpoints.js +2 -0
- package/dist/api/ApiParser.d.ts +10 -0
- package/dist/api/ApiParser.js +134 -0
- package/dist/api/ApiTypes.d.ts +157 -0
- package/dist/api/ApiTypes.js +75 -0
- package/dist/api/SerializedAction.d.ts +40 -0
- package/dist/api/SerializedAction.js +59 -0
- package/dist/api/SwapperApi.d.ts +50 -0
- package/dist/api/SwapperApi.js +431 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +24 -0
- package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
- package/dist/events/UnifiedSwapEventListener.js +8 -2
- package/dist/http/HttpUtils.d.ts +4 -2
- package/dist/http/HttpUtils.js +10 -4
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
- package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +171 -14
- package/dist/intermediaries/apis/IntermediaryAPI.js +174 -28
- package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
- package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
- package/dist/storage/IUnifiedStorage.d.ts +45 -3
- package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
- package/dist/storage/UnifiedSwapStorage.js +46 -8
- package/dist/swapper/Swapper.d.ts +41 -3
- package/dist/swapper/Swapper.js +93 -48
- package/dist/swapper/SwapperUtils.d.ts +18 -2
- package/dist/swapper/SwapperUtils.js +39 -1
- package/dist/swaps/ISwap.d.ts +70 -9
- package/dist/swaps/ISwap.js +28 -6
- package/dist/swaps/ISwapWrapper.d.ts +11 -1
- package/dist/swaps/ISwapWrapper.js +23 -3
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +76 -19
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +290 -51
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +3 -1
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +5 -5
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
- package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
- package/dist/types/SwapExecutionAction.d.ts +141 -34
- package/dist/types/SwapExecutionAction.js +104 -0
- package/dist/types/SwapExecutionStep.d.ts +144 -0
- package/dist/types/SwapExecutionStep.js +87 -0
- package/dist/types/TokenAmount.d.ts +6 -0
- package/dist/types/TokenAmount.js +26 -1
- package/dist/utils/BitcoinUtils.d.ts +2 -0
- package/dist/utils/BitcoinUtils.js +34 -1
- package/dist/utils/Utils.d.ts +3 -1
- package/dist/utils/Utils.js +7 -1
- package/package.json +7 -4
- package/src/api/ApiEndpoints.ts +427 -0
- package/src/api/ApiParser.ts +138 -0
- package/src/api/ApiTypes.ts +229 -0
- package/src/api/SerializedAction.ts +97 -0
- package/src/api/SwapperApi.ts +545 -0
- package/src/api/index.ts +5 -0
- package/src/events/UnifiedSwapEventListener.ts +11 -3
- package/src/http/HttpUtils.ts +10 -4
- package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
- package/src/index.ts +1 -0
- package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
- package/src/intermediaries/apis/IntermediaryAPI.ts +314 -30
- package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
- package/src/storage/IUnifiedStorage.ts +45 -4
- package/src/storage/UnifiedSwapStorage.ts +42 -8
- package/src/swapper/Swapper.ts +134 -52
- package/src/swapper/SwapperUtils.ts +42 -2
- package/src/swaps/ISwap.ts +88 -16
- package/src/swaps/ISwapWrapper.ts +28 -3
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +393 -57
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +5 -3
- package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
- package/src/types/SwapExecutionAction.ts +266 -43
- package/src/types/SwapExecutionStep.ts +224 -0
- package/src/types/TokenAmount.ts +36 -2
- package/src/utils/BitcoinUtils.ts +32 -0
- package/src/utils/Utils.ts +10 -1
- package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +0 -258
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {isISwapInit, ISwap, ISwapInit} from "../ISwap";
|
|
2
2
|
import {
|
|
3
|
+
BtcTx,
|
|
3
4
|
BtcTxWithBlockheight,
|
|
4
5
|
ChainType,
|
|
5
6
|
isAbstractSigner,
|
|
@@ -38,7 +39,16 @@ import {
|
|
|
38
39
|
serializePriceInfoType
|
|
39
40
|
} from "../../types/PriceInfoType";
|
|
40
41
|
import {toBitcoinWallet} from "../../utils/BitcoinWalletUtils";
|
|
41
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
SwapExecutionAction,
|
|
44
|
+
SwapExecutionActionSignPSBT, SwapExecutionActionSignSmartChainTx,
|
|
45
|
+
SwapExecutionActionWait
|
|
46
|
+
} from "../../types/SwapExecutionAction";
|
|
47
|
+
import {
|
|
48
|
+
SwapExecutionStepPayment,
|
|
49
|
+
SwapExecutionStepSettlement
|
|
50
|
+
} from "../../types/SwapExecutionStep";
|
|
51
|
+
import {SwapStateInfo} from "../../types/SwapStateInfo";
|
|
42
52
|
|
|
43
53
|
/**
|
|
44
54
|
* State enum for SPV vault (UTXO-controlled vault) based swaps
|
|
@@ -499,7 +509,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
499
509
|
* @inheritDoc
|
|
500
510
|
*/
|
|
501
511
|
isFinished(): boolean {
|
|
502
|
-
return this.
|
|
512
|
+
return this.isSuccessful() || this.isFailed() || this.isQuoteExpired();
|
|
503
513
|
}
|
|
504
514
|
|
|
505
515
|
/**
|
|
@@ -822,13 +832,15 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
822
832
|
/**
|
|
823
833
|
* Returns the raw PSBT (not funded), the wallet should fund the PSBT (add its inputs) and importantly **set the nSequence field of the
|
|
824
834
|
* 2nd input** (input 1 - indexing from 0) to the value returned in `in1sequence`, sign the PSBT and then pass
|
|
825
|
-
* it back to the swap with {@link submitPsbt} function.
|
|
835
|
+
* it back to the swap with {@link submitPsbt} function. The transaction should use at least the returned `feeRate`
|
|
836
|
+
* sats/vB as the transaction fee.
|
|
826
837
|
*/
|
|
827
838
|
async getPsbt(): Promise<{
|
|
828
839
|
psbt: Transaction,
|
|
829
840
|
psbtHex: string,
|
|
830
841
|
psbtBase64: string,
|
|
831
|
-
in1sequence: number
|
|
842
|
+
in1sequence: number,
|
|
843
|
+
feeRate: number
|
|
832
844
|
}> {
|
|
833
845
|
const res = await this.getTransactionDetails();
|
|
834
846
|
const psbt = new Transaction({
|
|
@@ -862,7 +874,8 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
862
874
|
psbt,
|
|
863
875
|
psbtHex: serializedPsbt.toString("hex"),
|
|
864
876
|
psbtBase64: serializedPsbt.toString("base64"),
|
|
865
|
-
in1sequence: res.in1sequence
|
|
877
|
+
in1sequence: res.in1sequence,
|
|
878
|
+
feeRate: this.minimumBtcFeeRate
|
|
866
879
|
};
|
|
867
880
|
}
|
|
868
881
|
|
|
@@ -892,7 +905,8 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
892
905
|
psbt: Transaction,
|
|
893
906
|
psbtHex: string,
|
|
894
907
|
psbtBase64: string,
|
|
895
|
-
signInputs: number[]
|
|
908
|
+
signInputs: number[],
|
|
909
|
+
feeRate: number
|
|
896
910
|
}> {
|
|
897
911
|
const bitcoinWallet: IBitcoinWallet = toBitcoinWallet(_bitcoinWallet, this.wrapper._btcRpc, this.wrapper._options.bitcoinNetwork);
|
|
898
912
|
if(feeRate!=null) {
|
|
@@ -919,7 +933,8 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
919
933
|
psbt,
|
|
920
934
|
psbtHex: serializedPsbt.toString("hex"),
|
|
921
935
|
psbtBase64: serializedPsbt.toString("base64"),
|
|
922
|
-
signInputs
|
|
936
|
+
signInputs,
|
|
937
|
+
feeRate
|
|
923
938
|
};
|
|
924
939
|
}
|
|
925
940
|
|
|
@@ -1000,7 +1015,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1000
1015
|
await this._saveAndEmit(SpvFromBTCSwapState.SIGNED);
|
|
1001
1016
|
|
|
1002
1017
|
try {
|
|
1003
|
-
await
|
|
1018
|
+
await this.wrapper._lpApi.initSpvFromBTC(
|
|
1004
1019
|
this.chainIdentifier,
|
|
1005
1020
|
this.url,
|
|
1006
1021
|
{
|
|
@@ -1102,39 +1117,329 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1102
1117
|
}
|
|
1103
1118
|
|
|
1104
1119
|
/**
|
|
1105
|
-
* @
|
|
1106
|
-
*
|
|
1107
|
-
* @param options.bitcoinFeeRate Optional fee rate to use for the created Bitcoin transaction
|
|
1108
|
-
* @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
|
|
1109
|
-
* if not provided a raw PSBT is returned instead which necessitates the implementor to manually add
|
|
1110
|
-
* inputs to the bitcoin transaction and **set the nSequence field of the 2nd input** (input 1 -
|
|
1111
|
-
* indexing from 0) to the value returned in `in1sequence`
|
|
1120
|
+
* @internal
|
|
1112
1121
|
*/
|
|
1113
|
-
async
|
|
1122
|
+
protected async _getExecutionStatus(options?: {
|
|
1114
1123
|
bitcoinFeeRate?: number,
|
|
1115
1124
|
bitcoinWallet?: MinimalBitcoinWalletInterface,
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1125
|
+
manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"],
|
|
1126
|
+
maxWaitTillAutomaticSettlementSeconds?: number
|
|
1127
|
+
}) {
|
|
1128
|
+
const state = this._state;
|
|
1129
|
+
const now = Date.now();
|
|
1130
|
+
|
|
1131
|
+
let confirmations: {
|
|
1132
|
+
current: number,
|
|
1133
|
+
target: number,
|
|
1134
|
+
etaSeconds: number
|
|
1135
|
+
} | undefined;
|
|
1136
|
+
|
|
1137
|
+
let bitcoinPaymentStatus: SwapExecutionStepPayment<"BITCOIN">["status"] = "inactive";
|
|
1138
|
+
let destinationSettlementStatus: SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">["status"] = "inactive";
|
|
1139
|
+
let buildCurrentAction: (actionOptions?: {
|
|
1140
|
+
bitcoinFeeRate?: number,
|
|
1141
|
+
bitcoinWallet?: MinimalBitcoinWalletInterface,
|
|
1142
|
+
manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"],
|
|
1143
|
+
maxWaitTillAutomaticSettlementSeconds?: number
|
|
1144
|
+
}) => Promise<
|
|
1145
|
+
SwapExecutionActionSignPSBT |
|
|
1146
|
+
SwapExecutionActionWait<"BITCOIN_CONFS" | "SETTLEMENT"> |
|
|
1147
|
+
SwapExecutionActionSignSmartChainTx<T> |
|
|
1148
|
+
undefined
|
|
1149
|
+
> = async () => undefined;
|
|
1150
|
+
|
|
1151
|
+
switch(state) {
|
|
1152
|
+
case SpvFromBTCSwapState.QUOTE_EXPIRED:
|
|
1153
|
+
case SpvFromBTCSwapState.DECLINED:
|
|
1154
|
+
case SpvFromBTCSwapState.FAILED:
|
|
1155
|
+
bitcoinPaymentStatus = "expired";
|
|
1156
|
+
break;
|
|
1157
|
+
case SpvFromBTCSwapState.CREATED: {
|
|
1158
|
+
const quoteValid = await this._verifyQuoteValid();
|
|
1159
|
+
bitcoinPaymentStatus = quoteValid ? "awaiting" : "soft_expired";
|
|
1160
|
+
if(quoteValid) {
|
|
1161
|
+
buildCurrentAction = this._buildDepositPsbtAction.bind(this);
|
|
1162
|
+
}
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
case SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED:
|
|
1166
|
+
case SpvFromBTCSwapState.SIGNED:
|
|
1167
|
+
case SpvFromBTCSwapState.POSTED:
|
|
1168
|
+
case SpvFromBTCSwapState.BROADCASTED:
|
|
1169
|
+
case SpvFromBTCSwapState.FRONTED: {
|
|
1170
|
+
const bitcoinPayment = await this.getBitcoinPayment();
|
|
1171
|
+
let bitcoinConfirmationDelay = -1;
|
|
1172
|
+
let knownBitcoinPaymentStatus: "received" | "confirmed" | undefined;
|
|
1173
|
+
if(bitcoinPayment!=null) {
|
|
1174
|
+
if(bitcoinPayment.confirmations >= bitcoinPayment.targetConfirmations) {
|
|
1175
|
+
knownBitcoinPaymentStatus = "confirmed";
|
|
1176
|
+
} else {
|
|
1177
|
+
const result = await this.wrapper._btcRpc.getConfirmationDelay(
|
|
1178
|
+
bitcoinPayment.btcTx,
|
|
1179
|
+
bitcoinPayment.targetConfirmations
|
|
1180
|
+
);
|
|
1181
|
+
confirmations = {
|
|
1182
|
+
current: bitcoinPayment.confirmations,
|
|
1183
|
+
target: bitcoinPayment.targetConfirmations,
|
|
1184
|
+
etaSeconds: result ?? -1
|
|
1185
|
+
};
|
|
1186
|
+
knownBitcoinPaymentStatus = "received";
|
|
1187
|
+
bitcoinConfirmationDelay = result ?? -1;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
if(state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED)
|
|
1191
|
+
bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "soft_expired";
|
|
1192
|
+
if(state===SpvFromBTCSwapState.POSTED || state===SpvFromBTCSwapState.SIGNED)
|
|
1193
|
+
bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "awaiting";
|
|
1194
|
+
if(state===SpvFromBTCSwapState.BROADCASTED)
|
|
1195
|
+
bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "received";
|
|
1196
|
+
destinationSettlementStatus = "inactive";
|
|
1197
|
+
|
|
1198
|
+
if(state===SpvFromBTCSwapState.FRONTED) {
|
|
1199
|
+
bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "received";
|
|
1200
|
+
destinationSettlementStatus = "settled";
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if(
|
|
1204
|
+
state===SpvFromBTCSwapState.SIGNED ||
|
|
1205
|
+
state===SpvFromBTCSwapState.POSTED ||
|
|
1206
|
+
state===SpvFromBTCSwapState.BROADCASTED
|
|
1207
|
+
) {
|
|
1208
|
+
buildCurrentAction = this._buildWaitBitcoinConfirmationsAction.bind(this, bitcoinConfirmationDelay);
|
|
1209
|
+
}
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
case SpvFromBTCSwapState.BTC_TX_CONFIRMED:
|
|
1213
|
+
bitcoinPaymentStatus = "confirmed";
|
|
1214
|
+
if(
|
|
1215
|
+
this.btcTxConfirmedAt==null ||
|
|
1216
|
+
options?.maxWaitTillAutomaticSettlementSeconds===0 ||
|
|
1217
|
+
(now - this.btcTxConfirmedAt) > (options?.maxWaitTillAutomaticSettlementSeconds ?? 60)*1000
|
|
1218
|
+
) {
|
|
1219
|
+
destinationSettlementStatus = "awaiting_manual";
|
|
1220
|
+
buildCurrentAction = this._buildClaimSmartChainTxAction.bind(this);
|
|
1221
|
+
} else {
|
|
1222
|
+
destinationSettlementStatus = "awaiting_automatic";
|
|
1223
|
+
buildCurrentAction = this._buildWaitSettlementAction.bind(this, options?.maxWaitTillAutomaticSettlementSeconds);
|
|
1224
|
+
}
|
|
1225
|
+
break;
|
|
1226
|
+
case SpvFromBTCSwapState.CLAIMED:
|
|
1227
|
+
bitcoinPaymentStatus = "confirmed";
|
|
1228
|
+
destinationSettlementStatus = "settled";
|
|
1229
|
+
break;
|
|
1230
|
+
case SpvFromBTCSwapState.CLOSED:
|
|
1231
|
+
bitcoinPaymentStatus = "confirmed";
|
|
1232
|
+
destinationSettlementStatus = "expired";
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
if(bitcoinPaymentStatus==="confirmed") {
|
|
1237
|
+
confirmations = {
|
|
1238
|
+
current: this.getRequiredConfirmationsCount(),
|
|
1239
|
+
target: this.getRequiredConfirmationsCount(),
|
|
1240
|
+
etaSeconds: 0
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
return {
|
|
1245
|
+
steps: [
|
|
1122
1246
|
{
|
|
1123
|
-
|
|
1124
|
-
|
|
1247
|
+
type: "Payment",
|
|
1248
|
+
side: "source",
|
|
1125
1249
|
chain: "BITCOIN",
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1250
|
+
title: "Bitcoin payment",
|
|
1251
|
+
description: "Sign and submit the Bitcoin swap PSBT, then wait for the bitcoin transaction to confirm",
|
|
1252
|
+
status: bitcoinPaymentStatus,
|
|
1253
|
+
confirmations,
|
|
1254
|
+
initTxId: this._data?.btcTx?.txid,
|
|
1255
|
+
settleTxId: bitcoinPaymentStatus==="confirmed" ? this._data?.btcTx?.txid : undefined
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
type: "Settlement",
|
|
1259
|
+
side: "destination",
|
|
1260
|
+
chain: this.chainIdentifier,
|
|
1261
|
+
title: "Destination settlement",
|
|
1262
|
+
description: `Wait for automatic settlement on the ${this.chainIdentifier} side, or settle manually if it takes too long`,
|
|
1263
|
+
status: destinationSettlementStatus,
|
|
1264
|
+
initTxId: this._frontTxId ?? this._claimTxId,
|
|
1265
|
+
settleTxId: this._frontTxId ?? this._claimTxId
|
|
1266
|
+
}
|
|
1267
|
+
] as [
|
|
1268
|
+
SwapExecutionStepPayment<"BITCOIN">,
|
|
1269
|
+
SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">
|
|
1270
|
+
],
|
|
1271
|
+
buildCurrentAction,
|
|
1272
|
+
state
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* @inheritDoc
|
|
1278
|
+
* @internal
|
|
1279
|
+
*/
|
|
1280
|
+
async _submitExecutionTransactions(txs: (T["SignedTXType"] | Transaction | string)[], abortSignal?: AbortSignal, requiredStates?: SpvFromBTCSwapState[], idempotent?: boolean): Promise<string[]> {
|
|
1281
|
+
if(txs.length===0) throw new Error("Need to submit at least 1 transaction in the array, submitted empty array of transactions!");
|
|
1282
|
+
|
|
1283
|
+
// Handle idempotent calls
|
|
1284
|
+
if(idempotent) {
|
|
1285
|
+
let idempotencyTriggered = false;
|
|
1286
|
+
const txIds: string[] = [];
|
|
1287
|
+
for(let tx of txs) {
|
|
1288
|
+
let parsedTx: T["SignedTXType"] | Transaction | undefined;
|
|
1289
|
+
if(typeof(tx)==="string") {
|
|
1290
|
+
try {
|
|
1291
|
+
parsedTx = await this.wrapper._chain.deserializeSignedTx(tx);
|
|
1292
|
+
} catch (e) {}
|
|
1293
|
+
try {
|
|
1294
|
+
parsedTx = parsePsbtTransaction(tx);
|
|
1295
|
+
} catch (e) {}
|
|
1296
|
+
} else {
|
|
1297
|
+
parsedTx = tx;
|
|
1131
1298
|
}
|
|
1132
|
-
|
|
1299
|
+
|
|
1300
|
+
if(parsedTx==null) {
|
|
1301
|
+
this.logger.debug("_submitExecutionTransactions(): Failed to parse provided execution transaction: ", tx);
|
|
1302
|
+
continue;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
if(parsedTx instanceof Transaction) {
|
|
1306
|
+
// Bitcoin tx
|
|
1307
|
+
const btcTx = await this.wrapper._btcRpc.parseTransaction(Buffer.from(parsedTx.toBytes(true)).toString("hex"));
|
|
1308
|
+
if(btcTx.txid===this._data?.getTxId()) {
|
|
1309
|
+
if(this._state!==SpvFromBTCSwapState.SIGNED && this._state!==SpvFromBTCSwapState.DECLINED)
|
|
1310
|
+
idempotencyTriggered = true;
|
|
1311
|
+
}
|
|
1312
|
+
txIds.push(btcTx.txid);
|
|
1313
|
+
} else {
|
|
1314
|
+
// SC tx
|
|
1315
|
+
if(this.wrapper._chain.getTxId!=null) {
|
|
1316
|
+
const txId = await this.wrapper._chain.getTxId(parsedTx);
|
|
1317
|
+
if(this._claimTxId===txId) idempotencyTriggered = true;
|
|
1318
|
+
txIds.push(txId);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if(idempotencyTriggered) return txIds;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
if(requiredStates!=null && !requiredStates.includes(this._state)) throw new Error("Swap state has changed before transactions were submitted!");
|
|
1326
|
+
|
|
1327
|
+
if(this._state===SpvFromBTCSwapState.CREATED || this._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED) {
|
|
1328
|
+
let psbt: string | Transaction;
|
|
1329
|
+
if(txs.length!==1) throw new Error("Need to submit exactly 1 signed PSBT!");
|
|
1330
|
+
if(typeof(txs[0])!=="string" && !(txs[0] instanceof Transaction))
|
|
1331
|
+
throw new Error("Must submit a valid PSBT as hex/base64 string or `@scure/btc-signer` Transaction object!");
|
|
1332
|
+
psbt = txs[0];
|
|
1333
|
+
return [await this.submitPsbt(psbt)];
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
if(this._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED) {
|
|
1337
|
+
const parsedTxs: T["SignedTXType"][] = [];
|
|
1338
|
+
for(let tx of txs) {
|
|
1339
|
+
parsedTxs.push(typeof(tx)==="string" ? await this.wrapper._chain.deserializeSignedTx(tx) : tx);
|
|
1340
|
+
}
|
|
1341
|
+
const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
|
|
1342
|
+
await this.waitTillClaimed(undefined, abortSignal);
|
|
1343
|
+
return txIds;
|
|
1133
1344
|
}
|
|
1134
1345
|
|
|
1135
|
-
throw new Error("Invalid swap state
|
|
1346
|
+
throw new Error("Invalid swap state for transaction submission!");
|
|
1136
1347
|
}
|
|
1137
1348
|
|
|
1349
|
+
/**
|
|
1350
|
+
* @internal
|
|
1351
|
+
*/
|
|
1352
|
+
private async _buildDepositPsbtAction(actionOptions?: {
|
|
1353
|
+
bitcoinFeeRate?: number,
|
|
1354
|
+
bitcoinWallet?: MinimalBitcoinWalletInterface
|
|
1355
|
+
}): Promise<SwapExecutionActionSignPSBT> {
|
|
1356
|
+
return {
|
|
1357
|
+
type: "SignPSBT",
|
|
1358
|
+
name: "Deposit on Bitcoin",
|
|
1359
|
+
description: "Send funds to the bitcoin swap address",
|
|
1360
|
+
chain: "BITCOIN",
|
|
1361
|
+
txs: [
|
|
1362
|
+
actionOptions?.bitcoinWallet==null
|
|
1363
|
+
? {...await this.getPsbt(), type: "RAW_PSBT"}
|
|
1364
|
+
: {...await this.getFundedPsbt(actionOptions.bitcoinWallet, actionOptions?.bitcoinFeeRate), type: "FUNDED_PSBT"}
|
|
1365
|
+
],
|
|
1366
|
+
submitPsbt: async (signedPsbt: string | Transaction | (string | Transaction)[], idempotent) => {
|
|
1367
|
+
return this._submitExecutionTransactions(
|
|
1368
|
+
Array.isArray(signedPsbt) ? signedPsbt : [signedPsbt],
|
|
1369
|
+
undefined,
|
|
1370
|
+
[SpvFromBTCSwapState.CREATED, SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED],
|
|
1371
|
+
idempotent
|
|
1372
|
+
);
|
|
1373
|
+
}
|
|
1374
|
+
} as SwapExecutionActionSignPSBT;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* @internal
|
|
1379
|
+
*/
|
|
1380
|
+
private async _buildWaitBitcoinConfirmationsAction(confirmationDelay: number): Promise<SwapExecutionActionWait<"BITCOIN_CONFS">> {
|
|
1381
|
+
return {
|
|
1382
|
+
type: "Wait",
|
|
1383
|
+
name: "Bitcoin confirmations",
|
|
1384
|
+
description: "Wait for bitcoin transaction to confirm",
|
|
1385
|
+
pollTimeSeconds: 10,
|
|
1386
|
+
expectedTimeSeconds: confirmationDelay===-1 ? -1 : Math.floor(confirmationDelay/1000),
|
|
1387
|
+
wait: async (
|
|
1388
|
+
maxWaitTimeSeconds?: number, pollIntervalSeconds?: number, abortSignal?: AbortSignal,
|
|
1389
|
+
btcConfirmationsCallback?: (txId?: string, confirmations?: number, targetConfirmations?: number, txEtaMs?: number) => void
|
|
1390
|
+
) => {
|
|
1391
|
+
const abortController = extendAbortController(
|
|
1392
|
+
abortSignal, maxWaitTimeSeconds, "Timed out waiting for bitcoin transaction"
|
|
1393
|
+
);
|
|
1394
|
+
await this.waitForBitcoinTransaction(btcConfirmationsCallback, pollIntervalSeconds, abortController.signal);
|
|
1395
|
+
}
|
|
1396
|
+
} as SwapExecutionActionWait<"BITCOIN_CONFS">;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* @internal
|
|
1401
|
+
*/
|
|
1402
|
+
private async _buildWaitSettlementAction(maxWaitTillAutomaticSettlementSeconds?: number): Promise<SwapExecutionActionWait<"SETTLEMENT">> {
|
|
1403
|
+
return {
|
|
1404
|
+
type: "Wait",
|
|
1405
|
+
name: "Automatic settlement",
|
|
1406
|
+
description: "Wait for bitcoin transaction to confirm",
|
|
1407
|
+
pollTimeSeconds: 5,
|
|
1408
|
+
expectedTimeSeconds: 10,
|
|
1409
|
+
wait: async (
|
|
1410
|
+
maxWaitTimeSeconds?: number, pollIntervalSeconds?: number, abortSignal?: AbortSignal
|
|
1411
|
+
) => {
|
|
1412
|
+
await this.waitTillClaimedOrFronted(maxWaitTimeSeconds ?? maxWaitTillAutomaticSettlementSeconds ?? 60, abortSignal, pollIntervalSeconds);
|
|
1413
|
+
}
|
|
1414
|
+
} as SwapExecutionActionWait<"SETTLEMENT">;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
/**
|
|
1418
|
+
* @internal
|
|
1419
|
+
*/
|
|
1420
|
+
private async _buildClaimSmartChainTxAction(actionOptions?: {
|
|
1421
|
+
manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"]
|
|
1422
|
+
}): Promise<SwapExecutionActionSignSmartChainTx<T>> {
|
|
1423
|
+
const signerAddress =
|
|
1424
|
+
await this.wrapper._getSignerAddress(actionOptions?.manualSettlementSmartChainSigner);
|
|
1425
|
+
|
|
1426
|
+
return {
|
|
1427
|
+
type: "SignSmartChainTransaction",
|
|
1428
|
+
name: "Settle manually",
|
|
1429
|
+
description: "Manually settle the swap on the destination smart chain",
|
|
1430
|
+
chain: this.chainIdentifier,
|
|
1431
|
+
txs: await this.prepareTransactions(this.txsClaim(actionOptions?.manualSettlementSmartChainSigner)),
|
|
1432
|
+
submitTransactions: async (txs: (T["SignedTXType"] | string)[], abortSignal?: AbortSignal, idempotent?: boolean) => {
|
|
1433
|
+
return this._submitExecutionTransactions(
|
|
1434
|
+
txs,
|
|
1435
|
+
abortSignal,
|
|
1436
|
+
[SpvFromBTCSwapState.BTC_TX_CONFIRMED],
|
|
1437
|
+
idempotent
|
|
1438
|
+
);
|
|
1439
|
+
},
|
|
1440
|
+
requiredSigner: signerAddress ?? this._getInitiator()
|
|
1441
|
+
} as SwapExecutionActionSignSmartChainTx<T>;
|
|
1442
|
+
}
|
|
1138
1443
|
|
|
1139
1444
|
/**
|
|
1140
1445
|
* @inheritDoc
|
|
@@ -1148,32 +1453,60 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1148
1453
|
* @param options.maxWaitTillAutomaticSettlementSeconds Maximum time to wait for an automatic settlement after
|
|
1149
1454
|
* the bitcoin transaction is confirmed (defaults to 60 seconds)
|
|
1150
1455
|
*/
|
|
1151
|
-
async
|
|
1456
|
+
async getExecutionAction(options?: {
|
|
1152
1457
|
bitcoinFeeRate?: number,
|
|
1153
1458
|
bitcoinWallet?: MinimalBitcoinWalletInterface,
|
|
1154
1459
|
manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"],
|
|
1155
1460
|
maxWaitTillAutomaticSettlementSeconds?: number
|
|
1156
|
-
}): Promise<
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1461
|
+
}): Promise<
|
|
1462
|
+
SwapExecutionActionSignPSBT |
|
|
1463
|
+
SwapExecutionActionWait<"BITCOIN_CONFS" | "SETTLEMENT"> |
|
|
1464
|
+
SwapExecutionActionSignSmartChainTx<T> |
|
|
1465
|
+
undefined
|
|
1466
|
+
> {
|
|
1467
|
+
const executionStatus = await this._getExecutionStatus(options);
|
|
1468
|
+
return executionStatus.buildCurrentAction(options);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/**
|
|
1472
|
+
* @inheritDoc
|
|
1473
|
+
*/
|
|
1474
|
+
async getExecutionStatus(options?: {
|
|
1475
|
+
skipBuildingAction?: boolean,
|
|
1476
|
+
bitcoinFeeRate?: number,
|
|
1477
|
+
bitcoinWallet?: MinimalBitcoinWalletInterface,
|
|
1478
|
+
manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"],
|
|
1479
|
+
maxWaitTillAutomaticSettlementSeconds?: number
|
|
1480
|
+
}): Promise<{
|
|
1481
|
+
steps: [
|
|
1482
|
+
SwapExecutionStepPayment<"BITCOIN">,
|
|
1483
|
+
SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">
|
|
1484
|
+
],
|
|
1485
|
+
currentAction:
|
|
1486
|
+
SwapExecutionActionSignPSBT |
|
|
1487
|
+
SwapExecutionActionWait<"BITCOIN_CONFS" | "SETTLEMENT"> |
|
|
1488
|
+
SwapExecutionActionSignSmartChainTx<T> |
|
|
1489
|
+
undefined,
|
|
1490
|
+
stateInfo: SwapStateInfo<SpvFromBTCSwapState>
|
|
1491
|
+
}> {
|
|
1492
|
+
const executionStatus = await this._getExecutionStatus(options);
|
|
1493
|
+
return {
|
|
1494
|
+
steps: executionStatus.steps,
|
|
1495
|
+
currentAction: options?.skipBuildingAction ? undefined : await executionStatus.buildCurrentAction(options),
|
|
1496
|
+
stateInfo: this._getStateInfo(executionStatus.state)
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/**
|
|
1501
|
+
* @inheritDoc
|
|
1502
|
+
*/
|
|
1503
|
+
async getExecutionSteps(options?: {
|
|
1504
|
+
maxWaitTillAutomaticSettlementSeconds?: number
|
|
1505
|
+
}): Promise<[
|
|
1506
|
+
SwapExecutionStepPayment<"BITCOIN">,
|
|
1507
|
+
SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">
|
|
1508
|
+
]> {
|
|
1509
|
+
return (await this._getExecutionStatus(options)).steps;
|
|
1177
1510
|
}
|
|
1178
1511
|
|
|
1179
1512
|
|
|
@@ -1188,6 +1521,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1188
1521
|
txId: string,
|
|
1189
1522
|
confirmations: number,
|
|
1190
1523
|
targetConfirmations: number,
|
|
1524
|
+
btcTx: BtcTx,
|
|
1191
1525
|
inputAddresses?: string[]
|
|
1192
1526
|
} | null> {
|
|
1193
1527
|
if(this._data?.btcTx?.txid==null) return null;
|
|
@@ -1199,6 +1533,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1199
1533
|
txId: result.txid,
|
|
1200
1534
|
confirmations: result.confirmations ?? 0,
|
|
1201
1535
|
targetConfirmations: this.vaultRequiredConfirmations,
|
|
1536
|
+
btcTx: result,
|
|
1202
1537
|
inputAddresses: result.inputAddresses
|
|
1203
1538
|
}
|
|
1204
1539
|
}
|
|
@@ -1379,11 +1714,11 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1379
1714
|
/**
|
|
1380
1715
|
* Periodically checks the chain to see whether the swap was finished (claimed or refunded)
|
|
1381
1716
|
*
|
|
1382
|
-
* @param abortSignal
|
|
1383
1717
|
* @param interval How often to check (in seconds), default to 5s
|
|
1718
|
+
* @param abortSignal
|
|
1384
1719
|
* @internal
|
|
1385
1720
|
*/
|
|
1386
|
-
protected async watchdogWaitTillResult(
|
|
1721
|
+
protected async watchdogWaitTillResult(interval: number = 5, abortSignal?: AbortSignal): Promise<
|
|
1387
1722
|
SpvWithdrawalClaimedState | SpvWithdrawalFrontedState | SpvWithdrawalClosedState
|
|
1388
1723
|
> {
|
|
1389
1724
|
if(this._data==null) throw new Error("Cannot await the result before the btc transaction is sent!");
|
|
@@ -1429,11 +1764,12 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1429
1764
|
* @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled (by default
|
|
1430
1765
|
* it waits indefinitely)
|
|
1431
1766
|
* @param abortSignal Abort signal
|
|
1767
|
+
* @param pollIntervalSeconds How often to poll via the watchdog
|
|
1432
1768
|
*
|
|
1433
1769
|
* @returns {boolean} whether the swap was claimed or fronted automatically or not, if the swap was not claimed
|
|
1434
1770
|
* the user can claim manually through the {@link claim} function
|
|
1435
1771
|
*/
|
|
1436
|
-
async waitTillClaimedOrFronted(maxWaitTimeSeconds?: number, abortSignal?: AbortSignal): Promise<boolean> {
|
|
1772
|
+
async waitTillClaimedOrFronted(maxWaitTimeSeconds?: number, abortSignal?: AbortSignal, pollIntervalSeconds?: number): Promise<boolean> {
|
|
1437
1773
|
if(this._state===SpvFromBTCSwapState.CLAIMED || this._state===SpvFromBTCSwapState.FRONTED) return Promise.resolve(true);
|
|
1438
1774
|
|
|
1439
1775
|
const abortController = extendAbortController(abortSignal);
|
|
@@ -1450,7 +1786,7 @@ export class SpvFromBTCSwap<T extends ChainType>
|
|
|
1450
1786
|
let res: number | SpvWithdrawalState;
|
|
1451
1787
|
try {
|
|
1452
1788
|
res = await Promise.race([
|
|
1453
|
-
this.watchdogWaitTillResult(abortController.signal),
|
|
1789
|
+
this.watchdogWaitTillResult(pollIntervalSeconds, abortController.signal),
|
|
1454
1790
|
this.waitTillState(SpvFromBTCSwapState.CLAIMED, "eq", abortController.signal).then(() => 0),
|
|
1455
1791
|
this.waitTillState(SpvFromBTCSwapState.FRONTED, "eq", abortController.signal).then(() => 1),
|
|
1456
1792
|
this.waitTillState(SpvFromBTCSwapState.FAILED, "eq", abortController.signal).then(() => 2),
|
|
@@ -225,6 +225,7 @@ export class SpvFromBTCWrapper<
|
|
|
225
225
|
* @param versionedContracts
|
|
226
226
|
* @param versionedSynchronizer
|
|
227
227
|
* @param btcRpc Bitcoin RPC which also supports getting transactions by txoHash
|
|
228
|
+
* @param lpApi
|
|
228
229
|
* @param options
|
|
229
230
|
* @param events Instance to use for emitting events
|
|
230
231
|
*/
|
|
@@ -248,11 +249,12 @@ export class SpvFromBTCWrapper<
|
|
|
248
249
|
}
|
|
249
250
|
},
|
|
250
251
|
btcRpc: BitcoinRpcWithAddressIndex<any>,
|
|
252
|
+
lpApi: IntermediaryAPI,
|
|
251
253
|
options?: AllOptional<SpvFromBTCWrapperOptions>,
|
|
252
254
|
events?: EventEmitter<{swapState: [ISwap]}>
|
|
253
255
|
) {
|
|
254
256
|
super(
|
|
255
|
-
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens,
|
|
257
|
+
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, lpApi,
|
|
256
258
|
{
|
|
257
259
|
...options,
|
|
258
260
|
bitcoinNetwork: options?.bitcoinNetwork ?? TEST_NETWORK,
|
|
@@ -834,7 +836,7 @@ export class SpvFromBTCWrapper<
|
|
|
834
836
|
|
|
835
837
|
try {
|
|
836
838
|
const resp = await tryWithRetries(async(retryCount: number) => {
|
|
837
|
-
return await
|
|
839
|
+
return await this._lpApi.prepareSpvFromBTC(
|
|
838
840
|
this.chainIdentifier, lp.url,
|
|
839
841
|
{
|
|
840
842
|
address: recipient,
|
|
@@ -935,7 +937,7 @@ export class SpvFromBTCWrapper<
|
|
|
935
937
|
|
|
936
938
|
genesisSmartChainBlockHeight: await throwIfUndefined(
|
|
937
939
|
finalizedBlockHeightPrefetchPromise,
|
|
938
|
-
"
|
|
940
|
+
"Network finalized blockheight pre-fetch failed!"
|
|
939
941
|
),
|
|
940
942
|
contractVersion: version
|
|
941
943
|
};
|