@atomiqlabs/chain-starknet 4.0.0-dev.27 → 4.0.0-dev.28

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