@atomiqlabs/chain-starknet 4.0.0-dev.11 → 4.0.0-dev.13

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 (28) hide show
  1. package/dist/starknet/chain/modules/StarknetBlocks.d.ts +1 -1
  2. package/dist/starknet/chain/modules/StarknetEvents.js +2 -2
  3. package/dist/starknet/chain/modules/StarknetFees.d.ts +7 -7
  4. package/dist/starknet/chain/modules/StarknetFees.js +4 -4
  5. package/dist/starknet/chain/modules/StarknetTokens.js +5 -1
  6. package/dist/starknet/chain/modules/StarknetTransactions.js +10 -4
  7. package/dist/starknet/contract/StarknetContractBase.js +5 -1
  8. package/dist/starknet/contract/modules/StarknetContractEvents.js +1 -1
  9. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +1 -2
  10. package/dist/starknet/events/StarknetChainEventsBrowser.js +8 -6
  11. package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +9 -2
  12. package/dist/starknet/swaps/modules/StarknetSwapInit.js +14 -4
  13. package/dist/starknet/wallet/StarknetKeypairWallet.js +6 -1
  14. package/dist/starknet/wallet/StarknetSigner.js +2 -1
  15. package/dist/utils/Utils.js +0 -1
  16. package/package.json +9 -3
  17. package/src/starknet/chain/modules/StarknetBlocks.ts +2 -1
  18. package/src/starknet/chain/modules/StarknetEvents.ts +2 -2
  19. package/src/starknet/chain/modules/StarknetFees.ts +4 -4
  20. package/src/starknet/chain/modules/StarknetTokens.ts +5 -1
  21. package/src/starknet/chain/modules/StarknetTransactions.ts +13 -5
  22. package/src/starknet/contract/StarknetContractBase.ts +5 -1
  23. package/src/starknet/contract/modules/StarknetContractEvents.ts +2 -2
  24. package/src/starknet/events/StarknetChainEventsBrowser.ts +9 -9
  25. package/src/starknet/swaps/modules/StarknetSwapInit.ts +18 -5
  26. package/src/starknet/wallet/StarknetKeypairWallet.ts +6 -1
  27. package/src/starknet/wallet/StarknetSigner.ts +2 -2
  28. package/src/utils/Utils.ts +0 -1
@@ -1,5 +1,5 @@
1
1
  import { StarknetModule } from "../StarknetModule";
2
- export type StarknetBlockTag = "pending" | "latest";
2
+ export type StarknetBlockTag = "pre_confirmed" | "latest";
3
3
  export declare class StarknetBlocks extends StarknetModule {
4
4
  private BLOCK_CACHE_TIME;
5
5
  private blockCache;
@@ -23,8 +23,8 @@ class StarknetEvents extends StarknetModule_1.StarknetModule {
23
23
  while (result == null || result?.continuation_token != null) {
24
24
  result = await this.root.provider.getEvents({
25
25
  address: contract,
26
- from_block: startBlock == null ? "pending" : { block_number: startBlock },
27
- to_block: endBlock == null ? "pending" : { block_number: endBlock },
26
+ from_block: startBlock == null ? "latest" : { block_number: startBlock },
27
+ to_block: endBlock == null ? "latest" : { block_number: endBlock },
28
28
  keys,
29
29
  chunk_size: this.EVENTS_LIMIT,
30
30
  continuation_token: result?.continuation_token
@@ -57,19 +57,19 @@ export declare class StarknetFees {
57
57
  version: "0x3";
58
58
  resourceBounds: {
59
59
  l1_gas: {
60
- max_amount: string;
61
- max_price_per_unit: string;
60
+ max_amount: bigint;
61
+ max_price_per_unit: bigint;
62
62
  };
63
63
  l2_gas: {
64
- max_amount: string;
65
- max_price_per_unit: string;
64
+ max_amount: bigint;
65
+ max_price_per_unit: bigint;
66
66
  };
67
67
  l1_data_gas: {
68
- max_amount: string;
69
- max_price_per_unit: string;
68
+ max_amount: bigint;
69
+ max_price_per_unit: bigint;
70
70
  };
71
71
  };
72
- tip: string;
72
+ tip: bigint;
73
73
  paymasterData: any[];
74
74
  nonceDataAvailabilityMode: "L1" | "L2";
75
75
  feeDataAvailabilityMode: "L1" | "L2";
@@ -100,11 +100,11 @@ class StarknetFees {
100
100
  return {
101
101
  version: "0x3",
102
102
  resourceBounds: {
103
- l1_gas: { max_amount: (0, Utils_1.toHex)(gas.l1Gas, 16), max_price_per_unit: (0, Utils_1.toHex)(BigInt(l1GasCostStr), 16) },
104
- l2_gas: { max_amount: (0, Utils_1.toHex)(gas.l2Gas, 16), max_price_per_unit: (0, Utils_1.toHex)(BigInt(l2GasCostStr), 16) },
105
- l1_data_gas: { max_amount: (0, Utils_1.toHex)(gas.l1DataGas, 16), max_price_per_unit: (0, Utils_1.toHex)(BigInt(l1DataGasCostStr), 16) }
103
+ l1_gas: { max_amount: BigInt(gas.l1Gas), max_price_per_unit: BigInt(l1GasCostStr) },
104
+ l2_gas: { max_amount: BigInt(gas.l2Gas), max_price_per_unit: BigInt(l2GasCostStr) },
105
+ l1_data_gas: { max_amount: BigInt(gas.l1DataGas), max_price_per_unit: BigInt(l1DataGasCostStr) }
106
106
  },
107
- tip: "0x0",
107
+ tip: 0n,
108
108
  paymasterData: [],
109
109
  nonceDataAvailabilityMode: this.nonceDA,
110
110
  feeDataAvailabilityMode: this.feeDA
@@ -9,7 +9,11 @@ const Utils_1 = require("../../../utils/Utils");
9
9
  const StarknetAddresses_1 = require("./StarknetAddresses");
10
10
  class StarknetTokens extends StarknetModule_1.StarknetModule {
11
11
  getContract(address) {
12
- return new starknet_1.Contract(ERC20Abi_1.ERC20Abi, address, this.root.provider).typedv2(ERC20Abi_1.ERC20Abi);
12
+ return new starknet_1.Contract({
13
+ abi: ERC20Abi_1.ERC20Abi,
14
+ address: address,
15
+ providerOrAccount: this.root.provider
16
+ }).typedv2(ERC20Abi_1.ERC20Abi);
13
17
  }
14
18
  /**
15
19
  * Action for transferring the erc20 token
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StarknetTransactions = void 0;
4
4
  const StarknetModule_1 = require("../StarknetModule");
5
+ const starknet_1 = require("starknet");
5
6
  const Utils_1 = require("../../../utils/Utils");
7
+ const MAX_UNCONFIRMED_TXS = 25;
6
8
  class StarknetTransactions extends StarknetModule_1.StarknetModule {
7
9
  constructor() {
8
10
  super(...arguments);
@@ -154,7 +156,7 @@ class StarknetTransactions extends StarknetModule_1.StarknetModule {
154
156
  " waitForConfirmation: " + waitForConfirmation + " parallel: " + parallel);
155
157
  const txIds = [];
156
158
  if (parallel) {
157
- const promises = [];
159
+ let promises = [];
158
160
  for (let i = 0; i < txs.length; i++) {
159
161
  const signedTx = txs[i];
160
162
  const txId = await this.sendSignedTransaction(signedTx, onBeforePublish, signer);
@@ -162,6 +164,10 @@ class StarknetTransactions extends StarknetModule_1.StarknetModule {
162
164
  promises.push(this.confirmTransaction(signedTx, abortSignal));
163
165
  txIds.push(txId);
164
166
  this.logger.debug("sendAndConfirm(): transaction sent (" + (i + 1) + "/" + txs.length + "): " + signedTx.txId);
167
+ if (promises.length >= MAX_UNCONFIRMED_TXS) {
168
+ await Promise.all(promises);
169
+ promises = [];
170
+ }
165
171
  }
166
172
  if (promises.length > 0)
167
173
  await Promise.all(promises);
@@ -224,11 +230,11 @@ class StarknetTransactions extends StarknetModule_1.StarknetModule {
224
230
  });
225
231
  if (status == null)
226
232
  return "not_found";
227
- if (status.finality_status === "RECEIVED")
233
+ if (status.finality_status === starknet_1.ETransactionStatus.RECEIVED)
228
234
  return "pending";
229
- if (status.finality_status === "REJECTED")
235
+ if (status.finality_status === starknet_1.ETransactionStatus.REJECTED)
230
236
  return "rejected";
231
- if (status.execution_status === "SUCCEEDED") {
237
+ if (status.execution_status === starknet_1.ETransactionExecutionStatus.SUCCEEDED) {
232
238
  return "success";
233
239
  }
234
240
  return "reverted";
@@ -9,7 +9,11 @@ const StarknetContractEvents_1 = require("./modules/StarknetContractEvents");
9
9
  class StarknetContractBase {
10
10
  constructor(chainInterface, contractAddress, contractAbi) {
11
11
  this.Chain = chainInterface;
12
- this.contract = new starknet_1.Contract(contractAbi, contractAddress, chainInterface.provider).typedv2(contractAbi);
12
+ this.contract = new starknet_1.Contract({
13
+ abi: contractAbi,
14
+ address: contractAddress,
15
+ providerOrAccount: chainInterface.provider
16
+ }).typedv2(contractAbi);
13
17
  this.Events = new StarknetContractEvents_1.StarknetContractEvents(chainInterface, this, contractAbi);
14
18
  }
15
19
  }
@@ -14,7 +14,7 @@ class StarknetContractEvents extends StarknetEvents_1.StarknetEvents {
14
14
  const abiEvents = starknet_1.events.getAbiEvents(this.abi);
15
15
  const abiStructs = starknet_1.CallData.getAbiStruct(this.abi);
16
16
  const abiEnums = starknet_1.CallData.getAbiEnum(this.abi);
17
- const result = starknet_1.events.parseEvents(blockEvents, abiEvents, abiStructs, abiEnums);
17
+ const result = starknet_1.events.parseEvents(blockEvents, abiEvents, abiStructs, abiEnums, (0, starknet_1.createAbiParser)(this.abi));
18
18
  if (result.length !== blockEvents.length)
19
19
  throw new Error("Invalid event detected, please check provided ABI");
20
20
  return result.map((value, index) => {
@@ -61,10 +61,9 @@ export declare class StarknetChainEventsBrowser implements ChainEvents<StarknetS
61
61
  * @param events
62
62
  * @param currentBlockNumber
63
63
  * @param currentBlockTimestamp
64
- * @param pendingEventTime
65
64
  * @protected
66
65
  */
67
- protected processEvents(events: (StarknetAbiEvent<EscrowManagerAbiType, "escrow_manager::events::Initialize" | "escrow_manager::events::Refund" | "escrow_manager::events::Claim"> | StarknetAbiEvent<SpvVaultContractAbiType, "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">)[], currentBlockNumber: number, currentBlockTimestamp: number, pendingEventTime: number): Promise<void>;
66
+ protected processEvents(events: (StarknetAbiEvent<EscrowManagerAbiType, "escrow_manager::events::Initialize" | "escrow_manager::events::Refund" | "escrow_manager::events::Claim"> | StarknetAbiEvent<SpvVaultContractAbiType, "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">)[], currentBlockNumber: number, currentBlockTimestamp: number): Promise<void>;
68
67
  protected checkEventsEcrowManager(lastTxHash: string, lastBlockNumber?: number, currentBlock?: {
69
68
  timestamp: number;
70
69
  block_number: number;
@@ -145,10 +145,9 @@ class StarknetChainEventsBrowser {
145
145
  * @param events
146
146
  * @param currentBlockNumber
147
147
  * @param currentBlockTimestamp
148
- * @param pendingEventTime
149
148
  * @protected
150
149
  */
151
- async processEvents(events, currentBlockNumber, currentBlockTimestamp, pendingEventTime) {
150
+ async processEvents(events, currentBlockNumber, currentBlockTimestamp) {
152
151
  const blockTimestampsCache = {};
153
152
  const getBlockTimestamp = async (blockNumber) => {
154
153
  if (blockNumber === currentBlockNumber)
@@ -188,7 +187,10 @@ class StarknetChainEventsBrowser {
188
187
  }
189
188
  if (parsedEvent == null)
190
189
  continue;
191
- const timestamp = event.blockNumber == null ? pendingEventTime : await getBlockTimestamp(event.blockNumber);
190
+ //We are not trusting pre-confs for events, so this shall never happen
191
+ if (event.blockNumber == null)
192
+ throw new Error("Event block number cannot be null!");
193
+ const timestamp = await getBlockTimestamp(event.blockNumber);
192
194
  parsedEvent.meta = {
193
195
  blockTime: timestamp,
194
196
  txId: event.txHash,
@@ -213,7 +215,7 @@ class StarknetChainEventsBrowser {
213
215
  }
214
216
  }
215
217
  if (events.length > 0) {
216
- await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now() / 1000));
218
+ await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp);
217
219
  lastTxHash = events[events.length - 1].txHash;
218
220
  }
219
221
  return lastTxHash;
@@ -231,14 +233,14 @@ class StarknetChainEventsBrowser {
231
233
  }
232
234
  }
233
235
  if (events.length > 0) {
234
- await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now() / 1000));
236
+ await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp);
235
237
  lastTxHash = events[events.length - 1].txHash;
236
238
  }
237
239
  return lastTxHash;
238
240
  }
239
241
  async checkEvents(lastBlockNumber, lastTxHashes) {
240
242
  lastTxHashes ?? (lastTxHashes = []);
241
- const currentBlock = await this.provider.getBlockWithTxHashes("latest");
243
+ const currentBlock = await this.provider.getBlockWithTxHashes(starknet_1.BlockTag.LATEST);
242
244
  const currentBlockNumber = currentBlock.block_number;
243
245
  lastTxHashes[0] = await this.checkEventsEcrowManager(lastTxHashes[0], lastBlockNumber, currentBlock);
244
246
  lastTxHashes[1] = await this.checkEventsSpvVaults(lastTxHashes[1], lastBlockNumber, currentBlock);
@@ -60,13 +60,20 @@ export declare class StarknetSwapInit extends StarknetSwapModule {
60
60
  */
61
61
  getSignatureExpiry(timeout: string): Promise<number>;
62
62
  /**
63
- * Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
63
+ * Checks whether signature is soft expired, compares the timestamp to the current "pre-confirmed" block timestamp
64
64
  *
65
65
  * @param timeout
66
66
  * @param preFetchData
67
67
  * @public
68
68
  */
69
- isSignatureExpired(timeout: string, preFetchData?: StarknetPreFetchVerification): Promise<boolean>;
69
+ isSignatureSoftExpired(timeout: string, preFetchData?: StarknetPreFetchVerification): Promise<boolean>;
70
+ /**
71
+ * Checks whether signature is expired for good, compares the timestamp to the current "latest" block timestamp
72
+ *
73
+ * @param timeout
74
+ * @public
75
+ */
76
+ isSignatureExpired(timeout: string): Promise<boolean>;
70
77
  /**
71
78
  * Creates init transaction with a valid signature from an LP
72
79
  *
@@ -50,7 +50,7 @@ class StarknetSwapInit extends StarknetSwapModule_1.StarknetSwapModule {
50
50
  }
51
51
  async preFetchForInitSignatureVerification() {
52
52
  return {
53
- pendingBlockTime: await this.root.Blocks.getBlockTime("pending")
53
+ pendingBlockTime: await this.root.Blocks.getBlockTime(starknet_1.BlockTag.PRE_CONFIRMED)
54
54
  };
55
55
  }
56
56
  /**
@@ -121,7 +121,7 @@ class StarknetSwapInit extends StarknetSwapModule_1.StarknetSwapModule {
121
121
  const isExpired = (timeoutBN - currentTimestamp) < BigInt(this.contract.authGracePeriod);
122
122
  if (isExpired)
123
123
  throw new base_1.SignatureVerificationError("Authorization expired!");
124
- if (await this.isSignatureExpired(timeout, preFetchData))
124
+ if (await this.isSignatureSoftExpired(timeout, preFetchData))
125
125
  throw new base_1.SignatureVerificationError("Authorization expired!");
126
126
  const valid = await this.root.Signatures.isValidSignature(signature, signer, Initialize, "Initialize", {
127
127
  "Swap hash": "0x" + swapData.getEscrowHash(),
@@ -167,18 +167,28 @@ class StarknetSwapInit extends StarknetSwapModule_1.StarknetSwapModule {
167
167
  return timeoutExpiryTime;
168
168
  }
169
169
  /**
170
- * Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
170
+ * Checks whether signature is soft expired, compares the timestamp to the current "pre-confirmed" block timestamp
171
171
  *
172
172
  * @param timeout
173
173
  * @param preFetchData
174
174
  * @public
175
175
  */
176
- async isSignatureExpired(timeout, preFetchData) {
176
+ async isSignatureSoftExpired(timeout, preFetchData) {
177
177
  if (preFetchData == null || preFetchData.pendingBlockTime == null) {
178
178
  preFetchData = await this.preFetchForInitSignatureVerification();
179
179
  }
180
180
  return preFetchData.pendingBlockTime > parseInt(timeout);
181
181
  }
182
+ /**
183
+ * Checks whether signature is expired for good, compares the timestamp to the current "latest" block timestamp
184
+ *
185
+ * @param timeout
186
+ * @public
187
+ */
188
+ async isSignatureExpired(timeout) {
189
+ const blockTime = await this.root.Blocks.getBlockTime(starknet_1.BlockTag.LATEST);
190
+ return blockTime > parseInt(timeout);
191
+ }
182
192
  /**
183
193
  * Creates init transaction with a valid signature from an LP
184
194
  *
@@ -12,7 +12,12 @@ class StarknetKeypairWallet extends starknet_1.Account {
12
12
  // Calculate future address of the account
13
13
  const OZaccountConstructorCallData = starknet_1.CallData.compile({ publicKey });
14
14
  const OZcontractAddress = starknet_1.hash.calculateContractAddressFromHash(publicKey, OZaccountClassHash, OZaccountConstructorCallData, 0);
15
- super(provider, OZcontractAddress, privateKey, "1");
15
+ super({
16
+ provider,
17
+ address: OZcontractAddress,
18
+ signer: privateKey,
19
+ cairoVersion: "1"
20
+ });
16
21
  this.publicKey = publicKey;
17
22
  }
18
23
  getDeploymentData() {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StarknetSigner = void 0;
4
+ const starknet_1 = require("starknet");
4
5
  const Utils_1 = require("../../utils/Utils");
5
6
  class StarknetSigner {
6
7
  constructor(account) {
@@ -19,7 +20,7 @@ class StarknetSigner {
19
20
  //TODO: Introduce proper nonce management!
20
21
  async getNonce() {
21
22
  try {
22
- return BigInt(await this.account.getNonceForAddress(this.getAddress(), "pending"));
23
+ return BigInt(await this.account.getNonceForAddress(this.getAddress(), starknet_1.BlockTag.PRE_CONFIRMED));
23
24
  }
24
25
  catch (e) {
25
26
  if (e.message != null && e.message.includes("20: Contract not found")) {
@@ -117,7 +117,6 @@ function calculateHash(tx) {
117
117
  return tx.txId = starknet_1.hash.calculateDeployAccountTransactionHash({
118
118
  contractAddress: tx.tx.contractAddress,
119
119
  classHash: tx.signed.classHash,
120
- constructorCalldata: deployAccountData,
121
120
  compiledConstructorCalldata: deployAccountData,
122
121
  salt: tx.signed.addressSalt,
123
122
  ...commonData
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@atomiqlabs/chain-starknet",
3
- "version": "4.0.0-dev.11",
3
+ "version": "4.0.0-dev.13",
4
4
  "description": "Starknet specific base implementation",
5
5
  "main": "./dist/index.js",
6
- "types:": "./dist/index.d.ts",
6
+ "types": "./dist/index.d.ts",
7
7
  "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build",
8
10
  "test": "echo \"Error: no test specified\" && exit 1"
9
11
  },
10
12
  "files": [
@@ -21,6 +23,10 @@
21
23
  ],
22
24
  "author": "adambor",
23
25
  "license": "ISC",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/atomiqlabs/atomiq-chain-starknet.git"
29
+ },
24
30
  "dependencies": {
25
31
  "@atomiqlabs/base": "^10.0.0-dev.9",
26
32
  "@noble/hashes": "^1.7.1",
@@ -29,7 +35,7 @@
29
35
  "buffer": "6.0.3"
30
36
  },
31
37
  "peerDependencies": {
32
- "starknet": "^7.5.0"
38
+ "starknet": "^8.5.0"
33
39
  },
34
40
  "devDependencies": {
35
41
  "typescript": "4.9.5"
@@ -1,6 +1,7 @@
1
1
  import {StarknetModule} from "../StarknetModule";
2
2
 
3
- export type StarknetBlockTag = "pending" | "latest";
3
+ // https://github.com/starkware-libs/starknet-specs/blob/c2e93098b9c2ca0423b7f4d15b201f52f22d8c36/api/starknet_api_openrpc.json#L1234
4
+ export type StarknetBlockTag = "pre_confirmed" | "latest";
4
5
 
5
6
  export class StarknetBlocks extends StarknetModule {
6
7
 
@@ -29,8 +29,8 @@ export class StarknetEvents extends StarknetModule {
29
29
  while(result==null || result?.continuation_token!=null) {
30
30
  result = await this.root.provider.getEvents({
31
31
  address: contract,
32
- from_block: startBlock==null ? "pending" : {block_number: startBlock},
33
- to_block: endBlock==null ? "pending" : {block_number: endBlock},
32
+ from_block: startBlock==null ? "latest" : {block_number: startBlock},
33
+ to_block: endBlock==null ? "latest" : {block_number: endBlock},
34
34
  keys,
35
35
  chunk_size: this.EVENTS_LIMIT,
36
36
  continuation_token: result?.continuation_token
@@ -141,11 +141,11 @@ export class StarknetFees {
141
141
  return {
142
142
  version: "0x3" as const,
143
143
  resourceBounds: {
144
- l1_gas: {max_amount: toHex(gas.l1Gas, 16), max_price_per_unit: toHex(BigInt(l1GasCostStr), 16)},
145
- l2_gas: {max_amount: toHex(gas.l2Gas, 16), max_price_per_unit: toHex(BigInt(l2GasCostStr), 16)},
146
- l1_data_gas: {max_amount: toHex(gas.l1DataGas, 16), max_price_per_unit: toHex(BigInt(l1DataGasCostStr), 16)}
144
+ l1_gas: {max_amount: BigInt(gas.l1Gas), max_price_per_unit: BigInt(l1GasCostStr)},
145
+ l2_gas: {max_amount: BigInt(gas.l2Gas), max_price_per_unit: BigInt(l2GasCostStr)},
146
+ l1_data_gas: {max_amount: BigInt(gas.l1DataGas), max_price_per_unit: BigInt(l1DataGasCostStr)}
147
147
  },
148
- tip: "0x0",
148
+ tip: 0n,
149
149
  paymasterData: [],
150
150
  nonceDataAvailabilityMode: this.nonceDA,
151
151
  feeDataAvailabilityMode: this.feeDA
@@ -17,7 +17,11 @@ export class StarknetTokens extends StarknetModule {
17
17
  };
18
18
 
19
19
  private getContract(address: string) {
20
- return new Contract(ERC20Abi, address, this.root.provider).typedv2(ERC20Abi);
20
+ return new Contract({
21
+ abi: ERC20Abi,
22
+ address: address,
23
+ providerOrAccount: this.root.provider
24
+ }).typedv2(ERC20Abi);
21
25
  }
22
26
 
23
27
  /**
@@ -3,7 +3,9 @@ import {
3
3
  Call,
4
4
  DeployAccountContractPayload, DeployAccountContractTransaction,
5
5
  Invocation, InvocationsSignerDetails,
6
- BigNumberish
6
+ BigNumberish,
7
+ ETransactionStatus,
8
+ ETransactionExecutionStatus
7
9
  } from "starknet";
8
10
  import {StarknetSigner} from "../../wallet/StarknetSigner";
9
11
  import {calculateHash, timeoutPromise, toBigInt, toHex, tryWithRetries} from "../../../utils/Utils";
@@ -21,6 +23,8 @@ export type StarknetTx = ({
21
23
  txId?: string
22
24
  };
23
25
 
26
+ const MAX_UNCONFIRMED_TXS = 25;
27
+
24
28
  export class StarknetTransactions extends StarknetModule {
25
29
 
26
30
  private readonly latestConfirmedNonces: {[address: string]: bigint} = {};
@@ -178,13 +182,17 @@ export class StarknetTransactions extends StarknetModule {
178
182
 
179
183
  const txIds: string[] = [];
180
184
  if(parallel) {
181
- const promises: Promise<void>[] = [];
185
+ let promises: Promise<void>[] = [];
182
186
  for(let i=0;i<txs.length;i++) {
183
187
  const signedTx = txs[i];
184
188
  const txId = await this.sendSignedTransaction(signedTx, onBeforePublish, signer);
185
189
  if(waitForConfirmation) promises.push(this.confirmTransaction(signedTx, abortSignal));
186
190
  txIds.push(txId);
187
191
  this.logger.debug("sendAndConfirm(): transaction sent ("+(i+1)+"/"+txs.length+"): "+signedTx.txId);
192
+ if(promises.length >= MAX_UNCONFIRMED_TXS) {
193
+ await Promise.all(promises);
194
+ promises = [];
195
+ }
188
196
  }
189
197
  if(promises.length>0) await Promise.all(promises);
190
198
  } else {
@@ -247,9 +255,9 @@ export class StarknetTransactions extends StarknetModule {
247
255
  throw e;
248
256
  });
249
257
  if(status==null) return "not_found";
250
- if(status.finality_status==="RECEIVED") return "pending";
251
- if(status.finality_status==="REJECTED") return "rejected";
252
- if(status.execution_status==="SUCCEEDED"){
258
+ if(status.finality_status===ETransactionStatus.RECEIVED) return "pending";
259
+ if(status.finality_status===ETransactionStatus.REJECTED) return "rejected";
260
+ if(status.execution_status===ETransactionExecutionStatus.SUCCEEDED){
253
261
  return "success";
254
262
  }
255
263
  return "reverted";
@@ -19,7 +19,11 @@ export class StarknetContractBase<T extends Abi> {
19
19
  contractAbi: T
20
20
  ) {
21
21
  this.Chain = chainInterface;
22
- this.contract = new Contract(contractAbi, contractAddress, chainInterface.provider).typedv2(contractAbi);
22
+ this.contract = new Contract({
23
+ abi: contractAbi,
24
+ address: contractAddress,
25
+ providerOrAccount: chainInterface.provider
26
+ }).typedv2(contractAbi);
23
27
  this.Events = new StarknetContractEvents(chainInterface, this, contractAbi);
24
28
  }
25
29
 
@@ -1,7 +1,7 @@
1
1
  import {Abi} from "abi-wan-kanabi";
2
2
  import {EventToPrimitiveType, ExtractAbiEventNames} from "abi-wan-kanabi/dist/kanabi";
3
3
  import {StarknetEvent, StarknetEvents} from "../../chain/modules/StarknetEvents";
4
- import {CallData, events, hash} from "starknet";
4
+ import {CallData, events, hash, createAbiParser} from "starknet";
5
5
  import {StarknetContractBase} from "../StarknetContractBase";
6
6
  import {toHex} from "../../../utils/Utils";
7
7
  import {StarknetChainInterface} from "../../chain/StarknetChainInterface";
@@ -32,7 +32,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
32
32
  const abiStructs = CallData.getAbiStruct(this.abi);
33
33
  const abiEnums = CallData.getAbiEnum(this.abi);
34
34
 
35
- const result = events.parseEvents(blockEvents, abiEvents, abiStructs, abiEnums);
35
+ const result = events.parseEvents(blockEvents, abiEvents, abiStructs, abiEnums, createAbiParser(this.abi));
36
36
  if(result.length!==blockEvents.length) throw new Error("Invalid event detected, please check provided ABI");
37
37
  return result.map((value, index) => {
38
38
  const starknetEvent = blockEvents[index];
@@ -17,7 +17,7 @@ import {
17
17
  toHex
18
18
  } from "../../utils/Utils";
19
19
  import {StarknetSwapContract} from "../swaps/StarknetSwapContract";
20
- import {BigNumberish, hash, Provider} from "starknet";
20
+ import {BigNumberish, BlockTag, hash, Provider} from "starknet";
21
21
  import {StarknetAbiEvent} from "../contract/modules/StarknetContractEvents";
22
22
  import {EscrowManagerAbiType} from "../swaps/EscrowManagerAbi";
23
23
  import {ExtractAbiFunctionNames} from "abi-wan-kanabi/dist/kanabi";
@@ -229,7 +229,6 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
229
229
  * @param events
230
230
  * @param currentBlockNumber
231
231
  * @param currentBlockTimestamp
232
- * @param pendingEventTime
233
232
  * @protected
234
233
  */
235
234
  protected async processEvents(
@@ -241,8 +240,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
241
240
  "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"
242
241
  >)[],
243
242
  currentBlockNumber: number,
244
- currentBlockTimestamp: number,
245
- pendingEventTime: number
243
+ currentBlockTimestamp: number
246
244
  ) {
247
245
  const blockTimestampsCache: {[blockNumber: string]: number} = {};
248
246
  const getBlockTimestamp: (blockNumber: number) => Promise<number> = async (blockNumber: number)=> {
@@ -283,7 +281,9 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
283
281
  break;
284
282
  }
285
283
  if(parsedEvent==null) continue;
286
- const timestamp = event.blockNumber==null ? pendingEventTime : await getBlockTimestamp(event.blockNumber);
284
+ //We are not trusting pre-confs for events, so this shall never happen
285
+ if(event.blockNumber==null) throw new Error("Event block number cannot be null!");
286
+ const timestamp = await getBlockTimestamp(event.blockNumber);
287
287
  parsedEvent.meta = {
288
288
  blockTime: timestamp,
289
289
  txId: event.txHash,
@@ -315,7 +315,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
315
315
  }
316
316
  }
317
317
  if(events.length>0) {
318
- await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now()/1000));
318
+ await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp);
319
319
  lastTxHash = events[events.length-1].txHash;
320
320
  }
321
321
  return lastTxHash;
@@ -339,7 +339,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
339
339
  }
340
340
  }
341
341
  if(events.length>0) {
342
- await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now()/1000));
342
+ await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp);
343
343
  lastTxHash = events[events.length-1].txHash;
344
344
  }
345
345
  return lastTxHash;
@@ -348,8 +348,8 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
348
348
  protected async checkEvents(lastBlockNumber: number, lastTxHashes: string[]): Promise<{txHashes: string[], blockNumber: number}> {
349
349
  lastTxHashes ??= [];
350
350
 
351
- const currentBlock = await this.provider.getBlockWithTxHashes("latest");
352
- const currentBlockNumber: number = (currentBlock as any).block_number;
351
+ const currentBlock = await this.provider.getBlockWithTxHashes(BlockTag.LATEST);
352
+ const currentBlockNumber: number = currentBlock.block_number;
353
353
 
354
354
  lastTxHashes[0] = await this.checkEventsEcrowManager(lastTxHashes[0], lastBlockNumber, currentBlock as any);
355
355
  lastTxHashes[1] = await this.checkEventsSpvVaults(lastTxHashes[1], lastBlockNumber, currentBlock as any);
@@ -4,7 +4,7 @@ import {Buffer} from "buffer";
4
4
  import {StarknetSwapData} from "../StarknetSwapData";
5
5
  import {StarknetAction} from "../../chain/StarknetAction";
6
6
  import {StarknetSwapModule} from "../StarknetSwapModule";
7
- import {BigNumberish, cairo} from "starknet";
7
+ import {BigNumberish, cairo, BlockTag} from "starknet";
8
8
  import {StarknetSigner} from "../../wallet/StarknetSigner";
9
9
  import {StarknetFees} from "../../chain/modules/StarknetFees";
10
10
  import {StarknetTx} from "../../chain/modules/StarknetTransactions";
@@ -74,7 +74,7 @@ export class StarknetSwapInit extends StarknetSwapModule {
74
74
 
75
75
  public async preFetchForInitSignatureVerification(): Promise<StarknetPreFetchVerification> {
76
76
  return {
77
- pendingBlockTime: await this.root.Blocks.getBlockTime("pending")
77
+ pendingBlockTime: await this.root.Blocks.getBlockTime(BlockTag.PRE_CONFIRMED)
78
78
  };
79
79
  }
80
80
 
@@ -162,7 +162,7 @@ export class StarknetSwapInit extends StarknetSwapModule {
162
162
  const timeoutBN = BigInt(timeout);
163
163
  const isExpired = (timeoutBN - currentTimestamp) < BigInt(this.contract.authGracePeriod);
164
164
  if (isExpired) throw new SignatureVerificationError("Authorization expired!");
165
- if(await this.isSignatureExpired(timeout, preFetchData)) throw new SignatureVerificationError("Authorization expired!");
165
+ if(await this.isSignatureSoftExpired(timeout, preFetchData)) throw new SignatureVerificationError("Authorization expired!");
166
166
 
167
167
  const valid = await this.root.Signatures.isValidSignature(signature, signer, Initialize, "Initialize", {
168
168
  "Swap hash": "0x"+swapData.getEscrowHash(),
@@ -214,13 +214,13 @@ export class StarknetSwapInit extends StarknetSwapModule {
214
214
  }
215
215
 
216
216
  /**
217
- * Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
217
+ * Checks whether signature is soft expired, compares the timestamp to the current "pre-confirmed" block timestamp
218
218
  *
219
219
  * @param timeout
220
220
  * @param preFetchData
221
221
  * @public
222
222
  */
223
- public async isSignatureExpired(
223
+ public async isSignatureSoftExpired(
224
224
  timeout: string,
225
225
  preFetchData?: StarknetPreFetchVerification
226
226
  ): Promise<boolean> {
@@ -230,6 +230,19 @@ export class StarknetSwapInit extends StarknetSwapModule {
230
230
  return preFetchData.pendingBlockTime > parseInt(timeout);
231
231
  }
232
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
+
233
246
  /**
234
247
  * Creates init transaction with a valid signature from an LP
235
248
  *
@@ -19,7 +19,12 @@ export class StarknetKeypairWallet extends Account {
19
19
  OZaccountConstructorCallData,
20
20
  0
21
21
  );
22
- super(provider, OZcontractAddress, privateKey, "1");
22
+ super({
23
+ provider,
24
+ address: OZcontractAddress,
25
+ signer: privateKey,
26
+ cairoVersion: "1"
27
+ });
23
28
  this.publicKey = publicKey;
24
29
  }
25
30
 
@@ -1,5 +1,5 @@
1
1
  import {AbstractSigner} from "@atomiqlabs/base";
2
- import {Account, DeployAccountContractPayload} from "starknet";
2
+ import {Account, DeployAccountContractPayload, BlockTag} from "starknet";
3
3
  import {toHex} from "../../utils/Utils";
4
4
 
5
5
  export class StarknetSigner implements AbstractSigner {
@@ -27,7 +27,7 @@ export class StarknetSigner implements AbstractSigner {
27
27
  //TODO: Introduce proper nonce management!
28
28
  async getNonce(): Promise<bigint> {
29
29
  try {
30
- return BigInt(await this.account.getNonceForAddress(this.getAddress(), "pending"));
30
+ return BigInt(await this.account.getNonceForAddress(this.getAddress(), BlockTag.PRE_CONFIRMED));
31
31
  } catch (e) {
32
32
  if(e.message!=null && e.message.includes("20: Contract not found")) {
33
33
  return BigInt(0);
@@ -120,7 +120,6 @@ export function calculateHash(tx: StarknetTx): string {
120
120
  return tx.txId = hash.calculateDeployAccountTransactionHash({
121
121
  contractAddress: tx.tx.contractAddress,
122
122
  classHash: tx.signed.classHash,
123
- constructorCalldata: deployAccountData,
124
123
  compiledConstructorCalldata: deployAccountData,
125
124
  salt: tx.signed.addressSalt,
126
125
  ...commonData