@atomiqlabs/sdk 8.6.3 → 8.7.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.
Files changed (78) hide show
  1. package/dist/events/UnifiedSwapEventListener.js +4 -2
  2. package/dist/intermediaries/Intermediary.d.ts +21 -0
  3. package/dist/intermediaries/Intermediary.js +25 -1
  4. package/dist/intermediaries/IntermediaryDiscovery.d.ts +15 -3
  5. package/dist/intermediaries/IntermediaryDiscovery.js +21 -3
  6. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +1 -0
  7. package/dist/swapper/Swapper.d.ts +9 -4
  8. package/dist/swapper/Swapper.js +89 -41
  9. package/dist/swapper/SwapperUtils.js +2 -1
  10. package/dist/swaps/ISwap.d.ts +5 -0
  11. package/dist/swaps/ISwap.js +4 -1
  12. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +5 -5
  13. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +4 -0
  14. package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -3
  15. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +19 -6
  16. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +54 -21
  17. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +7 -3
  18. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -4
  19. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +3 -3
  20. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +8 -2
  21. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +12 -8
  22. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +18 -18
  23. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +12 -6
  24. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +38 -24
  25. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +9 -9
  26. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +14 -7
  27. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +54 -38
  28. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +5 -5
  29. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +18 -7
  30. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +61 -33
  31. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +12 -12
  32. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +8 -2
  33. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +13 -8
  34. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +1 -1
  35. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +13 -4
  36. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +44 -28
  37. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +2 -2
  38. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +8 -4
  39. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +29 -21
  40. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +1 -0
  41. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +13 -12
  42. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +21 -10
  43. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +136 -73
  44. package/dist/swaps/trusted/ln/LnForGasWrapper.js +2 -1
  45. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +2 -1
  46. package/dist/utils/Utils.d.ts +9 -0
  47. package/dist/utils/Utils.js +15 -1
  48. package/package.json +2 -2
  49. package/src/events/UnifiedSwapEventListener.ts +4 -2
  50. package/src/intermediaries/Intermediary.ts +31 -1
  51. package/src/intermediaries/IntermediaryDiscovery.ts +27 -8
  52. package/src/intermediaries/apis/IntermediaryAPI.ts +2 -1
  53. package/src/swapper/Swapper.ts +133 -61
  54. package/src/swapper/SwapperUtils.ts +3 -1
  55. package/src/swaps/ISwap.ts +10 -2
  56. package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +5 -5
  57. package/src/swaps/escrow_swaps/IEscrowSwap.ts +10 -3
  58. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +64 -26
  59. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +8 -5
  60. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +3 -3
  61. package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +22 -12
  62. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +18 -18
  63. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +52 -31
  64. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +9 -9
  65. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +76 -52
  66. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +5 -5
  67. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +82 -38
  68. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +12 -12
  69. package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +21 -9
  70. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +1 -1
  71. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +56 -33
  72. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +2 -2
  73. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +40 -22
  74. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +17 -13
  75. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +149 -83
  76. package/src/swaps/trusted/ln/LnForGasWrapper.ts +2 -1
  77. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +2 -1
  78. package/src/utils/Utils.ts +14 -0
@@ -6,7 +6,7 @@ import {
6
6
  ChainSwapType,
7
7
  ChainType, LightningNetworkApi,
8
8
  Messenger,
9
- RelaySynchronizer
9
+ RelaySynchronizer, SpvWithdrawalClaimedState, SpvWithdrawalFrontedState, SwapCommitState, SwapContract, SwapData
10
10
  } from "@atomiqlabs/base";
11
11
  import {
12
12
  ToBTCLNOptions,
@@ -190,14 +190,20 @@ type ChainSpecificData<T extends ChainType> = {
190
190
  [SwapType.FROM_BTCLN_AUTO]: FromBTCLNAutoWrapper<T>
191
191
  }
192
192
  chainEvents: T["Events"],
193
- swapContract: T["Contract"],
194
- spvVaultContract: T["SpvVaultContract"],
195
193
  chainInterface: T["ChainInterface"],
196
- btcRelay: BtcRelay<any, T["TX"], BtcBlock, T["Signer"]>,
197
- synchronizer: RelaySynchronizer<any, T["TX"], BtcBlock>,
198
194
  unifiedChainEvents: UnifiedSwapEventListener<T>,
199
195
  unifiedSwapStorage: UnifiedSwapStorage<T>,
200
- reviver: (val: any) => ISwap<T>
196
+ reviver: (val: any) => ISwap<T>,
197
+ defaultVersion: string,
198
+
199
+ versionedContracts: {
200
+ [contractVersion: string]: {
201
+ swapContract: T["Contract"],
202
+ spvVaultContract: T["SpvVaultContract"],
203
+ btcRelay: BtcRelay<any, T["TX"], BtcBlock, T["Signer"]>,
204
+ synchronizer: RelaySynchronizer<any, T["TX"], BtcBlock>,
205
+ }
206
+ }
201
207
  };
202
208
 
203
209
  type MultiChainData<T extends MultiChain> = {
@@ -358,12 +364,37 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
358
364
  };
359
365
 
360
366
  this._chains = objectMap<CtorMultiChainData<T>, MultiChainData<T>>(chainsData, <InputKey extends keyof CtorMultiChainData<T>>(chainData: CtorMultiChainData<T>[InputKey], key: string) => {
361
- const {
362
- swapContract, chainEvents, btcRelay,
363
- chainInterface, spvVaultContract, spvVaultWithdrawalDataConstructor,
364
- chainId
367
+ let {
368
+ chainInterface, chainEvents, chainId,
369
+ btcRelay,
370
+ swapContract, swapDataConstructor,
371
+ spvVaultContract, spvVaultWithdrawalDataConstructor, spvVaultDataConstructor,
372
+ defaultVersion, versions
365
373
  } = chainData;
366
- const synchronizer = bitcoinSynchronizer(btcRelay);
374
+
375
+ defaultVersion ??= "v1";
376
+
377
+ if(versions==null) {
378
+ versions = {
379
+ [defaultVersion]: {
380
+ btcRelay,
381
+ swapContract,
382
+ swapDataConstructor,
383
+ spvVaultContract,
384
+ spvVaultDataConstructor,
385
+ spvVaultWithdrawalDataConstructor
386
+ }
387
+ }
388
+ }
389
+
390
+ const versionedContracts = objectMap(versions, (value, key) => {
391
+ return {
392
+ swapContract: value.swapContract,
393
+ spvVaultContract: value.spvVaultContract,
394
+ btcRelay: value.btcRelay,
395
+ synchronizer: bitcoinSynchronizer(value.btcRelay)
396
+ };
397
+ });
367
398
 
368
399
  const storageHandler = swapStorage(storagePrefix + chainId);
369
400
  const unifiedSwapStorage = new UnifiedSwapStorage<T[InputKey]>(storageHandler, this.options.noSwapCache);
@@ -376,10 +407,9 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
376
407
  unifiedSwapStorage,
377
408
  unifiedChainEvents,
378
409
  chainInterface,
379
- swapContract,
380
410
  pricing,
381
411
  this._tokens[chainId],
382
- chainData.swapDataConstructor,
412
+ versions,
383
413
  {
384
414
  getRequestTimeout: this.options.getRequestTimeout,
385
415
  postRequestTimeout: this.options.postRequestTimeout,
@@ -391,10 +421,9 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
391
421
  unifiedSwapStorage,
392
422
  unifiedChainEvents,
393
423
  chainInterface,
394
- swapContract,
395
424
  pricing,
396
425
  this._tokens[chainId],
397
- chainData.swapDataConstructor,
426
+ versions,
398
427
  this._bitcoinRpc,
399
428
  {
400
429
  getRequestTimeout: this.options.getRequestTimeout,
@@ -408,10 +437,9 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
408
437
  unifiedSwapStorage,
409
438
  unifiedChainEvents,
410
439
  chainInterface,
411
- swapContract,
412
440
  pricing,
413
441
  this._tokens[chainId],
414
- chainData.swapDataConstructor,
442
+ versions,
415
443
  lightningApi,
416
444
  {
417
445
  getRequestTimeout: this.options.getRequestTimeout,
@@ -425,12 +453,10 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
425
453
  unifiedSwapStorage,
426
454
  unifiedChainEvents,
427
455
  chainInterface,
428
- swapContract,
429
456
  pricing,
430
457
  this._tokens[chainId],
431
- chainData.swapDataConstructor,
432
- btcRelay,
433
- synchronizer,
458
+ versions,
459
+ versionedContracts,
434
460
  this._bitcoinRpc,
435
461
  {
436
462
  getRequestTimeout: this.options.getRequestTimeout,
@@ -468,18 +494,17 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
468
494
  }
469
495
  );
470
496
 
497
+ // This is gated on the default version of the contracts
471
498
  if(spvVaultContract!=null) {
472
499
  wrappers[SwapType.SPV_VAULT_FROM_BTC] = new SpvFromBTCWrapper<T[InputKey]>(
473
500
  key,
474
501
  unifiedSwapStorage,
475
502
  unifiedChainEvents,
476
503
  chainInterface,
477
- spvVaultContract,
478
504
  pricing,
479
505
  this._tokens[chainId],
480
- spvVaultWithdrawalDataConstructor,
481
- btcRelay,
482
- synchronizer,
506
+ versions,
507
+ versionedContracts,
483
508
  bitcoinRpc,
484
509
  {
485
510
  getRequestTimeout: this.options.getRequestTimeout,
@@ -490,16 +515,16 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
490
515
  );
491
516
  }
492
517
 
518
+ // This is gated on the default version of the contracts
493
519
  if(swapContract.supportsInitWithoutClaimer) {
494
520
  wrappers[SwapType.FROM_BTCLN_AUTO] = new FromBTCLNAutoWrapper<T[InputKey]>(
495
521
  key,
496
522
  unifiedSwapStorage,
497
523
  unifiedChainEvents,
498
524
  chainInterface,
499
- swapContract,
500
525
  pricing,
501
526
  this._tokens[chainId],
502
- chainData.swapDataConstructor,
527
+ versions,
503
528
  lightningApi,
504
529
  this.messenger,
505
530
  {
@@ -521,22 +546,22 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
521
546
 
522
547
  return {
523
548
  chainEvents,
524
- spvVaultContract,
525
- swapContract,
526
549
  chainInterface,
527
- btcRelay,
528
- synchronizer,
529
550
 
530
551
  wrappers,
531
552
 
532
553
  unifiedChainEvents,
533
554
  unifiedSwapStorage,
534
555
 
535
- reviver
556
+ defaultVersion,
557
+
558
+ reviver,
559
+
560
+ versionedContracts
536
561
  }
537
562
  });
538
563
 
539
- const contracts = objectMap(chainsData, (data) => data.swapContract);
564
+ const contracts = objectMap(chainsData, (data) => data.versions ?? {[data.defaultVersion ?? "v1"]: {swapContract: data.swapContract, spvVaultContract: data.spvVaultContract}});
540
565
  if(options.intermediaryUrl!=null) {
541
566
  this.intermediaryDiscovery = new IntermediaryDiscovery(contracts, options.registryUrl, Array.isArray(options.intermediaryUrl) ? options.intermediaryUrl : [options.intermediaryUrl], options.getRequestTimeout);
542
567
  } else {
@@ -595,7 +620,7 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
595
620
  chainPromises.push((async() => {
596
621
  const {
597
622
  chainInterface,
598
- swapContract,
623
+ versionedContracts,
599
624
  unifiedChainEvents,
600
625
  unifiedSwapStorage,
601
626
  wrappers,
@@ -607,8 +632,10 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
607
632
  await _chainInterface.verifyNetwork(this.bitcoinNetwork);
608
633
  }
609
634
 
610
- await swapContract.start();
611
- this.logger.debug("init(): Intialized swap contract: "+chainIdentifier);
635
+ for(let contractVersion in versionedContracts) {
636
+ await versionedContracts[contractVersion].swapContract.start();
637
+ this.logger.debug("init(): Intialized swap contract: "+chainIdentifier+` version: ${contractVersion}`);
638
+ }
612
639
 
613
640
  await unifiedSwapStorage.init();
614
641
  if(unifiedSwapStorage.storage instanceof IndexedDBUnifiedStorage) {
@@ -1872,18 +1899,56 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
1872
1899
  * initiated after this blockheight
1873
1900
  */
1874
1901
  async recoverSwaps<C extends ChainIds<T>>(chainId: C, signer: string, startBlockheight?: number): Promise<ISwap<T[C]>[]> {
1875
- const {spvVaultContract, swapContract, unifiedSwapStorage, reviver, wrappers} = this._chains[chainId];
1902
+ //TODO: Recover swaps from all the known contract versions
1903
+ const {versionedContracts, unifiedSwapStorage, reviver, wrappers} = this._chains[chainId];
1876
1904
 
1877
- if(
1878
- swapContract.getHistoricalSwaps==null ||
1879
- (spvVaultContract!=null && spvVaultContract.getHistoricalWithdrawalStates==null)
1880
- ) throw new Error(`Historical swap recovery is not supported for ${chainId}`);
1905
+ const recoveredSwaps: ISwap<T[C]>[] = [];
1906
+ let someVersionSupportsRecovery = false;
1907
+ const recoveredEscrowStates: {
1908
+ [p: string]: {
1909
+ init?: {
1910
+ data: SwapData
1911
+ getInitTxId: () => Promise<string>
1912
+ getTxBlock: () => Promise<{
1913
+ blockTime: number
1914
+ blockHeight: number
1915
+ }>
1916
+ },
1917
+ state: SwapCommitState
1918
+ contractVersion: string
1919
+ }
1920
+ } = {};
1921
+ const recoveredSpvStates: {
1922
+ [contractVersion: string]: {
1923
+ [escrowHash: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState
1924
+ }
1925
+ } = {};
1926
+
1927
+ for(let contractVersion in versionedContracts) {
1928
+ const {swapContract, spvVaultContract} = versionedContracts[contractVersion];
1929
+
1930
+ if(
1931
+ swapContract.getHistoricalSwaps==null ||
1932
+ (spvVaultContract!=null && spvVaultContract.getHistoricalWithdrawalStates==null)
1933
+ ) {
1934
+ this.logger.warn(`recoverSwaps(): Swap data recovery not supported on ${chainId}, with contract version ${contractVersion}`);
1935
+ continue;
1936
+ }
1937
+
1938
+ someVersionSupportsRecovery = true;
1881
1939
 
1882
- const {swaps} = await swapContract.getHistoricalSwaps(signer, startBlockheight);
1883
- const spvVaultData = await spvVaultContract?.getHistoricalWithdrawalStates!(signer, startBlockheight);
1940
+ const {swaps} = await swapContract.getHistoricalSwaps(signer, startBlockheight);
1941
+ const spvVaultData = wrappers[SwapType.SPV_VAULT_FROM_BTC]==null
1942
+ ? undefined
1943
+ : await spvVaultContract?.getHistoricalWithdrawalStates!(signer, startBlockheight);
1884
1944
 
1885
- const escrowHashes = Object.keys(swaps);
1886
- if(spvVaultData!=null) Object.keys(spvVaultData.withdrawals).forEach(btcTxId => escrowHashes.push(btcTxId));
1945
+ for(let key in swaps) recoveredEscrowStates[key] = {...swaps[key], contractVersion};
1946
+ if(spvVaultData!=null) for(let key in spvVaultData.withdrawals) (recoveredSpvStates[contractVersion] ??= {})[key] = spvVaultData.withdrawals[key];
1947
+ }
1948
+ if(!someVersionSupportsRecovery) throw new Error(`Historical swap recovery is not supported for ${chainId}`);
1949
+
1950
+ const escrowHashes = Object.keys(recoveredEscrowStates);
1951
+ for(let contractVersion in recoveredSpvStates) Object.keys(recoveredSpvStates[contractVersion]).forEach(btcTxId => escrowHashes.push(btcTxId));
1887
1952
  this.logger.debug(`recoverSwaps(): Loaded on-chain data for ${escrowHashes.length} swaps`);
1888
1953
  this.logger.debug(`recoverSwaps(): Fetching if swap escrowHashes are known: ${escrowHashes.join(", ")}`);
1889
1954
  const knownSwapsArray = await unifiedSwapStorage.query([[{key: "escrowHash", value: escrowHashes}]], reviver);
@@ -1894,11 +1959,10 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
1894
1959
  });
1895
1960
  this.logger.debug(`recoverSwaps(): Fetched known swaps escrowHashes: ${Object.keys(knownSwaps).join(", ")}`);
1896
1961
 
1897
- const recoveredSwaps: ISwap<T[C]>[] = [];
1898
-
1899
- for(let escrowHash in swaps) {
1900
- const {init, state} = swaps[escrowHash];
1962
+ for(let escrowHash in recoveredEscrowStates) {
1963
+ const {init, state, contractVersion} = recoveredEscrowStates[escrowHash];
1901
1964
  const knownSwap = knownSwaps[escrowHash];
1965
+ const { swapContract } = versionedContracts[contractVersion];
1902
1966
 
1903
1967
  if(knownSwap==null) {
1904
1968
  if(init==null) {
@@ -1907,6 +1971,10 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
1907
1971
  }
1908
1972
  } else if(knownSwap instanceof IEscrowSwap) {
1909
1973
  this.logger.debug(`recoverSwaps(escrow): Forcibly updating ${escrowHash} swap: swap already known and in local storage!`);
1974
+ if((knownSwap._contractVersion ?? "v1")!==contractVersion) {
1975
+ this.logger.debug(`recoverSwaps(escrow): Skipping ${escrowHash} swap: swap uses contract version ${knownSwap._contractVersion ?? "v1"}, but state comes from ${contractVersion}!`);
1976
+ continue;
1977
+ }
1910
1978
  if(await knownSwap._forciblySetOnchainState(state)) {
1911
1979
  await knownSwap._save();
1912
1980
  }
@@ -1926,27 +1994,27 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
1926
1994
  //To BTCLN
1927
1995
  typeIdentified = true;
1928
1996
  const lp = this.intermediaryDiscovery.intermediaries.find(val => val.supportsChain(chainId) && data.isClaimer(val.getAddress(chainId)));
1929
- swap = await wrappers[SwapType.TO_BTCLN].recoverFromSwapDataAndState(init, state, lp);
1997
+ swap = await wrappers[SwapType.TO_BTCLN].recoverFromSwapDataAndState(init, state, contractVersion, lp);
1930
1998
  } else if(data.isClaimer(signer)) {
1931
1999
  //From BTCLN
1932
2000
  typeIdentified = true;
1933
2001
  const lp = this.intermediaryDiscovery.intermediaries.find(val => val.supportsChain(chainId) && data.isOfferer(val.getAddress(chainId)));
1934
- if(this.supportsSwapType(chainId, SwapType.FROM_BTCLN_AUTO)) {
1935
- swap = await wrappers[SwapType.FROM_BTCLN_AUTO].recoverFromSwapDataAndState(init, state, lp);
2002
+ if(swapContract.supportsInitWithoutClaimer && wrappers[SwapType.FROM_BTCLN_AUTO]!=null) {
2003
+ swap = await wrappers[SwapType.FROM_BTCLN_AUTO].recoverFromSwapDataAndState(init, state, contractVersion, lp);
1936
2004
  } else {
1937
- swap = await wrappers[SwapType.FROM_BTCLN].recoverFromSwapDataAndState(init, state, lp);
2005
+ swap = await wrappers[SwapType.FROM_BTCLN].recoverFromSwapDataAndState(init, state, contractVersion, lp);
1938
2006
  }
1939
2007
  }
1940
2008
  } else if(data.getType()===ChainSwapType.CHAIN_NONCED) {
1941
2009
  //To BTC
1942
2010
  typeIdentified = true;
1943
2011
  const lp = this.intermediaryDiscovery.intermediaries.find(val => val.supportsChain(chainId) && data.isClaimer(val.getAddress(chainId)));
1944
- swap = await wrappers[SwapType.TO_BTC].recoverFromSwapDataAndState(init, state, lp);
2012
+ swap = await wrappers[SwapType.TO_BTC].recoverFromSwapDataAndState(init, state, contractVersion, lp);
1945
2013
  } else if(data.getType()===ChainSwapType.CHAIN) {
1946
2014
  //From BTC
1947
2015
  typeIdentified = true;
1948
2016
  const lp = this.intermediaryDiscovery.intermediaries.find(val => val.supportsChain(chainId) && data.isOfferer(val.getAddress(chainId)));
1949
- swap = await wrappers[SwapType.FROM_BTC].recoverFromSwapDataAndState(init, state, lp);
2017
+ swap = await wrappers[SwapType.FROM_BTC].recoverFromSwapDataAndState(init, state, contractVersion, lp);
1950
2018
  }
1951
2019
 
1952
2020
  if(swap!=null) {
@@ -1956,17 +2024,20 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
1956
2024
  }
1957
2025
  }
1958
2026
 
1959
- if(spvVaultContract!=null && spvVaultData!=null) {
2027
+ for(let contractVersion in recoveredSpvStates) {
2028
+ const { spvVaultContract } = versionedContracts[contractVersion];
2029
+ const spvVaultData = recoveredSpvStates[contractVersion];
2030
+
1960
2031
  const vaultsData = await spvVaultContract.getMultipleVaultData(
1961
- Object.keys(spvVaultData.withdrawals)
2032
+ Object.keys(spvVaultData)
1962
2033
  .map(btcTxId => ({
1963
- owner: spvVaultData.withdrawals[btcTxId].owner,
1964
- vaultId: spvVaultData.withdrawals[btcTxId].vaultId
2034
+ owner: spvVaultData[btcTxId].owner,
2035
+ vaultId: spvVaultData[btcTxId].vaultId
1965
2036
  }))
1966
2037
  );
1967
2038
 
1968
- for(let btcTxId in spvVaultData.withdrawals) {
1969
- const state = spvVaultData.withdrawals[btcTxId];
2039
+ for(let btcTxId in spvVaultData) {
2040
+ const state = spvVaultData[btcTxId];
1970
2041
  const knownSwap = knownSwaps[btcTxId];
1971
2042
 
1972
2043
  if(knownSwap!=null) {
@@ -1988,6 +2059,7 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
1988
2059
  );
1989
2060
  const swap = await wrappers[SwapType.SPV_VAULT_FROM_BTC].recoverFromState(
1990
2061
  state,
2062
+ contractVersion,
1991
2063
  vaultsData[state.owner]?.[state.vaultId.toString(10)],
1992
2064
  lp
1993
2065
  );
@@ -404,7 +404,9 @@ export class SwapperUtils<T extends MultiChain> {
404
404
  feeRate?: any
405
405
  }): Promise<TokenAmount> {
406
406
  if(this.root._chains[token.chainId]==null) throw new Error("Invalid chain identifier! Unknown chain: "+token.chainId);
407
- const {swapContract, chainInterface} = this.root._chains[token.chainId];
407
+ const {defaultVersion, versionedContracts, chainInterface} = this.root._chains[token.chainId];
408
+
409
+ const {swapContract} = versionedContracts[defaultVersion];
408
410
 
409
411
  let signer: string;
410
412
  if(typeof(wallet)==="string") {
@@ -25,7 +25,8 @@ export type ISwapInit = {
25
25
  expiry: number,
26
26
  swapFee: bigint,
27
27
  swapFeeBtc: bigint,
28
- exactIn: boolean
28
+ exactIn: boolean,
29
+ contractVersion: string
29
30
  };
30
31
 
31
32
  /**
@@ -140,6 +141,10 @@ export abstract class ISwap<
140
141
  * @internal
141
142
  */
142
143
  _persisted: boolean = false;
144
+ /**
145
+ * @internal
146
+ */
147
+ _contractVersion?: string;
143
148
 
144
149
 
145
150
  /**
@@ -181,6 +186,7 @@ export abstract class ISwap<
181
186
  this.version = this.currentVersion;
182
187
  this.createdAt = Date.now();
183
188
  this._randomNonce = randomBytes(16).toString("hex");
189
+ this._contractVersion = swapInitOrObj.contractVersion;
184
190
  } else {
185
191
  this.expiry = swapInitOrObj.expiry;
186
192
  this.url = swapInitOrObj.url;
@@ -211,6 +217,7 @@ export abstract class ISwap<
211
217
  this.createdAt = swapInitOrObj.createdAt ?? swapInitOrObj.expiry;
212
218
 
213
219
  this._randomNonce = swapInitOrObj.randomNonce;
220
+ this._contractVersion = swapInitOrObj.contractVersion;
214
221
  }
215
222
  if(this.version!==this.currentVersion) {
216
223
  this.upgradeVersion();
@@ -637,7 +644,8 @@ export abstract class ISwap<
637
644
  initiated: this.initiated,
638
645
  exactIn: this.exactIn,
639
646
  createdAt: this.createdAt,
640
- randomNonce: this._randomNonce
647
+ randomNonce: this._randomNonce,
648
+ contractVersion: this._contractVersion
641
649
  }
642
650
  }
643
651
 
@@ -89,7 +89,7 @@ export abstract class IEscrowSelfInitSwap<
89
89
  while(!expired) {
90
90
  await timeoutPromise(intervalSeconds*1000, abortSignal);
91
91
  try {
92
- expired = await this.wrapper._contract.isInitAuthorizationExpired(this._data, this.signatureData);
92
+ expired = await this._contract.isInitAuthorizationExpired(this._data, this.signatureData);
93
93
  } catch (e) {
94
94
  this.logger.error("watchdogWaitTillSignatureExpiry(): Error when checking signature expiry: ", e);
95
95
  }
@@ -106,14 +106,14 @@ export abstract class IEscrowSelfInitSwap<
106
106
  * @internal
107
107
  */
108
108
  protected getCommitFee(): Promise<bigint> {
109
- return this.wrapper._contract.getCommitFee(this._getInitiator(), this.getSwapData(), this.feeRate);
109
+ return this._contract.getCommitFee(this._getInitiator(), this.getSwapData(), this.feeRate);
110
110
  }
111
111
 
112
112
  /**
113
113
  * Returns the transaction fee paid on the smart chain side to initiate the escrow
114
114
  */
115
115
  async getSmartChainNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>> {
116
- const swapContract: T["Contract"] = this.wrapper._contract;
116
+ const swapContract: T["Contract"] = this._contract;
117
117
  return toTokenAmount(
118
118
  await (
119
119
  swapContract.getRawCommitFee!=null ?
@@ -178,7 +178,7 @@ export abstract class IEscrowSelfInitSwap<
178
178
  async _verifyQuoteDefinitelyExpired(): Promise<boolean> {
179
179
  if(this._data==null || this.signatureData==null) throw new Error("data or signature data are null!");
180
180
 
181
- return this.wrapper._contract.isInitAuthorizationExpired(
181
+ return this._contract.isInitAuthorizationExpired(
182
182
  this._data!, this.signatureData!
183
183
  );
184
184
  }
@@ -190,7 +190,7 @@ export abstract class IEscrowSelfInitSwap<
190
190
  if(this._data==null || this.signatureData==null) throw new Error("data or signature data are null!");
191
191
 
192
192
  try {
193
- await this.wrapper._contract.isValidInitAuthorization(
193
+ await this._contract.isValidInitAuthorization(
194
194
  this._getInitiator(), this._data!, this.signatureData!, this.feeRate
195
195
  );
196
196
  return true;
@@ -50,6 +50,11 @@ export abstract class IEscrowSwap<
50
50
  */
51
51
  _claimTxId?: string;
52
52
 
53
+ /**
54
+ * @internal
55
+ */
56
+ protected _contract: T["Contract"];
57
+
53
58
  protected constructor(wrapper: D["Wrapper"], obj: any);
54
59
  protected constructor(wrapper: D["Wrapper"], swapInit: IEscrowSwapInit<T["Data"]>);
55
60
  protected constructor(
@@ -61,12 +66,14 @@ export abstract class IEscrowSwap<
61
66
  if(isIEscrowSwapInit(swapInitOrObj)) {
62
67
  this._data = swapInitOrObj.data;
63
68
  } else {
64
- if(swapInitOrObj.data!=null) this._data = new wrapper._swapDataDeserializer(swapInitOrObj.data);
69
+ if(swapInitOrObj.data!=null) this._data = new (wrapper._swapDataDeserializer(this._contractVersion))(swapInitOrObj.data);
65
70
 
66
71
  this._commitTxId = swapInitOrObj.commitTxId;
67
72
  this._claimTxId = swapInitOrObj.claimTxId;
68
73
  this._refundTxId = swapInitOrObj.refundTxId;
69
74
  }
75
+
76
+ this._contract = wrapper._contract(this._contractVersion);
70
77
  }
71
78
 
72
79
  /**
@@ -170,7 +177,7 @@ export abstract class IEscrowSwap<
170
177
  while(status?.type===SwapCommitStateType.NOT_COMMITED) {
171
178
  await timeoutPromise(intervalSeconds*1000, abortSignal);
172
179
  try {
173
- status = await this.wrapper._contract.getCommitStatus(this._getInitiator(), this._data);
180
+ status = await this._contract.getCommitStatus(this._getInitiator(), this._data);
174
181
  if(
175
182
  status?.type===SwapCommitStateType.NOT_COMMITED &&
176
183
  await this._verifyQuoteDefinitelyExpired()
@@ -200,7 +207,7 @@ export abstract class IEscrowSwap<
200
207
  while(status?.type===SwapCommitStateType.COMMITED || status?.type===SwapCommitStateType.REFUNDABLE) {
201
208
  await timeoutPromise(intervalSeconds*1000, abortSignal);
202
209
  try {
203
- status = await this.wrapper._contract.getCommitStatus(this._getInitiator(), this._data);
210
+ status = await this._contract.getCommitStatus(this._getInitiator(), this._data);
204
211
  } catch (e) {
205
212
  this.logger.error("watchdogWaitTillResult(): Error when fetching commit status: ", e);
206
213
  }