@atomiqlabs/chain-starknet 1.0.9 → 2.0.0-beta.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 (121) hide show
  1. package/dist/index.d.ts +13 -9
  2. package/dist/index.js +13 -9
  3. package/dist/starknet/StarknetChainType.d.ts +6 -2
  4. package/dist/starknet/StarknetInitializer.d.ts +3 -2
  5. package/dist/starknet/StarknetInitializer.js +17 -6
  6. package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +28 -7
  7. package/dist/starknet/btcrelay/StarknetBtcRelay.js +75 -20
  8. package/dist/starknet/{base → chain}/StarknetAction.d.ts +2 -2
  9. package/dist/starknet/chain/StarknetChainInterface.d.ts +52 -0
  10. package/dist/starknet/chain/StarknetChainInterface.js +91 -0
  11. package/dist/starknet/{base → chain}/StarknetModule.d.ts +3 -3
  12. package/dist/starknet/{base → chain}/modules/StarknetAddresses.d.ts +1 -1
  13. package/dist/starknet/{base → chain}/modules/StarknetAddresses.js +1 -1
  14. package/dist/starknet/{base → chain}/modules/StarknetSignatures.d.ts +2 -2
  15. package/dist/starknet/{base → chain}/modules/StarknetTokens.js +2 -1
  16. package/dist/starknet/{base → chain}/modules/StarknetTransactions.d.ts +7 -1
  17. package/dist/starknet/{base → chain}/modules/StarknetTransactions.js +45 -16
  18. package/dist/starknet/contract/StarknetContractBase.d.ts +5 -5
  19. package/dist/starknet/contract/StarknetContractBase.js +5 -7
  20. package/dist/starknet/contract/StarknetContractModule.d.ts +8 -0
  21. package/dist/starknet/contract/StarknetContractModule.js +11 -0
  22. package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +15 -4
  23. package/dist/starknet/contract/modules/StarknetContractEvents.js +26 -6
  24. package/dist/starknet/events/StarknetChainEvents.d.ts +3 -1
  25. package/dist/starknet/events/StarknetChainEvents.js +9 -9
  26. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +23 -6
  27. package/dist/starknet/events/StarknetChainEventsBrowser.js +104 -13
  28. package/dist/starknet/provider/RpcProviderWithRetries.d.ts +21 -0
  29. package/dist/starknet/provider/RpcProviderWithRetries.js +32 -0
  30. package/dist/starknet/spv_swap/SpvVaultContractAbi.d.ts +488 -0
  31. package/dist/starknet/spv_swap/SpvVaultContractAbi.js +656 -0
  32. package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +65 -0
  33. package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +372 -0
  34. package/dist/starknet/spv_swap/StarknetSpvVaultData.d.ts +49 -0
  35. package/dist/starknet/spv_swap/StarknetSpvVaultData.js +144 -0
  36. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +24 -0
  37. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +61 -0
  38. package/dist/starknet/swaps/StarknetSwapContract.d.ts +4 -22
  39. package/dist/starknet/swaps/StarknetSwapContract.js +23 -80
  40. package/dist/starknet/swaps/StarknetSwapModule.d.ts +6 -5
  41. package/dist/starknet/swaps/StarknetSwapModule.js +5 -6
  42. package/dist/starknet/swaps/handlers/IHandler.d.ts +2 -2
  43. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +1 -1
  44. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +2 -2
  45. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +2 -2
  46. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +2 -2
  47. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +2 -2
  48. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +2 -21
  49. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +7 -41
  50. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +2 -2
  51. package/dist/starknet/swaps/modules/StarknetLpVault.d.ts +1 -1
  52. package/dist/starknet/swaps/modules/StarknetLpVault.js +9 -9
  53. package/dist/starknet/swaps/modules/StarknetSwapClaim.d.ts +1 -1
  54. package/dist/starknet/swaps/modules/StarknetSwapClaim.js +8 -8
  55. package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +1 -1
  56. package/dist/starknet/swaps/modules/StarknetSwapInit.js +9 -9
  57. package/dist/starknet/swaps/modules/StarknetSwapRefund.d.ts +1 -3
  58. package/dist/starknet/swaps/modules/StarknetSwapRefund.js +8 -11
  59. package/dist/starknet/wallet/StarknetSigner.js +1 -1
  60. package/dist/utils/Utils.d.ts +2 -2
  61. package/dist/utils/Utils.js +3 -1
  62. package/package.json +2 -2
  63. package/src/index.ts +15 -9
  64. package/src/starknet/StarknetChainType.ts +10 -2
  65. package/src/starknet/StarknetInitializer.ts +23 -7
  66. package/src/starknet/btcrelay/StarknetBtcRelay.ts +104 -30
  67. package/src/starknet/{base → chain}/StarknetAction.ts +3 -3
  68. package/src/starknet/chain/StarknetChainInterface.ts +149 -0
  69. package/src/starknet/{base → chain}/StarknetModule.ts +3 -3
  70. package/src/starknet/{base → chain}/modules/StarknetAddresses.ts +1 -1
  71. package/src/starknet/{base → chain}/modules/StarknetSignatures.ts +2 -2
  72. package/src/starknet/{base → chain}/modules/StarknetTokens.ts +2 -1
  73. package/src/starknet/{base → chain}/modules/StarknetTransactions.ts +43 -18
  74. package/src/starknet/contract/StarknetContractBase.ts +9 -12
  75. package/src/starknet/contract/StarknetContractModule.ts +16 -0
  76. package/src/starknet/contract/modules/StarknetContractEvents.ts +33 -7
  77. package/src/starknet/events/StarknetChainEvents.ts +15 -11
  78. package/src/starknet/events/StarknetChainEventsBrowser.ts +157 -26
  79. package/src/starknet/provider/RpcProviderWithRetries.ts +43 -0
  80. package/src/starknet/spv_swap/SpvVaultContractAbi.ts +656 -0
  81. package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +475 -0
  82. package/src/starknet/spv_swap/StarknetSpvVaultData.ts +194 -0
  83. package/src/starknet/spv_swap/StarknetSpvWithdrawalData.ts +68 -0
  84. package/src/starknet/swaps/StarknetSwapContract.ts +28 -116
  85. package/src/starknet/swaps/StarknetSwapModule.ts +8 -8
  86. package/src/starknet/swaps/handlers/IHandler.ts +2 -2
  87. package/src/starknet/swaps/handlers/claim/ClaimHandlers.ts +1 -1
  88. package/src/starknet/swaps/handlers/claim/HashlockClaimHandler.ts +2 -2
  89. package/src/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +2 -2
  90. package/src/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +2 -2
  91. package/src/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +2 -2
  92. package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +12 -61
  93. package/src/starknet/swaps/handlers/refund/TimelockRefundHandler.ts +2 -2
  94. package/src/starknet/swaps/modules/StarknetLpVault.ts +10 -10
  95. package/src/starknet/swaps/modules/StarknetSwapClaim.ts +9 -9
  96. package/src/starknet/swaps/modules/StarknetSwapInit.ts +10 -10
  97. package/src/starknet/swaps/modules/StarknetSwapRefund.ts +9 -13
  98. package/src/starknet/wallet/StarknetSigner.ts +1 -1
  99. package/src/utils/Utils.ts +4 -3
  100. package/dist/starknet/base/StarknetBase.d.ts +0 -34
  101. package/dist/starknet/base/StarknetBase.js +0 -29
  102. package/src/starknet/base/StarknetBase.ts +0 -56
  103. /package/dist/starknet/{base → chain}/StarknetAction.js +0 -0
  104. /package/dist/starknet/{base → chain}/StarknetModule.js +0 -0
  105. /package/dist/starknet/{base → chain}/modules/ERC20Abi.d.ts +0 -0
  106. /package/dist/starknet/{base → chain}/modules/ERC20Abi.js +0 -0
  107. /package/dist/starknet/{base → chain}/modules/StarknetAccounts.d.ts +0 -0
  108. /package/dist/starknet/{base → chain}/modules/StarknetAccounts.js +0 -0
  109. /package/dist/starknet/{base → chain}/modules/StarknetBlocks.d.ts +0 -0
  110. /package/dist/starknet/{base → chain}/modules/StarknetBlocks.js +0 -0
  111. /package/dist/starknet/{base → chain}/modules/StarknetEvents.d.ts +0 -0
  112. /package/dist/starknet/{base → chain}/modules/StarknetEvents.js +0 -0
  113. /package/dist/starknet/{base → chain}/modules/StarknetFees.d.ts +0 -0
  114. /package/dist/starknet/{base → chain}/modules/StarknetFees.js +0 -0
  115. /package/dist/starknet/{base → chain}/modules/StarknetSignatures.js +0 -0
  116. /package/dist/starknet/{base → chain}/modules/StarknetTokens.d.ts +0 -0
  117. /package/src/starknet/{base → chain}/modules/ERC20Abi.ts +0 -0
  118. /package/src/starknet/{base → chain}/modules/StarknetAccounts.ts +0 -0
  119. /package/src/starknet/{base → chain}/modules/StarknetBlocks.ts +0 -0
  120. /package/src/starknet/{base → chain}/modules/StarknetEvents.ts +0 -0
  121. /package/src/starknet/{base → chain}/modules/StarknetFees.ts +0 -0
@@ -1,29 +1,26 @@
1
- import {StarknetBase, StarknetRetryPolicy} from "../base/StarknetBase";
2
- import {constants, Contract, Provider, TypedContractV2} from "starknet";
3
- import {StarknetFees} from "../base/modules/StarknetFees";
1
+ import {StarknetChainInterface} from "../chain/StarknetChainInterface";
2
+ import {Contract, TypedContractV2} from "starknet";
4
3
  import {Abi} from "abi-wan-kanabi";
5
4
  import {StarknetContractEvents} from "./modules/StarknetContractEvents";
6
5
 
7
6
  /**
8
7
  * Base class providing program specific utilities
9
8
  */
10
- export class StarknetContractBase<T extends Abi> extends StarknetBase {
9
+ export class StarknetContractBase<T extends Abi> {
11
10
 
12
11
  contract: TypedContractV2<T>;
13
12
 
14
13
  public readonly Events: StarknetContractEvents<T>;
14
+ public readonly Chain: StarknetChainInterface;
15
15
 
16
16
  constructor(
17
- chainId: constants.StarknetChainId,
18
- provider: Provider,
17
+ chainInterface: StarknetChainInterface,
19
18
  contractAddress: string,
20
- contractAbi: T,
21
- retryPolicy?: StarknetRetryPolicy,
22
- solanaFeeEstimator: StarknetFees = new StarknetFees(provider)
19
+ contractAbi: T
23
20
  ) {
24
- super(chainId, provider, retryPolicy, solanaFeeEstimator);
25
- this.contract = new Contract(contractAbi, contractAddress, provider).typedv2(contractAbi);
26
- this.Events = new StarknetContractEvents(this, contractAbi);
21
+ this.Chain = chainInterface;
22
+ this.contract = new Contract(contractAbi, contractAddress, chainInterface.provider).typedv2(contractAbi);
23
+ this.Events = new StarknetContractEvents(chainInterface, this, contractAbi);
27
24
  }
28
25
 
29
26
  }
@@ -0,0 +1,16 @@
1
+ import {Abi} from "abi-wan-kanabi";
2
+ import {StarknetContractBase} from "./StarknetContractBase";
3
+ import {StarknetChainInterface} from "../chain/StarknetChainInterface";
4
+ import {StarknetModule} from "../chain/StarknetModule";
5
+
6
+
7
+ export class StarknetContractModule<TAbi extends Abi> extends StarknetModule {
8
+
9
+ readonly contract: StarknetContractBase<TAbi>;
10
+
11
+ constructor(chainInterface: StarknetChainInterface, contract: StarknetContractBase<TAbi>) {
12
+ super(chainInterface)
13
+ this.contract = contract;
14
+ }
15
+
16
+ }
@@ -1,9 +1,10 @@
1
1
  import {Abi} from "abi-wan-kanabi";
2
2
  import {EventToPrimitiveType, ExtractAbiEventNames} from "abi-wan-kanabi/dist/kanabi";
3
- import {StarknetEvent, StarknetEvents} from "../../base/modules/StarknetEvents";
3
+ import {StarknetEvent, StarknetEvents} from "../../chain/modules/StarknetEvents";
4
4
  import {CallData, events, hash} from "starknet";
5
5
  import {StarknetContractBase} from "../StarknetContractBase";
6
6
  import {toHex} from "../../../utils/Utils";
7
+ import {StarknetChainInterface} from "../../chain/StarknetChainInterface";
7
8
 
8
9
  export type StarknetAbiEvent<TAbi extends Abi, TEventName extends ExtractAbiEventNames<TAbi>> = {
9
10
  name: TEventName,
@@ -17,11 +18,12 @@ export type StarknetAbiEvent<TAbi extends Abi, TEventName extends ExtractAbiEven
17
18
 
18
19
  export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
19
20
 
20
- readonly root: StarknetContractBase<TAbi>;
21
+ readonly contract: StarknetContractBase<TAbi>;
21
22
  readonly abi: TAbi;
22
23
 
23
- constructor(root: StarknetContractBase<TAbi>, abi: TAbi) {
24
- super(root);
24
+ constructor(chainInterface: StarknetChainInterface, contract: StarknetContractBase<TAbi>, abi: TAbi) {
25
+ super(chainInterface);
26
+ this.contract = contract;
25
27
  this.abi = abi;
26
28
  }
27
29
 
@@ -76,12 +78,12 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
76
78
  startBlockHeight?: number,
77
79
  endBlockHeight: number = startBlockHeight
78
80
  ): Promise<StarknetAbiEvent<TAbi, T>[]> {
79
- const blockEvents = await super.getBlockEvents(this.root.contract.address, this.toFilter(events, keys), startBlockHeight, endBlockHeight);
81
+ const blockEvents = await super.getBlockEvents(this.contract.contract.address, this.toFilter(events, keys), startBlockHeight, endBlockHeight);
80
82
  return this.toStarknetAbiEvents(blockEvents);
81
83
  }
82
84
 
83
85
  /**
84
- * Runs a search forawrds in time, processing the events for a specific topic public key
86
+ * Runs a search backwards in time, processing the events for a specific topic public key
85
87
  *
86
88
  * @param events
87
89
  * @param keys
@@ -95,7 +97,31 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
95
97
  processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>,
96
98
  abortSignal?: AbortSignal
97
99
  ) {
98
- return this.findInEvents<T>(this.root.contract.address, this.toFilter(events, keys), async (events: StarknetEvent[]) => {
100
+ return this.findInEvents<T>(this.contract.contract.address, this.toFilter(events, keys), async (events: StarknetEvent[]) => {
101
+ const parsedEvents = this.toStarknetAbiEvents<TEvent>(events);
102
+ for(let event of parsedEvents) {
103
+ const result: T = await processor(event);
104
+ if(result!=null) return result;
105
+ }
106
+ }, abortSignal);
107
+ }
108
+
109
+ /**
110
+ * Runs a search forwards in time, processing the events for a specific topic public key
111
+ *
112
+ * @param events
113
+ * @param keys
114
+ * @param processor called for every event, should return a value if the correct event was found, or null
115
+ * if the search should continue
116
+ * @param abortSignal
117
+ */
118
+ public async findInContractEventsForward<T, TEvent extends ExtractAbiEventNames<TAbi>>(
119
+ events: TEvent[],
120
+ keys: string[],
121
+ processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>,
122
+ abortSignal?: AbortSignal
123
+ ) {
124
+ return this.findInEventsForward<T>(this.contract.contract.address, this.toFilter(events, keys), async (events: StarknetEvent[]) => {
99
125
  const parsedEvents = this.toStarknetAbiEvents<TEvent>(events);
100
126
  for(let event of parsedEvents) {
101
127
  const result: T = await processor(event);
@@ -2,6 +2,8 @@ import {StarknetChainEventsBrowser} from "./StarknetChainEventsBrowser";
2
2
  //@ts-ignore
3
3
  import * as fs from "fs/promises";
4
4
  import {StarknetSwapContract} from "../swaps/StarknetSwapContract";
5
+ import {StarknetChainInterface} from "../chain/StarknetChainInterface";
6
+ import {StarknetSpvVaultContract} from "../spv_swap/StarknetSpvVaultContract";
5
7
 
6
8
  const BLOCKHEIGHT_FILENAME = "/strk-blockheight.txt";
7
9
 
@@ -11,10 +13,12 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
11
13
 
12
14
  constructor(
13
15
  directory: string,
16
+ chainInterface: StarknetChainInterface,
14
17
  starknetSwapContract: StarknetSwapContract,
18
+ starknetSpvVaultContract: StarknetSpvVaultContract,
15
19
  pollIntervalSeconds?: number
16
20
  ) {
17
- super(starknetSwapContract, pollIntervalSeconds);
21
+ super(chainInterface, starknetSwapContract, starknetSpvVaultContract, pollIntervalSeconds);
18
22
  this.directory = directory;
19
23
  }
20
24
 
@@ -23,22 +27,22 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
23
27
  *
24
28
  * @private
25
29
  */
26
- private async getLastEventData(): Promise<{blockNumber: number, txHash: string}> {
30
+ private async getLastEventData(): Promise<{blockNumber: number, txHashes: string[]}> {
27
31
  try {
28
- const txt = (await fs.readFile(this.directory+BLOCKHEIGHT_FILENAME)).toString();
32
+ const txt: string = (await fs.readFile(this.directory+BLOCKHEIGHT_FILENAME)).toString();
29
33
  const arr = txt.split(";");
30
34
  if(arr.length<2) return {
31
35
  blockNumber: parseInt(arr[0]),
32
- txHash: null
36
+ txHashes: null
33
37
  };
34
38
  return {
35
39
  blockNumber: parseInt(arr[0]),
36
- txHash: arr[1]
40
+ txHashes: arr.slice(1)
37
41
  };
38
42
  } catch (e) {
39
43
  return {
40
44
  blockNumber: null,
41
- txHash: null
45
+ txHashes: null
42
46
  };
43
47
  }
44
48
  }
@@ -48,16 +52,16 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
48
52
  *
49
53
  * @private
50
54
  */
51
- private saveLastEventData(blockNumber: number, txHash: string): Promise<void> {
52
- return fs.writeFile(this.directory+BLOCKHEIGHT_FILENAME, blockNumber.toString()+";"+txHash);
55
+ private saveLastEventData(blockNumber: number, txHashes: string[]): Promise<void> {
56
+ return fs.writeFile(this.directory+BLOCKHEIGHT_FILENAME, blockNumber.toString()+";"+txHashes.join(";"));
53
57
  }
54
58
 
55
59
  async init(): Promise<void> {
56
- const {blockNumber, txHash} = await this.getLastEventData();
60
+ const {blockNumber, txHashes} = await this.getLastEventData();
57
61
  await this.setupPoll(
58
62
  blockNumber,
59
- txHash,
60
- (blockNumber: number, txHash: string) => this.saveLastEventData(blockNumber, txHash)
63
+ txHashes,
64
+ (blockNumber: number, txHashes: string[]) => this.saveLastEventData(blockNumber, txHashes)
61
65
  );
62
66
  }
63
67
 
@@ -1,11 +1,11 @@
1
1
  import {
2
+ ChainEvent,
2
3
  ChainEvents,
3
4
  ChainSwapType,
4
5
  ClaimEvent,
5
6
  EventListener,
6
7
  InitializeEvent,
7
- RefundEvent,
8
- SwapEvent
8
+ RefundEvent, SpvVaultClaimEvent, SpvVaultCloseEvent, SpvVaultDepositEvent, SpvVaultFrontEvent, SpvVaultOpenEvent
9
9
  } from "@atomiqlabs/base";
10
10
  import {StarknetSwapData} from "../swaps/StarknetSwapData";
11
11
  import {
@@ -13,8 +13,7 @@ import {
13
13
  bytes31SpanToBuffer, findLastIndex,
14
14
  getLogger,
15
15
  onceAsync,
16
- parseInitFunctionCalldata,
17
- timeoutPromise,
16
+ parseInitFunctionCalldata, toBigInt,
18
17
  toHex
19
18
  } from "../../utils/Utils";
20
19
  import {StarknetSwapContract} from "../swaps/StarknetSwapContract";
@@ -23,6 +22,9 @@ import {StarknetAbiEvent} from "../contract/modules/StarknetContractEvents";
23
22
  import {EscrowManagerAbiType} from "../swaps/EscrowManagerAbi";
24
23
  import {ExtractAbiFunctionNames} from "abi-wan-kanabi/dist/kanabi";
25
24
  import {IClaimHandler} from "../swaps/handlers/claim/ClaimHandlers";
25
+ import {StarknetSpvVaultContract} from "../spv_swap/StarknetSpvVaultContract";
26
+ import {StarknetChainInterface} from "../chain/StarknetChainInterface";
27
+ import {SpvVaultContractAbiType} from "../spv_swap/SpvVaultContractAbi";
26
28
 
27
29
  export type StarknetTraceCall = {
28
30
  calldata: string[],
@@ -41,6 +43,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
41
43
  protected readonly listeners: EventListener<StarknetSwapData>[] = [];
42
44
  protected readonly provider: Provider;
43
45
  protected readonly starknetSwapContract: StarknetSwapContract;
46
+ protected readonly starknetSpvVaultContract: StarknetSpvVaultContract;
44
47
  protected eventListeners: number[] = [];
45
48
  protected readonly logger = getLogger("StarknetChainEventsBrowser: ");
46
49
 
@@ -52,9 +55,15 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
52
55
 
53
56
  private timeout: number;
54
57
 
55
- constructor(starknetSwapContract: StarknetSwapContract, pollIntervalSeconds: number = 5) {
56
- this.provider = starknetSwapContract.provider;
58
+ constructor(
59
+ chainInterface: StarknetChainInterface,
60
+ starknetSwapContract: StarknetSwapContract,
61
+ starknetSpvVaultContract: StarknetSpvVaultContract,
62
+ pollIntervalSeconds: number = 5
63
+ ) {
64
+ this.provider = chainInterface.provider;
57
65
  this.starknetSwapContract = starknetSwapContract;
66
+ this.starknetSpvVaultContract = starknetSpvVaultContract;
58
67
  this.pollIntervalSeconds = pollIntervalSeconds;
59
68
  }
60
69
 
@@ -146,6 +155,75 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
146
155
  return new ClaimEvent<StarknetSwapData>(escrowHash, witnessResult);
147
156
  }
148
157
 
158
+ protected parseSpvOpenEvent(
159
+ event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Opened">
160
+ ): SpvVaultOpenEvent {
161
+ const owner = toHex(event.params.owner);
162
+ const vaultId = toBigInt(event.params.vault_id);
163
+ const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
164
+ const vout = Number(toBigInt(event.params.vout));
165
+
166
+ this.logger.debug("SpvOpenEvent owner: "+owner+" vaultId: "+vaultId+" utxo: "+btcTxId+":"+vout);
167
+ return new SpvVaultOpenEvent(owner, vaultId, btcTxId, vout);
168
+ }
169
+
170
+ protected parseSpvDepositEvent(
171
+ event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Deposited">
172
+ ): SpvVaultDepositEvent {
173
+ const owner = toHex(event.params.owner);
174
+ const vaultId = toBigInt(event.params.vault_id);
175
+ const amounts = [toBigInt(event.params.amounts["0"] as BigNumberish), toBigInt(event.params.amounts["1"] as BigNumberish)];
176
+ const depositCount = Number(toBigInt(event.params.deposit_count));
177
+
178
+ this.logger.debug("SpvDepositEvent owner: "+owner+" vaultId: "+vaultId+" depositCount: "+depositCount+" amounts: ", amounts);
179
+ return new SpvVaultDepositEvent(owner, vaultId, amounts, depositCount);
180
+ }
181
+
182
+ protected parseSpvFrontEvent(
183
+ event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Fronted">
184
+ ): SpvVaultFrontEvent {
185
+ const owner = toHex(event.params.owner);
186
+ const vaultId = toBigInt(event.params.vault_id);
187
+ const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
188
+ const recipient = toHex(event.params.recipient);
189
+ const executionHash = toHex(event.params.execution_hash);
190
+ const amounts = [toBigInt(event.params.amounts["0"] as BigNumberish), toBigInt(event.params.amounts["1"] as BigNumberish)];
191
+ const frontingAddress = toHex(event.params.caller);
192
+
193
+ this.logger.debug("SpvFrontEvent owner: "+owner+" vaultId: "+vaultId+" btcTxId: "+btcTxId+
194
+ " recipient: "+recipient+" frontedBy: "+frontingAddress+" amounts: ", amounts);
195
+ return new SpvVaultFrontEvent(owner, vaultId, btcTxId, recipient, executionHash, amounts, frontingAddress);
196
+ }
197
+
198
+ protected parseSpvClaimEvent(
199
+ event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Claimed">
200
+ ): SpvVaultClaimEvent {
201
+ const owner = toHex(event.params.owner);
202
+ const vaultId = toBigInt(event.params.vault_id);
203
+ const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
204
+ const recipient = toHex(event.params.recipient);
205
+ const executionHash = toHex(event.params.execution_hash);
206
+ const amounts = [toBigInt(event.params.amounts["0"] as BigNumberish), toBigInt(event.params.amounts["1"] as BigNumberish)];
207
+ const caller = toHex(event.params.caller);
208
+ const frontingAddress = toHex(event.params.fronting_address);
209
+ const withdrawCount = Number(toBigInt(event.params.withdraw_count));
210
+
211
+ this.logger.debug("SpvClaimEvent owner: "+owner+" vaultId: "+vaultId+" btcTxId: "+btcTxId+" withdrawCount: "+withdrawCount+
212
+ " recipient: "+recipient+" frontedBy: "+frontingAddress+" claimedBy: "+caller+" amounts: ", amounts);
213
+ return new SpvVaultClaimEvent(owner, vaultId, btcTxId, recipient, executionHash, amounts, caller, frontingAddress, withdrawCount);
214
+ }
215
+
216
+ protected parseSpvCloseEvent(
217
+ event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Closed">
218
+ ): SpvVaultCloseEvent {
219
+ const owner = toHex(event.params.owner);
220
+ const vaultId = toBigInt(event.params.vault_id);
221
+ const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
222
+ const error = bigNumberishToBuffer(event.params.error).toString();
223
+
224
+ return new SpvVaultCloseEvent(owner, vaultId, btcTxId, error);
225
+ }
226
+
149
227
  /**
150
228
  * Processes event as received from the chain, parses it & calls event listeners
151
229
  *
@@ -156,10 +234,13 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
156
234
  * @protected
157
235
  */
158
236
  protected async processEvents(
159
- events : StarknetAbiEvent<
237
+ events : (StarknetAbiEvent<
160
238
  EscrowManagerAbiType,
161
239
  "escrow_manager::events::Initialize" | "escrow_manager::events::Refund" | "escrow_manager::events::Claim"
162
- >[],
240
+ > | StarknetAbiEvent<
241
+ SpvVaultContractAbiType,
242
+ "spv_swap_vault::events::Opened" | "spv_swap_vault::events::Deposited" | "spv_swap_vault::events::Fronted" | "spv_swap_vault::events::Claimed" | "spv_swap_vault::events::Closed"
243
+ >)[],
163
244
  currentBlockNumber: number,
164
245
  currentBlockTimestamp: number,
165
246
  pendingEventTime: number
@@ -172,10 +253,10 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
172
253
  return blockTimestampsCache[blockNumberString];
173
254
  }
174
255
 
175
- const parsedEvents: SwapEvent<StarknetSwapData>[] = [];
256
+ const parsedEvents: ChainEvent<StarknetSwapData>[] = [];
176
257
 
177
258
  for(let event of events) {
178
- let parsedEvent: SwapEvent<StarknetSwapData>;
259
+ let parsedEvent: ChainEvent<StarknetSwapData>;
179
260
  switch(event.name) {
180
261
  case "escrow_manager::events::Claim":
181
262
  parsedEvent = this.parseClaimEvent(event as any);
@@ -186,6 +267,21 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
186
267
  case "escrow_manager::events::Initialize":
187
268
  parsedEvent = this.parseInitializeEvent(event as any);
188
269
  break;
270
+ case "spv_swap_vault::events::Opened":
271
+ parsedEvent = this.parseSpvOpenEvent(event as any);
272
+ break;
273
+ case "spv_swap_vault::events::Deposited":
274
+ parsedEvent = this.parseSpvDepositEvent(event as any);
275
+ break;
276
+ case "spv_swap_vault::events::Fronted":
277
+ parsedEvent = this.parseSpvFrontEvent(event as any);
278
+ break;
279
+ case "spv_swap_vault::events::Claimed":
280
+ parsedEvent = this.parseSpvClaimEvent(event as any);
281
+ break;
282
+ case "spv_swap_vault::events::Closed":
283
+ parsedEvent = this.parseSpvCloseEvent(event as any);
284
+ break;
189
285
  }
190
286
  const timestamp = event.blockNumber==null ? pendingEventTime : await getBlockTimestamp(event.blockNumber);
191
287
  parsedEvent.meta = {
@@ -201,32 +297,67 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
201
297
  }
202
298
  }
203
299
 
204
- protected async checkEvents(lastBlockNumber: number, lastTxHash: string): Promise<{txHash: string, blockNumber: number}> {
205
- const currentBlock = await this.provider.getBlockWithTxHashes("latest");
300
+ protected async checkEventsEcrowManager(lastTxHash: string, lastBlockNumber?: number, currentBlock?: {timestamp: number, block_number: number}): Promise<string> {
206
301
  const currentBlockNumber: number = (currentBlock as any).block_number;
207
302
  lastBlockNumber ??= currentBlockNumber;
208
303
  const logStartHeight = currentBlockNumber>lastBlockNumber ? lastBlockNumber+1 : lastBlockNumber;
209
- this.logger.debug("checkEvents(): Requesting logs: "+logStartHeight+"...pending");
210
- const events = await this.starknetSwapContract.Events.getContractBlockEvents(
304
+ this.logger.debug("checkEvents(EscrowManager): Requesting logs: "+logStartHeight+"...pending");
305
+ let events = await this.starknetSwapContract.Events.getContractBlockEvents(
211
306
  ["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
212
307
  [],
213
308
  logStartHeight,
214
309
  null
215
310
  );
216
311
  if(lastTxHash!=null) {
217
- const latestProcessedEventIndex = findLastIndex(events, val => val.txHash === lastTxHash);
218
- if (latestProcessedEventIndex !== -1) {
219
- events.splice(0, latestProcessedEventIndex + 1);
220
- this.logger.debug("checkEvents(): Splicing processed events, resulting size: "+events.length);
312
+ const latestProcessedEventIndex = findLastIndex(events, val => val.txHash===lastTxHash);
313
+ if(latestProcessedEventIndex!==-1) {
314
+ events.splice(0, latestProcessedEventIndex+1);
315
+ this.logger.debug("checkEvents(EscrowManager): Splicing processed events, resulting size: "+events.length);
221
316
  }
222
317
  }
223
318
  if(events.length>0) {
224
- await this.processEvents(events, currentBlockNumber, currentBlock.timestamp, Math.floor(Date.now()/1000));
225
- lastTxHash = events[events.length - 1].txHash;
319
+ await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now()/1000));
320
+ lastTxHash = events[events.length-1].txHash;
226
321
  }
322
+ return lastTxHash;
323
+ }
324
+
325
+ protected async checkEventsSpvVaults(lastTxHash: string, lastBlockNumber?: number, currentBlock?: {timestamp: number, block_number: number}): Promise<string> {
326
+ const currentBlockNumber: number = (currentBlock as any).block_number;
327
+ lastBlockNumber ??= currentBlockNumber;
328
+ const logStartHeight = currentBlockNumber>lastBlockNumber ? lastBlockNumber+1 : lastBlockNumber;
329
+ this.logger.debug("checkEvents(SpvVaults): Requesting logs: "+logStartHeight+"...pending");
330
+ let events = await this.starknetSpvVaultContract.Events.getContractBlockEvents(
331
+ ["spv_swap_vault::events::Opened", "spv_swap_vault::events::Deposited", "spv_swap_vault::events::Closed", "spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"],
332
+ [],
333
+ logStartHeight,
334
+ null
335
+ );
336
+ if(lastTxHash!=null) {
337
+ const latestProcessedEventIndex = findLastIndex(events, val => val.txHash===lastTxHash);
338
+ if(latestProcessedEventIndex!==-1) {
339
+ events.splice(0, latestProcessedEventIndex+1);
340
+ this.logger.debug("checkEvents(SpvVaults): Splicing processed events, resulting size: "+events.length);
341
+ }
342
+ }
343
+ if(events.length>0) {
344
+ await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now()/1000));
345
+ lastTxHash = events[events.length-1].txHash;
346
+ }
347
+ return lastTxHash;
348
+ }
349
+
350
+ protected async checkEvents(lastBlockNumber: number, lastTxHashes: string[]): Promise<{txHashes: string[], blockNumber: number}> {
351
+ lastTxHashes ??= [];
352
+
353
+ const currentBlock = await this.provider.getBlockWithTxHashes("latest");
354
+ const currentBlockNumber: number = (currentBlock as any).block_number;
355
+
356
+ lastTxHashes[0] = await this.checkEventsEcrowManager(lastTxHashes[0], lastBlockNumber, currentBlock as any);
357
+ lastTxHashes[1] = await this.checkEventsSpvVaults(lastTxHashes[1], lastBlockNumber, currentBlock as any);
227
358
 
228
359
  return {
229
- txHash: lastTxHash,
360
+ txHashes: lastTxHashes,
230
361
  blockNumber: currentBlockNumber
231
362
  };
232
363
  }
@@ -238,16 +369,16 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
238
369
  */
239
370
  protected async setupPoll(
240
371
  lastBlockNumber?: number,
241
- lastTxHash?: string,
242
- saveLatestProcessedBlockNumber?: (blockNumber: number, lastTxHash: string) => Promise<void>
372
+ lastTxHashes?: string[],
373
+ saveLatestProcessedBlockNumber?: (blockNumber: number, lastTxHashes: string[]) => Promise<void>
243
374
  ) {
244
375
  this.stopped = false;
245
376
  let func;
246
377
  func = async () => {
247
- await this.checkEvents(lastBlockNumber, lastTxHash).then(({blockNumber, txHash}) => {
378
+ await this.checkEvents(lastBlockNumber, lastTxHashes).then(({blockNumber, txHashes}) => {
248
379
  lastBlockNumber = blockNumber;
249
- lastTxHash = txHash;
250
- if(saveLatestProcessedBlockNumber!=null) return saveLatestProcessedBlockNumber(blockNumber, lastTxHash);
380
+ lastTxHashes = txHashes;
381
+ if(saveLatestProcessedBlockNumber!=null) return saveLatestProcessedBlockNumber(blockNumber, lastTxHashes);
251
382
  }).catch(e => {
252
383
  this.logger.error("setupPoll(): Failed to fetch starknet log: ", e);
253
384
  });
@@ -0,0 +1,43 @@
1
+ import {
2
+ RpcChannel,
3
+ RpcProvider,
4
+ RpcProviderOptions
5
+ } from "starknet";
6
+ import {tryWithRetries} from "../../utils/Utils";
7
+
8
+ export class RpcChannelWithRetries extends RpcChannel {
9
+
10
+ readonly retryPolicy?: {
11
+ maxRetries?: number, delay?: number, exponential?: boolean
12
+ };
13
+
14
+ constructor(options?: RpcProviderOptions, retryPolicy?: {
15
+ maxRetries?: number, delay?: number, exponential?: boolean
16
+ }) {
17
+ super(options);
18
+ this.retryPolicy = retryPolicy;
19
+ }
20
+
21
+ protected fetchEndpoint(method: any, params?: any): Promise<any> {
22
+ return tryWithRetries(() => super.fetchEndpoint(method, params), this.retryPolicy, e => {
23
+ if(!e.message.startsWith("RPC: ")) return false;
24
+ const arr = e.message.split("\n");
25
+ const errorCode = parseInt(arr[arr.length-1]);
26
+ if(isNaN(errorCode)) return false;
27
+ if(errorCode < 0) return false; //Not defined error, e.g. Rate limit (-32097)
28
+ return true;
29
+ });
30
+ }
31
+
32
+ }
33
+
34
+ export class RpcProviderWithRetries extends RpcProvider {
35
+
36
+ constructor(options?: RpcProviderOptions, retryPolicy?: {
37
+ maxRetries?: number, delay?: number, exponential?: boolean
38
+ }) {
39
+ super(options);
40
+ this.channel = new RpcChannelWithRetries({ ...options, waitMode: false }, retryPolicy);
41
+ }
42
+
43
+ }