@atomiqlabs/chain-starknet 3.0.0-dev.8 → 4.0.0-dev.3

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 (146) hide show
  1. package/LICENSE +201 -201
  2. package/dist/index.d.ts +38 -38
  3. package/dist/index.js +54 -54
  4. package/dist/starknet/StarknetChainType.d.ts +13 -13
  5. package/dist/starknet/StarknetChainType.js +2 -2
  6. package/dist/starknet/StarknetInitializer.d.ts +27 -19
  7. package/dist/starknet/StarknetInitializer.js +69 -69
  8. package/dist/starknet/btcrelay/BtcRelayAbi.d.ts +250 -250
  9. package/dist/starknet/btcrelay/BtcRelayAbi.js +341 -341
  10. package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +186 -186
  11. package/dist/starknet/btcrelay/StarknetBtcRelay.js +379 -379
  12. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.d.ts +31 -31
  13. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.js +74 -74
  14. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.d.ts +51 -51
  15. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.js +113 -113
  16. package/dist/starknet/chain/StarknetAction.d.ts +19 -19
  17. package/dist/starknet/chain/StarknetAction.js +73 -73
  18. package/dist/starknet/chain/StarknetChainInterface.d.ts +52 -52
  19. package/dist/starknet/chain/StarknetChainInterface.js +91 -91
  20. package/dist/starknet/chain/StarknetModule.d.ts +14 -14
  21. package/dist/starknet/chain/StarknetModule.js +13 -13
  22. package/dist/starknet/chain/modules/ERC20Abi.d.ts +755 -755
  23. package/dist/starknet/chain/modules/ERC20Abi.js +1032 -1032
  24. package/dist/starknet/chain/modules/StarknetAccounts.d.ts +6 -6
  25. package/dist/starknet/chain/modules/StarknetAccounts.js +24 -24
  26. package/dist/starknet/chain/modules/StarknetAddresses.d.ts +9 -9
  27. package/dist/starknet/chain/modules/StarknetAddresses.js +26 -26
  28. package/dist/starknet/chain/modules/StarknetBlocks.d.ts +20 -19
  29. package/dist/starknet/chain/modules/StarknetBlocks.js +64 -49
  30. package/dist/starknet/chain/modules/StarknetEvents.d.ts +44 -44
  31. package/dist/starknet/chain/modules/StarknetEvents.js +88 -88
  32. package/dist/starknet/chain/modules/StarknetFees.d.ts +77 -77
  33. package/dist/starknet/chain/modules/StarknetFees.js +114 -114
  34. package/dist/starknet/chain/modules/StarknetSignatures.d.ts +29 -29
  35. package/dist/starknet/chain/modules/StarknetSignatures.js +72 -72
  36. package/dist/starknet/chain/modules/StarknetTokens.d.ts +69 -69
  37. package/dist/starknet/chain/modules/StarknetTokens.js +98 -98
  38. package/dist/starknet/chain/modules/StarknetTransactions.d.ts +93 -93
  39. package/dist/starknet/chain/modules/StarknetTransactions.js +255 -255
  40. package/dist/starknet/contract/StarknetContractBase.d.ts +13 -13
  41. package/dist/starknet/contract/StarknetContractBase.js +16 -16
  42. package/dist/starknet/contract/StarknetContractModule.d.ts +8 -8
  43. package/dist/starknet/contract/StarknetContractModule.js +11 -11
  44. package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +51 -51
  45. package/dist/starknet/contract/modules/StarknetContractEvents.js +97 -97
  46. package/dist/starknet/events/StarknetChainEvents.d.ts +21 -21
  47. package/dist/starknet/events/StarknetChainEvents.js +52 -52
  48. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +90 -91
  49. package/dist/starknet/events/StarknetChainEventsBrowser.js +292 -294
  50. package/dist/starknet/provider/RpcProviderWithRetries.d.ts +21 -21
  51. package/dist/starknet/provider/RpcProviderWithRetries.js +32 -32
  52. package/dist/starknet/spv_swap/SpvVaultContractAbi.d.ts +488 -488
  53. package/dist/starknet/spv_swap/SpvVaultContractAbi.js +656 -656
  54. package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +66 -65
  55. package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +382 -376
  56. package/dist/starknet/spv_swap/StarknetSpvVaultData.d.ts +49 -49
  57. package/dist/starknet/spv_swap/StarknetSpvVaultData.js +145 -144
  58. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +25 -24
  59. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +72 -61
  60. package/dist/starknet/swaps/EscrowManagerAbi.d.ts +434 -434
  61. package/dist/starknet/swaps/EscrowManagerAbi.js +587 -587
  62. package/dist/starknet/swaps/StarknetSwapContract.d.ts +190 -196
  63. package/dist/starknet/swaps/StarknetSwapContract.js +409 -395
  64. package/dist/starknet/swaps/StarknetSwapData.d.ts +67 -67
  65. package/dist/starknet/swaps/StarknetSwapData.js +290 -290
  66. package/dist/starknet/swaps/StarknetSwapModule.d.ts +10 -10
  67. package/dist/starknet/swaps/StarknetSwapModule.js +11 -11
  68. package/dist/starknet/swaps/handlers/IHandler.d.ts +13 -13
  69. package/dist/starknet/swaps/handlers/IHandler.js +2 -2
  70. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +13 -13
  71. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.js +13 -13
  72. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +21 -21
  73. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.js +44 -44
  74. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +24 -24
  75. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.js +48 -48
  76. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +25 -25
  77. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.js +40 -40
  78. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +20 -20
  79. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.js +30 -30
  80. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +45 -45
  81. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +52 -52
  82. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +17 -17
  83. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.js +27 -27
  84. package/dist/starknet/swaps/modules/StarknetLpVault.d.ts +69 -69
  85. package/dist/starknet/swaps/modules/StarknetLpVault.js +122 -122
  86. package/dist/starknet/swaps/modules/StarknetSwapClaim.d.ts +53 -53
  87. package/dist/starknet/swaps/modules/StarknetSwapClaim.js +100 -100
  88. package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +86 -84
  89. package/dist/starknet/swaps/modules/StarknetSwapInit.js +224 -200
  90. package/dist/starknet/swaps/modules/StarknetSwapRefund.d.ts +62 -62
  91. package/dist/starknet/swaps/modules/StarknetSwapRefund.js +128 -128
  92. package/dist/starknet/wallet/StarknetKeypairWallet.d.ts +7 -7
  93. package/dist/starknet/wallet/StarknetKeypairWallet.js +30 -30
  94. package/dist/starknet/wallet/StarknetSigner.d.ts +12 -12
  95. package/dist/starknet/wallet/StarknetSigner.js +46 -46
  96. package/dist/utils/Utils.d.ts +37 -37
  97. package/dist/utils/Utils.js +261 -257
  98. package/package.json +37 -37
  99. package/src/index.ts +47 -47
  100. package/src/starknet/StarknetChainType.ts +28 -28
  101. package/src/starknet/StarknetInitializer.ts +108 -100
  102. package/src/starknet/btcrelay/BtcRelayAbi.ts +338 -338
  103. package/src/starknet/btcrelay/StarknetBtcRelay.ts +494 -494
  104. package/src/starknet/btcrelay/headers/StarknetBtcHeader.ts +100 -100
  105. package/src/starknet/btcrelay/headers/StarknetBtcStoredHeader.ts +141 -141
  106. package/src/starknet/chain/StarknetAction.ts +85 -85
  107. package/src/starknet/chain/StarknetChainInterface.ts +149 -149
  108. package/src/starknet/chain/StarknetModule.ts +19 -19
  109. package/src/starknet/chain/modules/ERC20Abi.ts +1029 -1029
  110. package/src/starknet/chain/modules/StarknetAccounts.ts +25 -25
  111. package/src/starknet/chain/modules/StarknetAddresses.ts +22 -22
  112. package/src/starknet/chain/modules/StarknetBlocks.ts +74 -58
  113. package/src/starknet/chain/modules/StarknetEvents.ts +104 -104
  114. package/src/starknet/chain/modules/StarknetFees.ts +154 -154
  115. package/src/starknet/chain/modules/StarknetSignatures.ts +91 -91
  116. package/src/starknet/chain/modules/StarknetTokens.ts +116 -116
  117. package/src/starknet/chain/modules/StarknetTransactions.ts +277 -277
  118. package/src/starknet/contract/StarknetContractBase.ts +26 -26
  119. package/src/starknet/contract/StarknetContractModule.ts +16 -16
  120. package/src/starknet/contract/modules/StarknetContractEvents.ts +134 -134
  121. package/src/starknet/events/StarknetChainEvents.ts +67 -67
  122. package/src/starknet/events/StarknetChainEventsBrowser.ts +410 -412
  123. package/src/starknet/provider/RpcProviderWithRetries.ts +43 -43
  124. package/src/starknet/spv_swap/SpvVaultContractAbi.ts +656 -656
  125. package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +483 -477
  126. package/src/starknet/spv_swap/StarknetSpvVaultData.ts +195 -194
  127. package/src/starknet/spv_swap/StarknetSpvWithdrawalData.ts +79 -68
  128. package/src/starknet/swaps/EscrowManagerAbi.ts +586 -586
  129. package/src/starknet/swaps/StarknetSwapContract.ts +628 -605
  130. package/src/starknet/swaps/StarknetSwapData.ts +403 -403
  131. package/src/starknet/swaps/StarknetSwapModule.ts +17 -17
  132. package/src/starknet/swaps/handlers/IHandler.ts +20 -20
  133. package/src/starknet/swaps/handlers/claim/ClaimHandlers.ts +23 -23
  134. package/src/starknet/swaps/handlers/claim/HashlockClaimHandler.ts +53 -53
  135. package/src/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +73 -73
  136. package/src/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +67 -67
  137. package/src/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +50 -50
  138. package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +102 -102
  139. package/src/starknet/swaps/handlers/refund/TimelockRefundHandler.ts +38 -38
  140. package/src/starknet/swaps/modules/StarknetLpVault.ts +147 -147
  141. package/src/starknet/swaps/modules/StarknetSwapClaim.ts +141 -141
  142. package/src/starknet/swaps/modules/StarknetSwapInit.ts +286 -260
  143. package/src/starknet/swaps/modules/StarknetSwapRefund.ts +196 -196
  144. package/src/starknet/wallet/StarknetKeypairWallet.ts +39 -39
  145. package/src/starknet/wallet/StarknetSigner.ts +55 -55
  146. package/src/utils/Utils.ts +252 -248
@@ -1,261 +1,287 @@
1
- import {SignatureVerificationError, SwapCommitStatus, SwapDataVerificationError} from "@atomiqlabs/base";
2
- import {bufferToBytes31Span, toHex, tryWithRetries} from "../../../utils/Utils";
3
- import {Buffer} from "buffer";
4
- import {StarknetSwapData} from "../StarknetSwapData";
5
- import {StarknetAction} from "../../chain/StarknetAction";
6
- import {StarknetSwapModule} from "../StarknetSwapModule";
7
- import {BigNumberish, cairo} from "starknet";
8
- import {StarknetSigner} from "../../wallet/StarknetSigner";
9
- import {StarknetFees} from "../../chain/modules/StarknetFees";
10
- import {StarknetTx} from "../../chain/modules/StarknetTransactions";
11
-
12
- export type StarknetPreFetchVerification = {
13
- pendingBlockTime?: number
14
- };
15
-
16
- const Initialize = [
17
- { name: 'Swap hash', type: 'felt' },
18
- { name: 'Offerer', type: 'ContractAddress'},
19
- { name: 'Claimer', type: 'ContractAddress'},
20
- { name: 'Token amount', type: 'TokenAmount'},
21
- { name: 'Pay in', type: 'bool'},
22
- { name: 'Pay out', type: 'bool'},
23
- { name: 'Tracking reputation', type: 'bool'},
24
- { name: 'Claim handler', type: 'ContractAddress'},
25
- { name: 'Claim data', type: 'felt'},
26
- { name: 'Refund handler', type: 'ContractAddress'},
27
- { name: 'Refund data', type: 'felt'},
28
- { name: 'Security deposit', type: 'TokenAmount'},
29
- { name: 'Claimer bounty', type: 'TokenAmount'},
30
- { name: 'Claim action hash', type: 'felt'},
31
- { name: 'Deadline', type: 'timestamp' }
32
- ];
33
-
34
- export class StarknetSwapInit extends StarknetSwapModule {
35
-
36
- private static readonly GasCosts = {
37
- INIT: {l1DataGas: 750, l2Gas: 8_000_000, l1Gas: 0},
38
- INIT_PAY_IN: {l1DataGas: 500, l2Gas: 4_800_000, l1Gas: 0},
39
- };
40
-
41
- /**
42
- * bare Init action based on the data passed in swapData
43
- *
44
- * @param swapData
45
- * @param timeout
46
- * @param signature
47
- * @private
48
- */
49
- private Init(swapData: StarknetSwapData, timeout: bigint, signature: BigNumberish[]): StarknetAction {
50
- return new StarknetAction(
51
- swapData.payIn ? swapData.offerer : swapData.claimer,
52
- this.root,
53
- this.swapContract.populateTransaction.initialize(
54
- swapData.toEscrowStruct(),
55
- signature,
56
- timeout,
57
- swapData.extraData==null || swapData.extraData==="" ? [] : bufferToBytes31Span(Buffer.from(swapData.extraData, "hex")).map(toHex)
58
- ),
59
- swapData.payIn ? StarknetSwapInit.GasCosts.INIT_PAY_IN : StarknetSwapInit.GasCosts.INIT
60
- )
61
- }
62
-
63
- /**
64
- * Returns auth prefix to be used with a specific swap, payIn=true & payIn=false use different prefixes (these
65
- * actually have no meaning for the smart contract/solana program in the Solana case)
66
- *
67
- * @param swapData
68
- * @private
69
- */
70
- private getAuthPrefix(swapData: StarknetSwapData): string {
71
- return swapData.isPayIn() ? "claim_initialize" : "initialize";
72
- }
73
-
74
- public async preFetchForInitSignatureVerification(): Promise<StarknetPreFetchVerification> {
75
- return {
76
- pendingBlockTime: await this.root.Blocks.getBlockTime("pending")
77
- };
78
- }
79
-
80
- /**
81
- * Signs swap initialization authorization, using data from preFetchedBlockData if provided & still valid (subject
82
- * to SIGNATURE_PREFETCH_DATA_VALIDITY)
83
- *
84
- * @param signer
85
- * @param swapData
86
- * @param authorizationTimeout
87
- * @public
88
- */
89
- public async signSwapInitialization(
90
- signer: StarknetSigner,
91
- swapData: StarknetSwapData,
92
- authorizationTimeout: number
93
- ): Promise<{prefix: string, timeout: string, signature: string}> {
94
- const authTimeout = Math.floor(Date.now()/1000)+authorizationTimeout;
95
-
96
- const signature = await this.root.Signatures.signTypedMessage(signer, Initialize, "Initialize", {
97
- "Swap hash": "0x"+swapData.getEscrowHash(),
98
- "Offerer": swapData.offerer,
99
- "Claimer": swapData.claimer,
100
- "Token amount": {
101
- token_address: swapData.token,
102
- amount: cairo.uint256(swapData.amount)
103
- },
104
- "Pay in": swapData.isPayIn(),
105
- "Pay out": swapData.isPayOut(),
106
- "Tracking reputation": swapData.reputation,
107
- "Refund handler": swapData.refundHandler,
108
- "Claim handler": swapData.claimHandler,
109
- "Claim data": "0x"+swapData.getClaimHash(),
110
- "Refund data": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
111
- "Security deposit": {
112
- token_address: swapData.feeToken,
113
- amount: cairo.uint256(swapData.securityDeposit)
114
- },
115
- "Claimer bounty": {
116
- token_address: swapData.feeToken,
117
- amount: cairo.uint256(swapData.claimerBounty)
118
- },
119
- "Claim action hash": 0n,
120
- "Deadline": toHex(authTimeout)
121
- });
122
-
123
- return {
124
- prefix: this.getAuthPrefix(swapData),
125
- timeout: authTimeout.toString(10),
126
- signature
127
- };
128
- }
129
-
130
- /**
131
- * Checks whether the provided signature data is valid, using preFetchedData if provided and still valid
132
- *
133
- * @param swapData
134
- * @param timeout
135
- * @param prefix
136
- * @param signature
137
- * @param preFetchData
138
- * @public
139
- */
140
- public async isSignatureValid(
141
- swapData: StarknetSwapData,
142
- timeout: string,
143
- prefix: string,
144
- signature: string,
145
- preFetchData?: StarknetPreFetchVerification
146
- ): Promise<null> {
147
- const sender = swapData.isPayIn() ? swapData.offerer : swapData.claimer;
148
- const signer = swapData.isPayIn() ? swapData.claimer : swapData.offerer;
149
-
150
- if(!swapData.isPayIn() && await this.contract.isExpired(sender.toString(), swapData)) {
151
- throw new SignatureVerificationError("Swap will expire too soon!");
152
- }
153
-
154
- if(prefix!==this.getAuthPrefix(swapData)) throw new SignatureVerificationError("Invalid prefix");
155
-
156
- const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
157
- const timeoutBN = BigInt(timeout);
158
- const isExpired = (timeoutBN - currentTimestamp) < BigInt(this.contract.authGracePeriod);
159
- if (isExpired) throw new SignatureVerificationError("Authorization expired!");
160
- if(await this.isSignatureExpired(timeout, preFetchData)) throw new SignatureVerificationError("Authorization expired!");
161
-
162
- const valid = await this.root.Signatures.isValidSignature(signature, signer, Initialize, "Initialize", {
163
- "Swap hash": "0x"+swapData.getEscrowHash(),
164
- "Timeout": toHex(timeoutBN)
165
- });
166
-
167
- if(!valid) throw new SignatureVerificationError("Invalid signature!");
168
-
169
- return null;
170
- }
171
-
172
- /**
173
- * Gets expiry of the provided signature data, this is a minimum of slot expiry & swap signature expiry
174
- *
175
- * @param timeout
176
- * @public
177
- */
178
- public async getSignatureExpiry(
179
- timeout: string
180
- ): Promise<number> {
181
- const now = Date.now();
182
- const timeoutExpiryTime = (parseInt(timeout)-this.contract.authGracePeriod)*1000;
183
-
184
- if(timeoutExpiryTime<now) return 0;
185
-
186
- return timeoutExpiryTime;
187
- }
188
-
189
- /**
190
- * Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
191
- *
192
- * @param timeout
193
- * @param preFetchData
194
- * @public
195
- */
196
- public async isSignatureExpired(
197
- timeout: string,
198
- preFetchData?: StarknetPreFetchVerification
199
- ): Promise<boolean> {
200
- if(preFetchData==null || preFetchData.pendingBlockTime==null) {
201
- preFetchData = await this.preFetchForInitSignatureVerification();
202
- }
203
- return preFetchData.pendingBlockTime > parseInt(timeout);
204
- }
205
-
206
- /**
207
- * Creates init transaction with a valid signature from an LP
208
- *
209
- * @param swapData swap to initialize
210
- * @param timeout init signature timeout
211
- * @param prefix init signature prefix
212
- * @param signature init signature
213
- * @param skipChecks whether to skip signature validity checks
214
- * @param feeRate fee rate to use for the transaction
215
- */
216
- public async txsInit(
217
- swapData: StarknetSwapData,
218
- timeout: string,
219
- prefix: string,
220
- signature: string,
221
- skipChecks?: boolean,
222
- feeRate?: string
223
- ): Promise<StarknetTx[]> {
224
- const sender = swapData.isPayIn() ? swapData.offerer : swapData.claimer;
225
-
226
- if(!skipChecks) {
227
- const [_, payStatus] = await Promise.all([
228
- tryWithRetries(
229
- () => this.isSignatureValid(swapData, timeout, prefix, signature),
230
- this.retryPolicy, (e) => e instanceof SignatureVerificationError
231
- ),
232
- tryWithRetries(() => this.contract.getCommitStatus(sender, swapData), this.retryPolicy)
233
- ]);
234
- if(payStatus!==SwapCommitStatus.NOT_COMMITED) throw new SwapDataVerificationError("Invoice already being paid for or paid");
235
- }
236
-
237
- feeRate ??= await this.root.Fees.getFeeRate();
238
-
239
- const initAction = this.Init(swapData, BigInt(timeout), JSON.parse(signature));
240
- if(swapData.payIn) initAction.addAction(
241
- this.root.Tokens.Approve(sender, this.swapContract.address, swapData.token, swapData.amount), 0
242
- ); //Add erc20 approve
243
- if(swapData.getTotalDeposit() !== 0n) initAction.addAction(
244
- this.root.Tokens.Approve(sender, this.swapContract.address, swapData.feeToken, swapData.getTotalDeposit()), 0
245
- ); //Add deposit erc20 approve
246
-
247
- this.logger.debug("txsInitPayIn(): create swap init TX, swap: "+swapData.getClaimHash()+
248
- " feerate: "+feeRate);
249
-
250
- return [await initAction.tx(feeRate)];
251
- }
252
-
253
- /**
254
- * Get the estimated solana fee of the init transaction, this includes the required deposit for creating swap PDA
255
- * and also deposit for ATAs
256
- */
257
- async getInitFee(swapData?: StarknetSwapData, feeRate?: string): Promise<bigint> {
258
- feeRate ??= await this.root.Fees.getFeeRate();
259
- return StarknetFees.getGasFee(swapData.payIn ? StarknetSwapInit.GasCosts.INIT_PAY_IN : StarknetSwapInit.GasCosts.INIT, feeRate);
260
- }
1
+ import {SignatureVerificationError, SwapCommitStateType, SwapDataVerificationError} from "@atomiqlabs/base";
2
+ import {bufferToBytes31Span, toHex, tryWithRetries} from "../../../utils/Utils";
3
+ import {Buffer} from "buffer";
4
+ import {StarknetSwapData} from "../StarknetSwapData";
5
+ import {StarknetAction} from "../../chain/StarknetAction";
6
+ import {StarknetSwapModule} from "../StarknetSwapModule";
7
+ import {BigNumberish, cairo} from "starknet";
8
+ import {StarknetSigner} from "../../wallet/StarknetSigner";
9
+ import {StarknetFees} from "../../chain/modules/StarknetFees";
10
+ import {StarknetTx} from "../../chain/modules/StarknetTransactions";
11
+
12
+ export type StarknetPreFetchVerification = {
13
+ pendingBlockTime?: number
14
+ };
15
+
16
+ const Initialize = [
17
+ { name: 'Swap hash', type: 'felt' },
18
+ { name: 'Offerer', type: 'ContractAddress'},
19
+ { name: 'Claimer', type: 'ContractAddress'},
20
+ { name: 'Token amount', type: 'TokenAmount'},
21
+ { name: 'Pay in', type: 'bool'},
22
+ { name: 'Pay out', type: 'bool'},
23
+ { name: 'Tracking reputation', type: 'bool'},
24
+ { name: 'Claim handler', type: 'ContractAddress'},
25
+ { name: 'Claim data', type: 'felt'},
26
+ { name: 'Refund handler', type: 'ContractAddress'},
27
+ { name: 'Refund data', type: 'felt'},
28
+ { name: 'Security deposit', type: 'TokenAmount'},
29
+ { name: 'Claimer bounty', type: 'TokenAmount'},
30
+ { name: 'Claim action hash', type: 'felt'},
31
+ { name: 'Deadline', type: 'timestamp' }
32
+ ];
33
+
34
+ export class StarknetSwapInit extends StarknetSwapModule {
35
+
36
+ private static readonly GasCosts = {
37
+ INIT: {l1DataGas: 750, l2Gas: 8_000_000, l1Gas: 0},
38
+ INIT_PAY_IN: {l1DataGas: 500, l2Gas: 4_800_000, l1Gas: 0},
39
+ };
40
+
41
+ /**
42
+ * bare Init action based on the data passed in swapData
43
+ *
44
+ * @param swapData
45
+ * @param timeout
46
+ * @param signature
47
+ * @private
48
+ */
49
+ private Init(swapData: StarknetSwapData, timeout: bigint, signature: BigNumberish[]): StarknetAction {
50
+ return new StarknetAction(
51
+ swapData.payIn ? swapData.offerer : swapData.claimer,
52
+ this.root,
53
+ this.swapContract.populateTransaction.initialize(
54
+ swapData.toEscrowStruct(),
55
+ signature,
56
+ timeout,
57
+ swapData.extraData==null || swapData.extraData==="" ? [] : bufferToBytes31Span(Buffer.from(swapData.extraData, "hex")).map(toHex)
58
+ ),
59
+ swapData.payIn ? StarknetSwapInit.GasCosts.INIT_PAY_IN : StarknetSwapInit.GasCosts.INIT
60
+ )
61
+ }
62
+
63
+ /**
64
+ * Returns auth prefix to be used with a specific swap, payIn=true & payIn=false use different prefixes (these
65
+ * actually have no meaning for the smart contract/solana program in the Solana case)
66
+ *
67
+ * @param swapData
68
+ * @private
69
+ */
70
+ private getAuthPrefix(swapData: StarknetSwapData): string {
71
+ return swapData.isPayIn() ? "claim_initialize" : "initialize";
72
+ }
73
+
74
+ public async preFetchForInitSignatureVerification(): Promise<StarknetPreFetchVerification> {
75
+ return {
76
+ pendingBlockTime: await this.root.Blocks.getBlockTime("pending")
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Signs swap initialization authorization, using data from preFetchedBlockData if provided & still valid (subject
82
+ * to SIGNATURE_PREFETCH_DATA_VALIDITY)
83
+ *
84
+ * @param signer
85
+ * @param swapData
86
+ * @param authorizationTimeout
87
+ * @public
88
+ */
89
+ public async signSwapInitialization(
90
+ signer: StarknetSigner,
91
+ swapData: StarknetSwapData,
92
+ authorizationTimeout: number
93
+ ): Promise<{prefix: string, timeout: string, signature: string}> {
94
+ const authTimeout = Math.floor(Date.now()/1000)+authorizationTimeout;
95
+
96
+ const signature = await this.root.Signatures.signTypedMessage(signer, Initialize, "Initialize", {
97
+ "Swap hash": "0x"+swapData.getEscrowHash(),
98
+ "Offerer": swapData.offerer,
99
+ "Claimer": swapData.claimer,
100
+ "Token amount": {
101
+ token_address: swapData.token,
102
+ amount: cairo.uint256(swapData.amount)
103
+ },
104
+ "Pay in": swapData.isPayIn(),
105
+ "Pay out": swapData.isPayOut(),
106
+ "Tracking reputation": swapData.reputation,
107
+ "Refund handler": swapData.refundHandler,
108
+ "Claim handler": swapData.claimHandler,
109
+ "Claim data": "0x"+swapData.getClaimHash(),
110
+ "Refund data": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
111
+ "Security deposit": {
112
+ token_address: swapData.feeToken,
113
+ amount: cairo.uint256(swapData.securityDeposit)
114
+ },
115
+ "Claimer bounty": {
116
+ token_address: swapData.feeToken,
117
+ amount: cairo.uint256(swapData.claimerBounty)
118
+ },
119
+ "Claim action hash": 0n,
120
+ "Deadline": toHex(authTimeout)
121
+ });
122
+
123
+ return {
124
+ prefix: this.getAuthPrefix(swapData),
125
+ timeout: authTimeout.toString(10),
126
+ signature
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Checks whether the provided signature data is valid, using preFetchedData if provided and still valid
132
+ *
133
+ * @param sender
134
+ * @param swapData
135
+ * @param timeout
136
+ * @param prefix
137
+ * @param signature
138
+ * @param preFetchData
139
+ * @public
140
+ */
141
+ public async isSignatureValid(
142
+ sender: string,
143
+ swapData: StarknetSwapData,
144
+ timeout: string,
145
+ prefix: string,
146
+ signature: string,
147
+ preFetchData?: StarknetPreFetchVerification
148
+ ): Promise<null> {
149
+ if(!swapData.isOfferer(sender) && !swapData.isClaimer(sender))
150
+ throw new SignatureVerificationError("TX sender not offerer nor claimer");
151
+
152
+ const signer = swapData.isOfferer(sender) ? swapData.claimer : swapData.offerer;
153
+
154
+ if(!swapData.isPayIn() && await this.contract.isExpired(sender.toString(), swapData)) {
155
+ throw new SignatureVerificationError("Swap will expire too soon!");
156
+ }
157
+
158
+ if(prefix!==this.getAuthPrefix(swapData)) throw new SignatureVerificationError("Invalid prefix");
159
+
160
+ const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
161
+ const timeoutBN = BigInt(timeout);
162
+ const isExpired = (timeoutBN - currentTimestamp) < BigInt(this.contract.authGracePeriod);
163
+ if (isExpired) throw new SignatureVerificationError("Authorization expired!");
164
+ if(await this.isSignatureExpired(timeout, preFetchData)) throw new SignatureVerificationError("Authorization expired!");
165
+
166
+ const valid = await this.root.Signatures.isValidSignature(signature, signer, Initialize, "Initialize", {
167
+ "Swap hash": "0x"+swapData.getEscrowHash(),
168
+ "Offerer": swapData.offerer,
169
+ "Claimer": swapData.claimer,
170
+ "Token amount": {
171
+ token_address: swapData.token,
172
+ amount: cairo.uint256(swapData.amount)
173
+ },
174
+ "Pay in": swapData.isPayIn(),
175
+ "Pay out": swapData.isPayOut(),
176
+ "Tracking reputation": swapData.reputation,
177
+ "Refund handler": swapData.refundHandler,
178
+ "Claim handler": swapData.claimHandler,
179
+ "Claim data": "0x"+swapData.getClaimHash(),
180
+ "Refund data": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
181
+ "Security deposit": {
182
+ token_address: swapData.feeToken,
183
+ amount: cairo.uint256(swapData.securityDeposit)
184
+ },
185
+ "Claimer bounty": {
186
+ token_address: swapData.feeToken,
187
+ amount: cairo.uint256(swapData.claimerBounty)
188
+ },
189
+ "Claim action hash": 0n,
190
+ "Deadline": toHex(timeoutBN)
191
+ });
192
+
193
+ if(!valid) throw new SignatureVerificationError("Invalid signature!");
194
+
195
+ return null;
196
+ }
197
+
198
+ /**
199
+ * Gets expiry of the provided signature data, this is a minimum of slot expiry & swap signature expiry
200
+ *
201
+ * @param timeout
202
+ * @public
203
+ */
204
+ public async getSignatureExpiry(
205
+ timeout: string
206
+ ): Promise<number> {
207
+ const now = Date.now();
208
+ const timeoutExpiryTime = (parseInt(timeout)-this.contract.authGracePeriod)*1000;
209
+
210
+ if(timeoutExpiryTime<now) return 0;
211
+
212
+ return timeoutExpiryTime;
213
+ }
214
+
215
+ /**
216
+ * Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
217
+ *
218
+ * @param timeout
219
+ * @param preFetchData
220
+ * @public
221
+ */
222
+ public async isSignatureExpired(
223
+ timeout: string,
224
+ preFetchData?: StarknetPreFetchVerification
225
+ ): Promise<boolean> {
226
+ if(preFetchData==null || preFetchData.pendingBlockTime==null) {
227
+ preFetchData = await this.preFetchForInitSignatureVerification();
228
+ }
229
+ return preFetchData.pendingBlockTime > parseInt(timeout);
230
+ }
231
+
232
+ /**
233
+ * Creates init transaction with a valid signature from an LP
234
+ *
235
+ * @param sender
236
+ * @param swapData swap to initialize
237
+ * @param timeout init signature timeout
238
+ * @param prefix init signature prefix
239
+ * @param signature init signature
240
+ * @param skipChecks whether to skip signature validity checks
241
+ * @param feeRate fee rate to use for the transaction
242
+ */
243
+ public async txsInit(
244
+ sender: string,
245
+ swapData: StarknetSwapData,
246
+ timeout: string,
247
+ prefix: string,
248
+ signature: string,
249
+ skipChecks?: boolean,
250
+ feeRate?: string
251
+ ): Promise<StarknetTx[]> {
252
+ if(!skipChecks) {
253
+ const [_, payStatus] = await Promise.all([
254
+ swapData.isOfferer(sender) && !swapData.reputation ? Promise.resolve() : tryWithRetries(
255
+ () => this.isSignatureValid(sender, swapData, timeout, prefix, signature),
256
+ this.retryPolicy, (e) => e instanceof SignatureVerificationError
257
+ ),
258
+ tryWithRetries(() => this.contract.getCommitStatus(sender, swapData), this.retryPolicy)
259
+ ]);
260
+ if(payStatus.type!==SwapCommitStateType.NOT_COMMITED) throw new SwapDataVerificationError("Invoice already being paid for or paid");
261
+ }
262
+
263
+ feeRate ??= await this.root.Fees.getFeeRate();
264
+
265
+ const initAction = this.Init(swapData, BigInt(timeout), JSON.parse(signature));
266
+ if(swapData.payIn && swapData.isOfferer(sender)) initAction.addAction(
267
+ this.root.Tokens.Approve(sender, this.swapContract.address, swapData.token, swapData.amount), 0
268
+ ); //Add erc20 approve
269
+ if(swapData.getTotalDeposit() !== 0n) initAction.addAction(
270
+ this.root.Tokens.Approve(sender, this.swapContract.address, swapData.feeToken, swapData.getTotalDeposit()), 0
271
+ ); //Add deposit erc20 approve
272
+
273
+ this.logger.debug("txsInitPayIn(): create swap init TX, swap: "+swapData.getClaimHash()+
274
+ " feerate: "+feeRate);
275
+
276
+ return [await initAction.tx(feeRate)];
277
+ }
278
+
279
+ /**
280
+ * Get the estimated solana fee of the init transaction, this includes the required deposit for creating swap PDA
281
+ * and also deposit for ATAs
282
+ */
283
+ async getInitFee(swapData?: StarknetSwapData, feeRate?: string): Promise<bigint> {
284
+ feeRate ??= await this.root.Fees.getFeeRate();
285
+ return StarknetFees.getGasFee(swapData.payIn ? StarknetSwapInit.GasCosts.INIT_PAY_IN : StarknetSwapInit.GasCosts.INIT, feeRate);
286
+ }
261
287
  }