@atomiqlabs/chain-starknet 8.0.13 → 8.1.10

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 (119) hide show
  1. package/dist/index.d.ts +18 -18
  2. package/dist/index.js +42 -42
  3. package/dist/starknet/StarknetChainType.d.ts +19 -19
  4. package/dist/starknet/StarknetChainType.js +2 -2
  5. package/dist/starknet/StarknetInitializer.d.ts +66 -63
  6. package/dist/starknet/StarknetInitializer.js +101 -101
  7. package/dist/starknet/btcrelay/BtcRelayAbi.d.ts +250 -250
  8. package/dist/starknet/btcrelay/BtcRelayAbi.js +341 -341
  9. package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +196 -196
  10. package/dist/starknet/btcrelay/StarknetBtcRelay.js +419 -411
  11. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.d.ts +70 -70
  12. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.js +115 -115
  13. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.d.ts +91 -91
  14. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.js +155 -155
  15. package/dist/starknet/chain/StarknetAction.d.ts +19 -19
  16. package/dist/starknet/chain/StarknetAction.js +74 -74
  17. package/dist/starknet/chain/StarknetChainInterface.d.ts +142 -143
  18. package/dist/starknet/chain/StarknetChainInterface.js +198 -199
  19. package/dist/starknet/chain/StarknetModule.d.ts +8 -8
  20. package/dist/starknet/chain/StarknetModule.js +12 -12
  21. package/dist/starknet/chain/modules/ERC20Abi.d.ts +755 -755
  22. package/dist/starknet/chain/modules/ERC20Abi.js +1032 -1032
  23. package/dist/starknet/chain/modules/StarknetAccounts.d.ts +6 -6
  24. package/dist/starknet/chain/modules/StarknetAccounts.js +26 -26
  25. package/dist/starknet/chain/modules/StarknetAddresses.d.ts +10 -10
  26. package/dist/starknet/chain/modules/StarknetAddresses.js +27 -27
  27. package/dist/starknet/chain/modules/StarknetBlocks.d.ts +27 -27
  28. package/dist/starknet/chain/modules/StarknetBlocks.js +82 -82
  29. package/dist/starknet/chain/modules/StarknetEvents.d.ts +47 -47
  30. package/dist/starknet/chain/modules/StarknetEvents.js +90 -90
  31. package/dist/starknet/chain/modules/StarknetFees.d.ts +118 -104
  32. package/dist/starknet/chain/modules/StarknetFees.js +150 -146
  33. package/dist/starknet/chain/modules/StarknetSignatures.d.ts +29 -29
  34. package/dist/starknet/chain/modules/StarknetSignatures.js +72 -72
  35. package/dist/starknet/chain/modules/StarknetTokens.d.ts +66 -66
  36. package/dist/starknet/chain/modules/StarknetTokens.js +99 -99
  37. package/dist/starknet/chain/modules/StarknetTransactions.d.ts +122 -115
  38. package/dist/starknet/chain/modules/StarknetTransactions.js +633 -612
  39. package/dist/starknet/contract/StarknetContractBase.d.ts +14 -13
  40. package/dist/starknet/contract/StarknetContractBase.js +21 -20
  41. package/dist/starknet/contract/StarknetContractModule.d.ts +8 -8
  42. package/dist/starknet/contract/StarknetContractModule.js +11 -11
  43. package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +56 -57
  44. package/dist/starknet/contract/modules/StarknetContractEvents.js +111 -111
  45. package/dist/starknet/events/StarknetChainEvents.d.ts +21 -21
  46. package/dist/starknet/events/StarknetChainEvents.js +61 -61
  47. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +178 -190
  48. package/dist/starknet/events/StarknetChainEventsBrowser.js +523 -582
  49. package/dist/starknet/provider/RpcProviderWithRetries.d.ts +49 -53
  50. package/dist/starknet/provider/RpcProviderWithRetries.js +94 -94
  51. package/dist/starknet/provider/WebSocketChannelWithRetries.d.ts +21 -21
  52. package/dist/starknet/provider/WebSocketChannelWithRetries.js +46 -46
  53. package/dist/starknet/spv_swap/SpvVaultContractAbi.d.ts +488 -488
  54. package/dist/starknet/spv_swap/SpvVaultContractAbi.js +656 -656
  55. package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +225 -219
  56. package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +663 -621
  57. package/dist/starknet/spv_swap/StarknetSpvVaultData.d.ts +108 -108
  58. package/dist/starknet/spv_swap/StarknetSpvVaultData.js +190 -190
  59. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +56 -56
  60. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +103 -103
  61. package/dist/starknet/swaps/EscrowManagerAbi.d.ts +431 -431
  62. package/dist/starknet/swaps/EscrowManagerAbi.js +583 -583
  63. package/dist/starknet/swaps/StarknetSwapContract.d.ts +309 -278
  64. package/dist/starknet/swaps/StarknetSwapContract.js +755 -579
  65. package/dist/starknet/swaps/StarknetSwapData.d.ts +234 -234
  66. package/dist/starknet/swaps/StarknetSwapData.js +474 -474
  67. package/dist/starknet/swaps/StarknetSwapModule.d.ts +10 -10
  68. package/dist/starknet/swaps/StarknetSwapModule.js +12 -12
  69. package/dist/starknet/swaps/handlers/IHandler.d.ts +13 -13
  70. package/dist/starknet/swaps/handlers/IHandler.js +2 -2
  71. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +13 -13
  72. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.js +13 -13
  73. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +21 -21
  74. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.js +44 -44
  75. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +24 -24
  76. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.js +48 -48
  77. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +25 -25
  78. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.js +40 -40
  79. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +20 -20
  80. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.js +30 -30
  81. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +42 -45
  82. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +50 -54
  83. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +17 -17
  84. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.js +27 -27
  85. package/dist/starknet/swaps/modules/StarknetLpVault.d.ts +67 -67
  86. package/dist/starknet/swaps/modules/StarknetLpVault.js +122 -122
  87. package/dist/starknet/swaps/modules/StarknetSwapClaim.d.ts +52 -52
  88. package/dist/starknet/swaps/modules/StarknetSwapClaim.js +99 -99
  89. package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +94 -94
  90. package/dist/starknet/swaps/modules/StarknetSwapInit.js +239 -239
  91. package/dist/starknet/swaps/modules/StarknetSwapRefund.d.ts +60 -60
  92. package/dist/starknet/swaps/modules/StarknetSwapRefund.js +126 -126
  93. package/dist/starknet/wallet/StarknetBrowserSigner.d.ts +11 -11
  94. package/dist/starknet/wallet/StarknetBrowserSigner.js +17 -17
  95. package/dist/starknet/wallet/StarknetPersistentSigner.d.ts +76 -76
  96. package/dist/starknet/wallet/StarknetPersistentSigner.js +291 -291
  97. package/dist/starknet/wallet/StarknetSigner.d.ts +72 -72
  98. package/dist/starknet/wallet/StarknetSigner.js +114 -114
  99. package/dist/starknet/wallet/accounts/StarknetKeypairWallet.d.ts +18 -18
  100. package/dist/starknet/wallet/accounts/StarknetKeypairWallet.js +45 -45
  101. package/dist/utils/Utils.d.ts +77 -77
  102. package/dist/utils/Utils.js +304 -303
  103. package/package.json +2 -2
  104. package/src/starknet/StarknetInitializer.ts +6 -3
  105. package/src/starknet/btcrelay/StarknetBtcRelay.ts +19 -6
  106. package/src/starknet/btcrelay/headers/StarknetBtcHeader.ts +7 -7
  107. package/src/starknet/btcrelay/headers/StarknetBtcStoredHeader.ts +6 -6
  108. package/src/starknet/chain/StarknetAction.ts +1 -0
  109. package/src/starknet/chain/StarknetChainInterface.ts +0 -2
  110. package/src/starknet/chain/modules/StarknetFees.ts +15 -2
  111. package/src/starknet/chain/modules/StarknetTransactions.ts +24 -0
  112. package/src/starknet/contract/StarknetContractBase.ts +7 -4
  113. package/src/starknet/contract/StarknetContractModule.ts +1 -1
  114. package/src/starknet/contract/modules/StarknetContractEvents.ts +7 -7
  115. package/src/starknet/events/StarknetChainEventsBrowser.ts +2 -64
  116. package/src/starknet/provider/RpcProviderWithRetries.ts +1 -1
  117. package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +84 -18
  118. package/src/starknet/swaps/StarknetSwapContract.ts +242 -6
  119. package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +0 -4
@@ -71,8 +71,11 @@ export type StarknetOptions = {
71
71
  chainId?: constants.StarknetChainId,
72
72
 
73
73
  swapContract?: string,
74
+ swapContractDeploymentHeight?: number,
74
75
  btcRelayContract?: string,
76
+ btcRelayContractDeploymentHeight?: number,
75
77
  spvVaultContract?: string,
78
+ spvVaultContractDeploymentHeight?: number,
76
79
  handlerContracts?: {
77
80
  refund?: {
78
81
  timelock?: string
@@ -113,15 +116,15 @@ export function initializeStarknet(
113
116
  const chainInterface = new StarknetChainInterface(chainId, provider, wsChannel, Fees, options.starknetConfig);
114
117
 
115
118
  const btcRelay = new StarknetBtcRelay(
116
- chainInterface, bitcoinRpc, network, options.btcRelayContract
119
+ chainInterface, bitcoinRpc, network, options.btcRelayContract, options.btcRelayContractDeploymentHeight
117
120
  );
118
121
 
119
122
  const swapContract = new StarknetSwapContract(
120
- chainInterface, btcRelay, options.swapContract, options.handlerContracts
123
+ chainInterface, btcRelay, options.swapContract, options.handlerContracts, options.swapContractDeploymentHeight
121
124
  );
122
125
 
123
126
  const spvVaultContract = new StarknetSpvVaultContract(
124
- chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract
127
+ chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract, options.spvVaultContractDeploymentHeight
125
128
  )
126
129
 
127
130
  const chainEvents = new StarknetChainEventsBrowser(chainInterface, swapContract, spvVaultContract);
@@ -11,7 +11,7 @@ import {StarknetBtcStoredHeader} from "./headers/StarknetBtcStoredHeader";
11
11
  import {StarknetTx} from "../chain/modules/StarknetTransactions";
12
12
  import {StarknetSigner} from "../wallet/StarknetSigner";
13
13
  import {BtcRelayAbi} from "./BtcRelayAbi";
14
- import {BigNumberish, hash} from "starknet";
14
+ import {BigNumberish, constants, hash} from "starknet";
15
15
  import {StarknetFees, starknetGasAdd, starknetGasMul} from "../chain/modules/StarknetFees";
16
16
  import {StarknetChainInterface} from "../chain/StarknetChainInterface";
17
17
  import {StarknetAction} from "../chain/StarknetAction";
@@ -37,6 +37,12 @@ const btcRelayAddreses: {[network in BitcoinNetwork]?: string} = {
37
37
  [BitcoinNetwork.MAINNET]: "0x057b14a4231b82f1e525ff35a722d893ca3dd2bde0baa6cee97937c5be861dbc"
38
38
  };
39
39
 
40
+ const btcRelayDeploymentHeights: {[network in BitcoinNetwork]?: number} = {
41
+ [BitcoinNetwork.TESTNET4]: 760719,
42
+ [BitcoinNetwork.TESTNET]: 633915,
43
+ [BitcoinNetwork.MAINNET]: 1278562
44
+ };
45
+
40
46
  function serializeCalldata(headers: StarknetBtcHeader[], storedHeader: StarknetBtcStoredHeader, span: BigNumberish[]) {
41
47
  span.push(toHex(headers.length));
42
48
  headers.forEach(header => {
@@ -131,9 +137,16 @@ export class StarknetBtcRelay<B extends BtcBlock>
131
137
  bitcoinRpc: BitcoinRpc<B>,
132
138
  bitcoinNetwork: BitcoinNetwork,
133
139
  contractAddress: string | undefined = btcRelayAddreses[bitcoinNetwork],
140
+ contractDeploymentHeight?: number
134
141
  ) {
135
142
  if(contractAddress==null) throw new Error("No BtcRelay address specified!");
136
- super(chainInterface, contractAddress, BtcRelayAbi);
143
+ super(
144
+ chainInterface, contractAddress, BtcRelayAbi,
145
+ contractDeploymentHeight ??
146
+ (btcRelayAddreses[bitcoinNetwork]===contractAddress
147
+ ? btcRelayDeploymentHeights[bitcoinNetwork]
148
+ : undefined)
149
+ );
137
150
  this.bitcoinRpc = bitcoinRpc;
138
151
  }
139
152
 
@@ -266,7 +279,7 @@ export class StarknetBtcRelay<B extends BtcBlock>
266
279
  const [storedBlockHeader, commitHash] = result;
267
280
 
268
281
  //Check if block is part of the main chain
269
- const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.block_height);
282
+ const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.getBlockheight());
270
283
  if(BigInt(chainCommitment)!==BigInt(commitHash)) return null;
271
284
 
272
285
  logger.debug("retrieveLogAndBlockheight(): block found," +
@@ -285,11 +298,11 @@ export class StarknetBtcRelay<B extends BtcBlock>
285
298
  const [storedBlockHeader, commitHash] = result;
286
299
 
287
300
  //Check if block is part of the main chain
288
- const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.block_height);
301
+ const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.getBlockheight());
289
302
  if(BigInt(chainCommitment)!==BigInt(commitHash)) return null;
290
303
 
291
304
  logger.debug("retrieveLogByCommitHash(): block found," +
292
- " commit hash: "+commitmentHash+" blockhash: "+blockData.blockhash+" height: "+storedBlockHeader.block_height);
305
+ " commit hash: "+commitmentHash+" blockhash: "+blockData.blockhash+" height: "+storedBlockHeader.getBlockheight());
293
306
 
294
307
  return storedBlockHeader;
295
308
  }
@@ -312,7 +325,7 @@ export class StarknetBtcRelay<B extends BtcBlock>
312
325
 
313
326
  const [isInBtcMainChain, btcRelayCommitHash] = await Promise.all([
314
327
  this.bitcoinRpc.isInMainChain(blockHashHex).catch(() => false),
315
- this.contract.get_commit_hash(storedHeader.block_height)
328
+ this.contract.get_commit_hash(storedHeader.getBlockheight())
316
329
  ]);
317
330
 
318
331
  if(!isInBtcMainChain) return null;
@@ -21,13 +21,13 @@ export type StarknetBtcHeaderType = {
21
21
  */
22
22
  export class StarknetBtcHeader implements BtcHeader {
23
23
 
24
- reversed_version: number;
25
- previous_blockhash: number[];
26
- merkle_root: number[];
27
- reversed_timestamp: number;
28
- nbits: number;
29
- nonce: number;
30
- hash?: Buffer;
24
+ private readonly reversed_version: number;
25
+ private readonly previous_blockhash: number[];
26
+ private readonly merkle_root: number[];
27
+ private readonly reversed_timestamp: number;
28
+ private readonly nbits: number;
29
+ private readonly nonce: number;
30
+ private readonly hash?: Buffer;
31
31
 
32
32
  /**
33
33
  * Constructs the bitcoin blockheader from a struct as returned by the starknet.js lib
@@ -21,12 +21,12 @@ export type StarknetBtcStoredHeaderType = {
21
21
  */
22
22
  export class StarknetBtcStoredHeader implements BtcStoredHeader<StarknetBtcHeader> {
23
23
 
24
- blockheader: StarknetBtcHeader;
25
- block_hash: number[];
26
- chain_work: Uint256;
27
- block_height: number;
28
- last_diff_adjustment: number;
29
- prev_block_timestamps: number[];
24
+ private readonly blockheader: StarknetBtcHeader;
25
+ private readonly block_hash: number[];
26
+ private readonly chain_work: Uint256;
27
+ private readonly block_height: number;
28
+ private readonly last_diff_adjustment: number;
29
+ private readonly prev_block_timestamps: number[];
30
30
 
31
31
  /**
32
32
  * Constructs the bitcoin stored blockheader from a struct as returned by the starknet.js lib
@@ -7,6 +7,7 @@ export class StarknetAction {
7
7
 
8
8
  gas: StarknetGas;
9
9
  readonly mainSigner: string;
10
+
10
11
  private readonly root: StarknetChainInterface;
11
12
  private readonly instructions: Call[];
12
13
  private feeRate?: string;
@@ -54,8 +54,6 @@ export class StarknetChainInterface implements ChainInterface<StarknetTx, Signed
54
54
  public readonly Accounts: StarknetAccounts;
55
55
  public readonly Blocks: StarknetBlocks;
56
56
 
57
- protected readonly logger = getLogger("StarknetChainInterface: ");
58
-
59
57
  public readonly config: StarknetConfig;
60
58
 
61
59
  constructor(
@@ -1,15 +1,24 @@
1
- import {getLogger, toBigInt, toHex} from "../../../utils/Utils";
1
+ import {getLogger, toBigInt} from "../../../utils/Utils";
2
2
  import {Provider} from "starknet";
3
- import {StarknetTokens} from "./StarknetTokens";
4
3
 
5
4
  const MAX_FEE_AGE = 5000;
6
5
 
6
+ /**
7
+ * Representation of a starknet feerate including costs for different units of gas
8
+ *
9
+ * @category Chain Interface
10
+ */
7
11
  export type StarknetFeeRate = {
8
12
  l1GasCost: bigint;
9
13
  l2GasCost: bigint;
10
14
  l1DataGasCost: bigint;
11
15
  };
12
16
 
17
+ /**
18
+ * Representation of the starknet transaction gas limits used to create resource bounds and estimate fees
19
+ *
20
+ * @category Chain Interface
21
+ */
13
22
  export type StarknetGas = {
14
23
  l1Gas: number,
15
24
  l2Gas: number,
@@ -21,6 +30,8 @@ export type StarknetGas = {
21
30
  *
22
31
  * @param gas
23
32
  * @param scalar
33
+ *
34
+ * @category Chain Interface
24
35
  */
25
36
  export function starknetGasMul(gas: StarknetGas, scalar: number): StarknetGas {
26
37
  return {l1Gas: gas.l1Gas * scalar, l2Gas: gas.l2Gas * scalar, l1DataGas: gas.l1DataGas * scalar};
@@ -31,6 +42,8 @@ export function starknetGasMul(gas: StarknetGas, scalar: number): StarknetGas {
31
42
  *
32
43
  * @param a
33
44
  * @param b
45
+ *
46
+ * @category Chain Interface
34
47
  */
35
48
  export function starknetGasAdd(a: StarknetGas, b?: StarknetGas): StarknetGas {
36
49
  if(b==null) return a;
@@ -65,6 +65,13 @@ export function isStarknetTxDeployAccount(obj: any): obj is StarknetTxDeployAcco
65
65
  export type StarknetTx = StarknetTxInvoke | StarknetTxDeployAccount;
66
66
  export type SignedStarknetTx = StarknetTx;
67
67
 
68
+ export type StarknetTraceCall = {
69
+ calldata: string[],
70
+ contract_address: string,
71
+ entry_point_selector: string,
72
+ calls: StarknetTraceCall[]
73
+ };
74
+
68
75
  const MAX_UNCONFIRMED_TXS = 25;
69
76
 
70
77
  export class StarknetTransactions extends StarknetModule {
@@ -657,6 +664,23 @@ export class StarknetTransactions extends StarknetModule {
657
664
  return status;
658
665
  }
659
666
 
667
+ async traceTransaction(txId: string, blockHash?: string): Promise<StarknetTraceCall | null> {
668
+ let trace: any;
669
+ try {
670
+ trace = await this.provider.getTransactionTrace(txId);
671
+ } catch (e) {
672
+ this.logger.warn("getSwapDataGetter(): getter: starknet_traceTransaction not supported by the RPC: ", e);
673
+ if(blockHash==null) throw e;
674
+ const blockTraces: any[] = await this.provider.getBlockTransactionsTraces(blockHash);
675
+ const foundTrace = blockTraces.find(val => toHex(val.transaction_hash)===toHex(txId));
676
+ if(foundTrace==null) throw new Error(`Cannot find ${txId} in the block traces, block: ${blockHash}`);
677
+ trace = foundTrace.trace_root;
678
+ }
679
+ if(trace==null) return null;
680
+ if(trace.execute_invocation.revert_reason!=null) return null;
681
+ return trace.execute_invocation;
682
+ }
683
+
660
684
  onBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): void {
661
685
  this._cbksBeforeTxReplace.push(callback);
662
686
  }
@@ -8,15 +8,17 @@ import {StarknetContractEvents} from "./modules/StarknetContractEvents";
8
8
  */
9
9
  export class StarknetContractBase<T extends Abi> {
10
10
 
11
- contract: TypedContractV2<T>;
11
+ readonly contract: TypedContractV2<T>;
12
12
 
13
- public readonly Events: StarknetContractEvents<T>;
14
- public readonly Chain: StarknetChainInterface;
13
+ readonly Events: StarknetContractEvents<T>;
14
+ readonly Chain: StarknetChainInterface;
15
+ readonly contractDeploymentHeight?: number;
15
16
 
16
17
  constructor(
17
18
  chainInterface: StarknetChainInterface,
18
19
  contractAddress: string,
19
- contractAbi: T
20
+ contractAbi: T,
21
+ contractDeploymentHeight?: number
20
22
  ) {
21
23
  this.Chain = chainInterface;
22
24
  this.contract = new Contract({
@@ -25,6 +27,7 @@ export class StarknetContractBase<T extends Abi> {
25
27
  providerOrAccount: chainInterface.provider
26
28
  }).typedv2(contractAbi);
27
29
  this.Events = new StarknetContractEvents(chainInterface, this, contractAbi);
30
+ this.contractDeploymentHeight = contractDeploymentHeight;
28
31
  }
29
32
 
30
33
  }
@@ -6,7 +6,7 @@ import {StarknetModule} from "../chain/StarknetModule";
6
6
 
7
7
  export class StarknetContractModule<TAbi extends Abi> extends StarknetModule {
8
8
 
9
- readonly contract: StarknetContractBase<TAbi>;
9
+ protected readonly contract: StarknetContractBase<TAbi>;
10
10
 
11
11
  constructor(chainInterface: StarknetChainInterface, contract: StarknetContractBase<TAbi>) {
12
12
  super(chainInterface)
@@ -18,12 +18,12 @@ export type StarknetAbiEvent<TAbi extends Abi, TEventName extends ExtractAbiEven
18
18
 
19
19
  export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
20
20
 
21
- readonly contract: StarknetContractBase<TAbi>;
22
- readonly abi: TAbi;
23
- readonly knownEventNames: string[];
24
- readonly abiEvents: AbiEvents;
25
- readonly abiStructs: AbiStructs;
26
- readonly abiEnums: AbiEnums;
21
+ private readonly contract: StarknetContractBase<TAbi>;
22
+ private readonly abi: TAbi;
23
+ private readonly knownEventNames: string[];
24
+ private readonly abiEvents: AbiEvents;
25
+ private readonly abiStructs: AbiStructs;
26
+ private readonly abiEnums: AbiEnums;
27
27
 
28
28
  constructor(chainInterface: StarknetChainInterface, contract: StarknetContractBase<TAbi>, abi: TAbi) {
29
29
  super(chainInterface);
@@ -148,7 +148,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
148
148
  if(result!=null) return result;
149
149
  }
150
150
  return null;
151
- }, startHeight, abortSignal);
151
+ }, Math.max(startHeight ?? 0, this.contract.contractDeploymentHeight ?? 0), abortSignal);
152
152
  }
153
153
 
154
154
  }
@@ -39,13 +39,6 @@ import {Buffer} from "buffer";
39
39
  const PROCESSED_EVENTS_BACKLOG = 5000;
40
40
  const LOGS_SLIDING_WINDOW = 60;
41
41
 
42
- type StarknetTraceCall = {
43
- calldata: string[],
44
- contract_address: string,
45
- entry_point_selector: string,
46
- calls: StarknetTraceCall[]
47
- };
48
-
49
42
  /**
50
43
  * Current state of the starknet event listener, contains the last processed
51
44
  * block number and transaction hash of the last processed event
@@ -57,20 +50,6 @@ export type StarknetEventListenerState = {
57
50
  lastTxHash?: string
58
51
  };
59
52
 
60
- function parseInitFunctionCalldata(calldata: BigNumberish[], claimHandler: IClaimHandler<any, any>): {escrow: StarknetSwapData, signature: BigNumberish[], timeout: bigint, extraData: BigNumberish[]} {
61
- const escrow = StarknetSwapData.fromSerializedFeltArray(calldata, claimHandler);
62
- if(calldata.length < 1) throw new Error("Calldata invalid length");
63
- const signatureLen = Number(toBigInt(calldata.shift()!));
64
- if(calldata.length < signatureLen + 2) throw new Error("Calldata invalid length");
65
- const signature = calldata.splice(0, signatureLen);
66
- const timeout = toBigInt(calldata.shift()!);
67
- const extraDataLen = Number(toBigInt(calldata.shift()!));
68
- if(calldata.length < extraDataLen) throw new Error("Calldata invalid length");
69
- const extraData = calldata.splice(0, extraDataLen);
70
- if(calldata.length!==0) throw new Error("Calldata not read fully!");
71
- return {escrow, signature, timeout, extraData};
72
- }
73
-
74
53
  /**
75
54
  * Starknet on-chain event handler for front-end systems without access to fs, uses WS or long-polling to subscribe, might lose
76
55
  * out on some events if the network is unreliable, front-end systems should take this into consideration and not
@@ -96,9 +75,6 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
96
75
  protected escrowContractSubscription?: SubscriptionStarknetEventsEvent;
97
76
  protected spvVaultContractSubscription?: SubscriptionStarknetEventsEvent;
98
77
 
99
- protected initFunctionName: ExtractAbiFunctionNames<EscrowManagerAbiType> = "initialize";
100
- protected initEntryPointSelector = BigInt(hash.starknetKeccak(this.initFunctionName));
101
-
102
78
  protected stopped: boolean = true;
103
79
  protected pollIntervalSeconds: number;
104
80
 
@@ -153,34 +129,6 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
153
129
  return this.processedEvents.has(eventFingerprint);
154
130
  }
155
131
 
156
- /**
157
- *
158
- * @param call
159
- * @param escrowHash
160
- * @param claimHandler
161
- * @private
162
- */
163
- private findInitSwapData(call: StarknetTraceCall, escrowHash: BigNumberish, claimHandler: IClaimHandler<any, any>): StarknetSwapData | null {
164
- if(
165
- BigInt(call.contract_address)===BigInt(this.starknetSwapContract.contract.address) &&
166
- BigInt(call.entry_point_selector)===this.initEntryPointSelector
167
- ) {
168
- //Found, check correct escrow hash
169
- const {escrow, extraData} = parseInitFunctionCalldata(call.calldata, claimHandler);
170
- if("0x"+escrow.getEscrowHash()===toHex(escrowHash)) {
171
- if(extraData.length!==0) {
172
- escrow.setExtraData(bytes31SpanToBuffer(extraData, 42).toString("hex"));
173
- }
174
- return escrow;
175
- }
176
- }
177
- for(let _call of call.calls) {
178
- const found = this.findInitSwapData(_call, escrowHash, claimHandler);
179
- if(found!=null) return found;
180
- }
181
- return null;
182
- }
183
-
184
132
  /**
185
133
  * Returns async getter for fetching on-demand initialize event swap data
186
134
  *
@@ -194,19 +142,9 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
194
142
  claimHandler: IClaimHandler<any, any>
195
143
  ): () => Promise<StarknetSwapData | null> {
196
144
  return async () => {
197
- let trace: any;
198
- try {
199
- trace = await this.provider.getTransactionTrace(event.txHash);
200
- } catch (e) {
201
- this.logger.warn("getSwapDataGetter(): getter: starknet_traceTransaction not supported by the RPC: ", e);
202
- const blockTraces: any[] = await this.provider.getBlockTransactionsTraces(event.blockHash);
203
- const foundTrace = blockTraces.find(val => toHex(val.transaction_hash)===toHex(event.txHash));
204
- if(foundTrace==null) throw new Error(`Cannot find ${event.txHash} in the block traces, block: ${event.blockHash}`);
205
- trace = foundTrace.trace_root;
206
- }
145
+ const trace = await this.Chain.Transactions.traceTransaction(event.txHash, event.blockHash);
207
146
  if(trace==null) return null;
208
- if(trace.execute_invocation.revert_reason!=null) return null;
209
- return this.findInitSwapData(trace.execute_invocation as any, event.params.escrow_hash, claimHandler);
147
+ return this.starknetSwapContract.findInitSwapData(trace, event.params.escrow_hash, claimHandler);
210
148
  }
211
149
  }
212
150
 
@@ -10,7 +10,7 @@ import {tryWithRetries} from "../../utils/Utils";
10
10
  */
11
11
  export class Rpc09ChannelWithRetries extends RPC09.RpcChannel {
12
12
 
13
- readonly retryPolicy?: {
13
+ private readonly retryPolicy?: {
14
14
  maxRetries?: number, delay?: number, exponential?: boolean
15
15
  };
16
16
 
@@ -3,7 +3,7 @@ import {
3
3
  BtcTx,
4
4
  RelaySynchronizer,
5
5
  SpvVaultContract,
6
- SpvVaultTokenData,
6
+ SpvVaultTokenData, SpvWithdrawalClaimedState, SpvWithdrawalClosedState, SpvWithdrawalFrontedState,
7
7
  SpvWithdrawalState,
8
8
  SpvWithdrawalStateType,
9
9
  SpvWithdrawalTransactionData,
@@ -31,6 +31,11 @@ const spvVaultContractAddreses = {
31
31
  [constants.StarknetChainId.SN_MAIN]: "0x01932042992647771f3d0aa6ee526e65359c891fe05a285faaf4d3ffa373e132"
32
32
  };
33
33
 
34
+ const spvVaultContractDeploymentHeights = {
35
+ [constants.StarknetChainId.SN_SEPOLIA]: 1118191,
36
+ [constants.StarknetChainId.SN_MAIN]: 1617295
37
+ };
38
+
34
39
  const STARK_PRIME_MOD: bigint = 2n**251n + 17n * 2n**192n + 1n;
35
40
 
36
41
  function decodeUtxo(utxo: string): {txHash: bigint, vout: bigint} {
@@ -66,20 +71,27 @@ export class StarknetSpvVaultContract
66
71
 
67
72
  readonly chainId = "STARKNET";
68
73
 
69
- readonly btcRelay: StarknetBtcRelay<any>;
70
- readonly bitcoinRpc: BitcoinRpc<any>;
71
74
  readonly claimTimeout: number = 180;
72
75
  readonly maxClaimsPerTx: number = 10;
73
76
 
74
- readonly logger = getLogger("StarknetSpvVaultContract: ");
77
+ private readonly btcRelay: StarknetBtcRelay<any>;
78
+ private readonly bitcoinRpc: BitcoinRpc<any>;
79
+ private readonly logger = getLogger("StarknetSpvVaultContract: ");
75
80
 
76
81
  constructor(
77
82
  chainInterface: StarknetChainInterface,
78
83
  btcRelay: StarknetBtcRelay<any>,
79
84
  bitcoinRpc: BitcoinRpc<any>,
80
- contractAddress: string = spvVaultContractAddreses[chainInterface.starknetChainId]
85
+ contractAddress: string = spvVaultContractAddreses[chainInterface.starknetChainId],
86
+ contractDeploymentHeight?: number
81
87
  ) {
82
- super(chainInterface, contractAddress, SpvVaultContractAbi);
88
+ super(
89
+ chainInterface, contractAddress, SpvVaultContractAbi,
90
+ contractDeploymentHeight ??
91
+ (spvVaultContractAddreses[chainInterface.starknetChainId]===contractAddress
92
+ ? spvVaultContractDeploymentHeights[chainInterface.starknetChainId]
93
+ : undefined)
94
+ );
83
95
  this.btcRelay = btcRelay;
84
96
  this.bitcoinRpc = bitcoinRpc;
85
97
  }
@@ -280,7 +292,7 @@ export class StarknetSpvVaultContract
280
292
  const openedVaults = new Set<string>();
281
293
  await this.Events.findInContractEventsForward(
282
294
  ["spv_swap_vault::events::Opened", "spv_swap_vault::events::Closed"],
283
- owner==null ? null : [null, owner],
295
+ owner==null ? null : [null, null, owner],
284
296
  (event) => {
285
297
  const owner = toHex(event.params.owner);
286
298
  const vaultId = toBigInt(event.params.vault_id);
@@ -293,12 +305,20 @@ export class StarknetSpvVaultContract
293
305
  return Promise.resolve(null);
294
306
  }
295
307
  );
296
- const vaults: StarknetSpvVaultData[] = [];
297
- for(let identifier of openedVaults.keys()) {
308
+
309
+ const fetchedVaultData = await this.getMultipleVaultData([...openedVaults.keys()].map(identifier => {
298
310
  const [owner, vaultIdStr] = identifier.split(":");
299
- const vaultData = await this.getVaultData(owner, BigInt(vaultIdStr));
300
- if(vaultData!=null) vaults.push(vaultData);
311
+ return {owner, vaultId: BigInt(vaultIdStr)}
312
+ }));
313
+
314
+ const vaults: StarknetSpvVaultData[] = [];
315
+ for(let owner in fetchedVaultData) {
316
+ for(let vaultIdStr in fetchedVaultData[owner]) {
317
+ const vault = fetchedVaultData[owner][vaultIdStr];
318
+ if(vault!=null) vaults.push(vault);
319
+ }
301
320
  }
321
+
302
322
  return vaults;
303
323
  }
304
324
 
@@ -338,34 +358,53 @@ export class StarknetSpvVaultContract
338
358
  * @param event
339
359
  * @private
340
360
  */
341
- private parseWithdrawalEvent(event: StarknetAbiEvent<typeof SpvVaultContractAbi, "spv_swap_vault::events::Claimed" | "spv_swap_vault::events::Fronted" | "spv_swap_vault::events::Closed">): SpvWithdrawalState | null {
361
+ private parseWithdrawalEvent(
362
+ event: StarknetAbiEvent<typeof SpvVaultContractAbi, "spv_swap_vault::events::Fronted"> |
363
+ StarknetAbiEvent<typeof SpvVaultContractAbi, "spv_swap_vault::events::Claimed"> |
364
+ StarknetAbiEvent<typeof SpvVaultContractAbi, "spv_swap_vault::events::Closed">
365
+ ): ((SpvWithdrawalFrontedState | SpvWithdrawalClaimedState | SpvWithdrawalClosedState) & {btcTxId: string}) | null {
342
366
  switch(event.name) {
343
367
  case "spv_swap_vault::events::Fronted":
344
368
  return {
345
369
  type: SpvWithdrawalStateType.FRONTED,
346
- txId: event.txHash,
370
+ btcTxId: bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex"),
347
371
  owner: toHex(event.params.owner),
348
372
  vaultId: toBigInt(event.params.vault_id),
349
373
  recipient: toHex(event.params.recipient),
350
- fronter: toHex(event.params.fronting_address)
374
+ fronter: toHex(event.params.caller),
375
+ txId: event.txHash,
376
+ getTxBlock: async() => ({
377
+ blockHeight: event.blockNumber!,
378
+ blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber!)
379
+ })
351
380
  };
352
381
  case "spv_swap_vault::events::Claimed":
353
382
  return {
354
383
  type: SpvWithdrawalStateType.CLAIMED,
355
- txId: event.txHash,
384
+ btcTxId: bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex"),
356
385
  owner: toHex(event.params.owner),
357
386
  vaultId: toBigInt(event.params.vault_id),
358
387
  recipient: toHex(event.params.recipient),
359
388
  claimer: toHex(event.params.caller),
360
- fronter: toHex(event.params.fronting_address)
389
+ fronter: toHex(event.params.fronting_address),
390
+ txId: event.txHash,
391
+ getTxBlock: async() => ({
392
+ blockHeight: event.blockNumber!,
393
+ blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber!)
394
+ })
361
395
  };
362
396
  case "spv_swap_vault::events::Closed":
363
397
  return {
364
398
  type: SpvWithdrawalStateType.CLOSED,
365
- txId: event.txHash,
399
+ btcTxId: bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex"),
366
400
  owner: toHex(event.params.owner),
367
401
  vaultId: toBigInt(event.params.vault_id),
368
- error: bigNumberishToBuffer(event.params.error).toString()
402
+ error: bigNumberishToBuffer(event.params.error).toString(),
403
+ txId: event.txHash,
404
+ getTxBlock: async() => ({
405
+ blockHeight: event.blockNumber!,
406
+ blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber!)
407
+ })
369
408
  };
370
409
  default:
371
410
  return null;
@@ -447,6 +486,33 @@ export class StarknetSpvVaultContract
447
486
  return result;
448
487
  }
449
488
 
489
+ async getHistoricalWithdrawalStates(recipient: string, startBlockheight?: number): Promise<{
490
+ withdrawals: { [btcTxId: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState };
491
+ latestBlockheight?: number
492
+ }> {
493
+ const {height: latestBlockheight} = await this.Chain.getFinalizedBlock();
494
+ const withdrawals: { [btcTxId: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState } = {};
495
+
496
+ const eventTypes: ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"] =
497
+ ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"];
498
+
499
+ await this.Events.findInContractEventsForward(
500
+ eventTypes,
501
+ [null, null, null, null, recipient],
502
+ async (_event) => {
503
+ const eventResult = this.parseWithdrawalEvent(_event);
504
+ if(eventResult==null || eventResult.type===SpvWithdrawalStateType.CLOSED) return null;
505
+ withdrawals[eventResult.btcTxId] = eventResult;
506
+ },
507
+ startBlockheight
508
+ );
509
+
510
+ return {
511
+ withdrawals,
512
+ latestBlockheight
513
+ }
514
+ }
515
+
450
516
  /**
451
517
  * @inheritDoc
452
518
  */