starknet 4.5.0 → 4.7.0

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 (88) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +3 -1
  3. package/__tests__/account.test.ts +2 -5
  4. package/__tests__/contract.test.ts +0 -1
  5. package/__tests__/defaultProvider.test.ts +16 -10
  6. package/__tests__/rpcProvider.test.ts +107 -12
  7. package/__tests__/sequencerProvider.test.ts +10 -8
  8. package/__tests__/utils/ellipticalCurve.test.ts +7 -8
  9. package/__tests__/utils/utils.test.ts +17 -0
  10. package/account/default.d.ts +3 -2
  11. package/account/default.js +22 -29
  12. package/account/interface.d.ts +2 -1
  13. package/contract/contractFactory.d.ts +1 -2
  14. package/contract/default.d.ts +2 -2
  15. package/contract/default.js +7 -3
  16. package/dist/account/default.d.ts +3 -2
  17. package/dist/account/default.js +22 -29
  18. package/dist/account/interface.d.ts +2 -1
  19. package/dist/contract/contractFactory.d.ts +1 -2
  20. package/dist/contract/default.d.ts +2 -2
  21. package/dist/contract/default.js +7 -3
  22. package/dist/provider/default.d.ts +4 -3
  23. package/dist/provider/default.js +9 -3
  24. package/dist/provider/interface.d.ts +10 -3
  25. package/dist/provider/rpc.d.ts +24 -12
  26. package/dist/provider/rpc.js +167 -105
  27. package/dist/provider/sequencer.d.ts +4 -3
  28. package/dist/provider/sequencer.js +16 -7
  29. package/dist/provider/utils.d.ts +11 -35
  30. package/dist/provider/utils.js +52 -63
  31. package/dist/signer/default.d.ts +2 -2
  32. package/dist/signer/default.js +2 -2
  33. package/dist/signer/interface.d.ts +2 -2
  34. package/dist/types/api/openrpc.d.ts +395 -45
  35. package/dist/types/api/openrpc.js +21 -3
  36. package/dist/types/api/rpc.d.ts +34 -191
  37. package/dist/types/api/sequencer.d.ts +15 -4
  38. package/dist/types/lib.d.ts +10 -4
  39. package/dist/types/provider.d.ts +3 -2
  40. package/dist/utils/hash.d.ts +2 -2
  41. package/dist/utils/hash.js +5 -5
  42. package/dist/utils/responseParser/rpc.d.ts +6 -6
  43. package/dist/utils/responseParser/rpc.js +3 -39
  44. package/package.json +1 -1
  45. package/provider/default.d.ts +4 -3
  46. package/provider/default.js +9 -3
  47. package/provider/interface.d.ts +10 -3
  48. package/provider/rpc.d.ts +24 -12
  49. package/provider/rpc.js +167 -105
  50. package/provider/sequencer.d.ts +4 -3
  51. package/provider/sequencer.js +16 -7
  52. package/provider/utils.d.ts +11 -35
  53. package/provider/utils.js +52 -63
  54. package/signer/default.d.ts +2 -2
  55. package/signer/default.js +2 -2
  56. package/signer/interface.d.ts +2 -2
  57. package/src/account/default.ts +21 -20
  58. package/src/account/interface.ts +2 -1
  59. package/src/contract/contractFactory.ts +1 -2
  60. package/src/contract/default.ts +16 -8
  61. package/src/provider/default.ts +12 -5
  62. package/src/provider/interface.ts +15 -4
  63. package/src/provider/rpc.ts +152 -102
  64. package/src/provider/sequencer.ts +19 -10
  65. package/src/provider/utils.ts +43 -56
  66. package/src/signer/default.ts +8 -8
  67. package/src/signer/interface.ts +2 -2
  68. package/src/types/api/openrpc.ts +378 -53
  69. package/src/types/api/rpc.ts +33 -211
  70. package/src/types/api/sequencer.ts +17 -4
  71. package/src/types/lib.ts +7 -5
  72. package/src/types/provider.ts +3 -2
  73. package/src/utils/hash.ts +7 -6
  74. package/src/utils/responseParser/rpc.ts +13 -27
  75. package/types/api/openrpc.d.ts +395 -45
  76. package/types/api/openrpc.js +21 -3
  77. package/types/api/rpc.d.ts +34 -191
  78. package/types/api/sequencer.d.ts +15 -4
  79. package/types/lib.d.ts +10 -4
  80. package/types/provider.d.ts +3 -2
  81. package/utils/hash.d.ts +2 -2
  82. package/utils/hash.js +5 -5
  83. package/utils/responseParser/rpc.d.ts +6 -6
  84. package/utils/responseParser/rpc.js +3 -39
  85. package/www/docs/API/account.md +3 -3
  86. package/www/docs/API/contract.md +2 -2
  87. package/www/docs/API/provider.md +6 -0
  88. package/www/docs/API/utils.md +2 -2
@@ -12,7 +12,7 @@ import {
12
12
  GetTransactionReceiptResponse,
13
13
  GetTransactionResponse,
14
14
  Invocation,
15
- InvocationsDetails,
15
+ InvocationsDetailsWithNonce,
16
16
  InvokeFunctionResponse,
17
17
  } from '../types';
18
18
  import { RPC } from '../types/api';
@@ -29,90 +29,126 @@ import { parseCalldata, parseContract, wait } from '../utils/provider';
29
29
  import { RPCResponseParser } from '../utils/responseParser/rpc';
30
30
  import { randomAddress } from '../utils/stark';
31
31
  import { ProviderInterface } from './interface';
32
- import { BlockIdentifier, BlockIdentifierClass } from './utils';
32
+ import { Block, BlockIdentifier } from './utils';
33
33
 
34
- export type RpcProviderOptions = { nodeUrl: string };
34
+ export type RpcProviderOptions = {
35
+ nodeUrl: string;
36
+ retries?: number;
37
+ };
35
38
 
36
39
  export class RpcProvider implements ProviderInterface {
37
40
  public nodeUrl: string;
38
41
 
42
+ // from interface
39
43
  public chainId!: StarknetChainId;
40
44
 
41
45
  private responseParser = new RPCResponseParser();
42
46
 
47
+ private retries: number;
48
+
43
49
  constructor(optionsOrProvider: RpcProviderOptions) {
44
- const { nodeUrl } = optionsOrProvider;
50
+ const { nodeUrl, retries } = optionsOrProvider;
45
51
  this.nodeUrl = nodeUrl;
52
+ this.retries = retries || 200;
46
53
 
47
54
  this.getChainId().then((chainId) => {
48
55
  this.chainId = chainId;
49
56
  });
50
57
  }
51
58
 
59
+ public fetch(method: any, params: any): Promise<any> {
60
+ return fetch(this.nodeUrl, {
61
+ method: 'POST',
62
+ body: stringify({ method, jsonrpc: '2.0', params, id: 0 }),
63
+ headers: { 'Content-Type': 'application/json' },
64
+ });
65
+ }
66
+
67
+ protected errorHandler(error: any) {
68
+ if (error) {
69
+ const { code, message } = error;
70
+ throw new Error(`${code}: ${message}`);
71
+ }
72
+ }
73
+
52
74
  protected async fetchEndpoint<T extends keyof RPC.Methods>(
53
75
  method: T,
54
- request?: RPC.Methods[T]['REQUEST']
55
- ): Promise<RPC.Methods[T]['RESPONSE']> {
56
- const requestData = {
57
- method,
58
- jsonrpc: '2.0',
59
- params: request,
60
- id: 0,
61
- };
62
-
76
+ params?: RPC.Methods[T]['params']
77
+ ): Promise<RPC.Methods[T]['result']> {
63
78
  try {
64
- const rawResult = await fetch(this.nodeUrl, {
65
- method: 'POST',
66
- body: stringify(requestData),
67
- headers: {
68
- 'Content-Type': 'application/json',
69
- },
70
- });
79
+ const rawResult = await this.fetch(method, params);
71
80
  const { error, result } = await rawResult.json();
72
- if (error) {
73
- const { code, message } = error;
74
- throw new Error(`${code}: ${message}`);
75
- } else {
76
- return result as RPC.Methods[T]['RESPONSE'];
77
- }
81
+ this.errorHandler(error);
82
+ return result as RPC.Methods[T]['result'];
78
83
  } catch (error: any) {
79
- const data = error?.response?.data;
80
- if (data?.message) {
81
- throw new Error(`${data.code}: ${data.message}`);
82
- }
84
+ this.errorHandler(error?.response?.data);
83
85
  throw error;
84
86
  }
85
87
  }
86
88
 
87
- public async getChainId(): Promise<StarknetChainId> {
89
+ // Methods from Interface
90
+ public async getChainId(): Promise<any> {
88
91
  return this.fetchEndpoint('starknet_chainId');
89
92
  }
90
93
 
91
- // Common Interface
94
+ // Methods from Interface
92
95
  public async getBlock(blockIdentifier: BlockIdentifier = 'pending'): Promise<GetBlockResponse> {
93
96
  return this.getBlockWithTxHashes(blockIdentifier).then(
94
97
  this.responseParser.parseGetBlockResponse
95
98
  );
96
99
  }
97
100
 
101
+ public async getBlockHashAndNumber(): Promise<RPC.BlockHashAndNumber> {
102
+ return this.fetchEndpoint('starknet_blockHashAndNumber');
103
+ }
104
+
98
105
  public async getBlockWithTxHashes(
99
106
  blockIdentifier: BlockIdentifier = 'pending'
100
107
  ): Promise<RPC.GetBlockWithTxHashesResponse> {
101
- const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
102
- return this.fetchEndpoint('starknet_getBlockWithTxHashes', [
103
- blockIdentifierGetter.getIdentifier(),
104
- ]);
108
+ const block_id = new Block(blockIdentifier).identifier;
109
+ return this.fetchEndpoint('starknet_getBlockWithTxHashes', { block_id });
105
110
  }
106
111
 
107
112
  public async getBlockWithTxs(
108
113
  blockIdentifier: BlockIdentifier = 'pending'
109
114
  ): Promise<RPC.GetBlockWithTxs> {
110
- const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
111
- return this.fetchEndpoint('starknet_getBlockWithTxs', [blockIdentifierGetter.getIdentifier()]);
115
+ const block_id = new Block(blockIdentifier).identifier;
116
+ return this.fetchEndpoint('starknet_getBlockWithTxs', { block_id });
117
+ }
118
+
119
+ public async getClassHashAt(
120
+ blockIdentifier: BlockIdentifier,
121
+ contractAddress: RPC.ContractAddress
122
+ ): Promise<RPC.Felt> {
123
+ const block_id = new Block(blockIdentifier).identifier;
124
+ return this.fetchEndpoint('starknet_getClassHashAt', {
125
+ block_id,
126
+ contract_address: contractAddress,
127
+ });
112
128
  }
113
129
 
114
- public async getNonce(contractAddress: string): Promise<any> {
115
- return this.fetchEndpoint('starknet_getNonce', [contractAddress]);
130
+ public async getNonce(
131
+ contractAddress: string,
132
+ blockIdentifier: BlockIdentifier = 'pending'
133
+ ): Promise<RPC.Nonce> {
134
+ const block_id = new Block(blockIdentifier).identifier;
135
+ return this.fetchEndpoint('starknet_getNonce', {
136
+ contract_address: contractAddress,
137
+ block_id,
138
+ });
139
+ }
140
+
141
+ public async getPendingTransactions(): Promise<RPC.PendingTransactions> {
142
+ return this.fetchEndpoint('starknet_pendingTransactions');
143
+ }
144
+
145
+ public async getProtocolVersion(): Promise<Error> {
146
+ throw new Error('Pathfinder does not implement this rpc 0.1.0 method');
147
+ }
148
+
149
+ public async getStateUpdate(blockIdentifier: BlockIdentifier): Promise<RPC.StateUpdate> {
150
+ const block_id = new Block(blockIdentifier).identifier;
151
+ return this.fetchEndpoint('starknet_getStateUpdate', { block_id });
116
152
  }
117
153
 
118
154
  public async getStorageAt(
@@ -121,61 +157,75 @@ export class RpcProvider implements ProviderInterface {
121
157
  blockIdentifier: BlockIdentifier = 'pending'
122
158
  ): Promise<BigNumberish> {
123
159
  const parsedKey = toHex(toBN(key));
124
- const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
125
- return this.fetchEndpoint('starknet_getStorageAt', [
126
- contractAddress,
127
- parsedKey,
128
- blockIdentifierGetter.getIdentifier(),
129
- ]);
160
+ const block_id = new Block(blockIdentifier).identifier;
161
+ return this.fetchEndpoint('starknet_getStorageAt', {
162
+ contract_address: contractAddress,
163
+ key: parsedKey,
164
+ block_id,
165
+ });
130
166
  }
131
167
 
132
- // common interface
133
- public async getTransaction(txHash: BigNumberish): Promise<GetTransactionResponse> {
168
+ // Methods from Interface
169
+ public async getTransaction(txHash: string): Promise<GetTransactionResponse> {
134
170
  return this.getTransactionByHash(txHash).then(this.responseParser.parseGetTransactionResponse);
135
171
  }
136
172
 
137
- public async getTransactionByHash(
138
- txHash: BigNumberish
139
- ): Promise<RPC.GetTransactionByHashResponse> {
140
- return this.fetchEndpoint('starknet_getTransactionByHash', [txHash]);
173
+ public async getTransactionByHash(txHash: string): Promise<RPC.GetTransactionByHashResponse> {
174
+ return this.fetchEndpoint('starknet_getTransactionByHash', { transaction_hash: txHash });
141
175
  }
142
176
 
143
177
  public async getTransactionByBlockIdAndIndex(
144
178
  blockIdentifier: BlockIdentifier,
145
179
  index: number
146
180
  ): Promise<RPC.GetTransactionByBlockIdAndIndex> {
147
- return this.fetchEndpoint('starknet_getTransactionByHash', [blockIdentifier, index]);
181
+ const block_id = new Block(blockIdentifier).identifier;
182
+ return this.fetchEndpoint('starknet_getTransactionByBlockIdAndIndex', { block_id, index });
148
183
  }
149
184
 
150
- public async getTransactionReceipt(txHash: BigNumberish): Promise<GetTransactionReceiptResponse> {
151
- return this.fetchEndpoint('starknet_getTransactionReceipt', [txHash]).then(
185
+ public async getTransactionReceipt(txHash: string): Promise<GetTransactionReceiptResponse> {
186
+ return this.fetchEndpoint('starknet_getTransactionReceipt', { transaction_hash: txHash }).then(
152
187
  this.responseParser.parseGetTransactionReceiptResponse
153
188
  );
154
189
  }
155
190
 
156
- public async getClassAt(contractAddress: string, blockIdentifier: BlockIdentifier): Promise<any> {
157
- const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
158
- return this.fetchEndpoint('starknet_getClassAt', [
159
- blockIdentifierGetter.getIdentifier(),
160
- contractAddress,
161
- ]);
191
+ public async getClass(classHash: RPC.Felt): Promise<RPC.ContractClass> {
192
+ return this.fetchEndpoint('starknet_getClass', { class_hash: classHash });
193
+ }
194
+
195
+ public async getClassAt(
196
+ contractAddress: string,
197
+ blockIdentifier: BlockIdentifier
198
+ ): Promise<RPC.ContractClass> {
199
+ const block_id = new Block(blockIdentifier).identifier;
200
+ return this.fetchEndpoint('starknet_getClassAt', {
201
+ block_id,
202
+ contract_address: contractAddress,
203
+ });
204
+ }
205
+
206
+ public async getCode(
207
+ _contractAddress: string,
208
+ _blockIdentifier?: BlockIdentifier
209
+ ): Promise<GetCodeResponse> {
210
+ throw new Error('RPC 0.1.0 does not implement getCode function');
162
211
  }
163
212
 
164
213
  public async getEstimateFee(
165
214
  invocation: Invocation,
166
- blockIdentifier: BlockIdentifier = 'pending',
167
- invocationDetails: InvocationsDetails = {}
215
+ invocationDetails: InvocationsDetailsWithNonce,
216
+ blockIdentifier: BlockIdentifier = 'pending'
168
217
  ): Promise<EstimateFeeResponse> {
169
- return this.fetchEndpoint('starknet_estimateFee', [
170
- {
218
+ const block_id = new Block(blockIdentifier).identifier;
219
+ return this.fetchEndpoint('starknet_estimateFee', {
220
+ request: {
171
221
  contract_address: invocation.contractAddress,
172
- entry_point_selector: getSelectorFromName(invocation.entrypoint),
173
222
  calldata: parseCalldata(invocation.calldata),
174
223
  signature: bigNumberishArrayToHexadecimalStringArray(invocation.signature || []),
175
224
  version: toHex(toBN(invocationDetails?.version || 0)),
225
+ max_fee: toHex(toBN(invocationDetails?.maxFee || 0)),
176
226
  },
177
- blockIdentifier,
178
- ]).then(this.responseParser.parseFeeEstimateResponse);
227
+ block_id,
228
+ }).then(this.responseParser.parseFeeEstimateResponse);
179
229
  }
180
230
 
181
231
  public async declareContract({
@@ -184,14 +234,14 @@ export class RpcProvider implements ProviderInterface {
184
234
  }: DeclareContractPayload): Promise<DeclareContractResponse> {
185
235
  const contractDefinition = parseContract(contract);
186
236
 
187
- return this.fetchEndpoint('starknet_addDeclareTransaction', [
188
- {
237
+ return this.fetchEndpoint('starknet_addDeclareTransaction', {
238
+ contract_class: {
189
239
  program: contractDefinition.program,
190
240
  entry_points_by_type: contractDefinition.entry_points_by_type,
191
241
  abi: contractDefinition.abi, // rpc 2.0
192
242
  },
193
- toHex(toBN(version || 0)),
194
- ]).then(this.responseParser.parseDeclareContractResponse);
243
+ version: toHex(toBN(version || 0)),
244
+ });
195
245
  }
196
246
 
197
247
  public async deployContract({
@@ -201,59 +251,61 @@ export class RpcProvider implements ProviderInterface {
201
251
  }: DeployContractPayload): Promise<DeployContractResponse> {
202
252
  const contractDefinition = parseContract(contract);
203
253
 
204
- return this.fetchEndpoint('starknet_addDeployTransaction', [
205
- addressSalt ?? randomAddress(),
206
- bigNumberishArrayToHexadecimalStringArray(constructorCalldata ?? []),
207
- {
254
+ return this.fetchEndpoint('starknet_addDeployTransaction', {
255
+ contract_address_salt: addressSalt ?? randomAddress(),
256
+ constructor_calldata: bigNumberishArrayToHexadecimalStringArray(constructorCalldata ?? []),
257
+ contract_definition: {
208
258
  program: contractDefinition.program,
209
259
  entry_points_by_type: contractDefinition.entry_points_by_type,
210
260
  abi: contractDefinition.abi, // rpc 2.0
211
261
  },
212
- ]).then(this.responseParser.parseDeployContractResponse);
262
+ });
213
263
  }
214
264
 
215
265
  public async invokeFunction(
216
266
  functionInvocation: Invocation,
217
- details: InvocationsDetails
267
+ details: InvocationsDetailsWithNonce
218
268
  ): Promise<InvokeFunctionResponse> {
219
- return this.fetchEndpoint('starknet_addInvokeTransaction', [
220
- {
269
+ return this.fetchEndpoint('starknet_addInvokeTransaction', {
270
+ function_invocation: {
221
271
  contract_address: functionInvocation.contractAddress,
222
- entry_point_selector: getSelectorFromName(functionInvocation.entrypoint),
223
272
  calldata: parseCalldata(functionInvocation.calldata),
224
273
  },
225
- bigNumberishArrayToHexadecimalStringArray(functionInvocation.signature || []),
226
- toHex(toBN(details.maxFee || 0)),
227
- toHex(toBN(details.version || 0)),
228
- ]).then(this.responseParser.parseInvokeFunctionResponse);
274
+ signature: bigNumberishArrayToHexadecimalStringArray(functionInvocation.signature || []),
275
+ max_fee: toHex(toBN(details.maxFee || 0)),
276
+ version: toHex(toBN(details.version || 0)),
277
+ });
229
278
  }
230
279
 
280
+ // Methods from Interface
231
281
  public async callContract(
232
282
  call: Call,
233
283
  blockIdentifier: BlockIdentifier = 'pending'
234
284
  ): Promise<CallContractResponse> {
235
- const result = await this.fetchEndpoint('starknet_call', [
236
- {
285
+ const block_id = new Block(blockIdentifier).identifier;
286
+ const result = await this.fetchEndpoint('starknet_call', {
287
+ request: {
237
288
  contract_address: call.contractAddress,
238
289
  entry_point_selector: getSelectorFromName(call.entrypoint),
239
290
  calldata: parseCalldata(call.calldata),
240
291
  },
241
- blockIdentifier,
242
- ]);
292
+ block_id,
293
+ });
243
294
 
244
295
  return this.responseParser.parseCallContractResponse(result);
245
296
  }
246
297
 
247
- public async getCode(
248
- _contractAddress: string,
249
- _blockIdentifier?: BlockIdentifier
250
- ): Promise<GetCodeResponse> {
251
- throw new Error('RPC 0.1.0 does not implement getCode function');
298
+ public async traceTransaction(transactionHash: RPC.TransactionHash): Promise<RPC.Trace> {
299
+ return this.fetchEndpoint('starknet_traceTransaction', { transaction_hash: transactionHash });
252
300
  }
253
301
 
254
- public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) {
302
+ public async traceBlockTransactions(blockHash: RPC.BlockHash): Promise<RPC.Traces> {
303
+ return this.fetchEndpoint('starknet_traceBlockTransactions', { block_hash: blockHash });
304
+ }
305
+
306
+ public async waitForTransaction(txHash: string, retryInterval: number = 8000) {
307
+ let { retries } = this;
255
308
  let onchain = false;
256
- let retries = 100;
257
309
 
258
310
  while (!onchain) {
259
311
  const successStates = ['ACCEPTED_ON_L1', 'ACCEPTED_ON_L2', 'PENDING'];
@@ -279,7 +331,7 @@ export class RpcProvider implements ProviderInterface {
279
331
  }
280
332
 
281
333
  if (retries === 0) {
282
- throw error;
334
+ throw new Error('waitForTransaction timedout with retries');
283
335
  }
284
336
  }
285
337
 
@@ -299,10 +351,8 @@ export class RpcProvider implements ProviderInterface {
299
351
  public async getTransactionCount(
300
352
  blockIdentifier: BlockIdentifier
301
353
  ): Promise<RPC.GetTransactionCountResponse> {
302
- const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
303
- return this.fetchEndpoint('starknet_getBlockTransactionCount', [
304
- blockIdentifierGetter.getIdentifier(),
305
- ]);
354
+ const block_id = new Block(blockIdentifier).identifier;
355
+ return this.fetchEndpoint('starknet_getBlockTransactionCount', { block_id });
306
356
  }
307
357
 
308
358
  /**
@@ -332,6 +382,6 @@ export class RpcProvider implements ProviderInterface {
332
382
  * @returns events and the pagination of the events
333
383
  */
334
384
  public async getEvents(eventFilter: RPC.EventFilter): Promise<RPC.GetEventsResponse> {
335
- return this.fetchEndpoint('starknet_getEvents', [eventFilter]);
385
+ return this.fetchEndpoint('starknet_getEvents', { filter: eventFilter });
336
386
  }
337
387
  }
@@ -14,7 +14,7 @@ import {
14
14
  GetTransactionReceiptResponse,
15
15
  GetTransactionResponse,
16
16
  Invocation,
17
- InvocationsDetails,
17
+ InvocationsDetailsWithNonce,
18
18
  InvokeFunctionResponse,
19
19
  } from '../types';
20
20
  import {
@@ -33,7 +33,7 @@ import { randomAddress } from '../utils/stark';
33
33
  import { buildUrl } from '../utils/url';
34
34
  import { GatewayError, HttpError } from './errors';
35
35
  import { ProviderInterface } from './interface';
36
- import { BlockIdentifier, getFormattedBlockIdentifier } from './utils';
36
+ import { Block, BlockIdentifier } from './utils';
37
37
 
38
38
  type NetworkName = 'mainnet-alpha' | 'goerli-alpha';
39
39
 
@@ -129,7 +129,8 @@ export class SequencerProvider implements ProviderInterface {
129
129
  const queryString = Object.entries(query)
130
130
  .map(([key, value]) => {
131
131
  if (key === 'blockIdentifier') {
132
- return `${getFormattedBlockIdentifier(value)}`;
132
+ const block = new Block(value);
133
+ return `${block.queryIdentifier}`;
133
134
  }
134
135
  return `${key}=${value}`;
135
136
  })
@@ -233,6 +234,13 @@ export class SequencerProvider implements ProviderInterface {
233
234
  );
234
235
  }
235
236
 
237
+ public async getNonce(
238
+ contractAddress: string,
239
+ blockIdentifier: BlockIdentifier = 'pending'
240
+ ): Promise<BigNumberish> {
241
+ return this.fetchEndpoint('get_nonce', { contractAddress, blockIdentifier });
242
+ }
243
+
236
244
  public async getStorageAt(
237
245
  contractAddress: string,
238
246
  key: BigNumberish,
@@ -271,16 +279,16 @@ export class SequencerProvider implements ProviderInterface {
271
279
 
272
280
  public async invokeFunction(
273
281
  functionInvocation: Invocation,
274
- details: InvocationsDetails
282
+ details: InvocationsDetailsWithNonce
275
283
  ): Promise<InvokeFunctionResponse> {
276
284
  return this.fetchEndpoint('add_transaction', undefined, {
277
285
  type: 'INVOKE_FUNCTION',
278
286
  contract_address: functionInvocation.contractAddress,
279
- entry_point_selector: getSelectorFromName(functionInvocation.entrypoint),
280
287
  calldata: bigNumberishArrayToDecimalStringArray(functionInvocation.calldata ?? []),
281
288
  signature: bigNumberishArrayToDecimalStringArray(functionInvocation.signature ?? []),
289
+ nonce: toHex(toBN(details.nonce)),
282
290
  max_fee: toHex(toBN(details.maxFee || 0)),
283
- version: toHex(toBN(details.version || 0)),
291
+ version: toHex(toBN(details.version || 1)),
284
292
  }).then(this.responseParser.parseInvokeFunctionResponse);
285
293
  }
286
294
 
@@ -315,18 +323,19 @@ export class SequencerProvider implements ProviderInterface {
315
323
 
316
324
  public async getEstimateFee(
317
325
  invocation: Invocation,
318
- blockIdentifier: BlockIdentifier = 'pending',
319
- invocationDetails: InvocationsDetails = {}
326
+ invocationDetails: InvocationsDetailsWithNonce,
327
+ blockIdentifier: BlockIdentifier = 'pending'
320
328
  ): Promise<EstimateFeeResponse> {
321
329
  return this.fetchEndpoint(
322
330
  'estimate_fee',
323
331
  { blockIdentifier },
324
332
  {
333
+ type: 'INVOKE_FUNCTION',
325
334
  contract_address: invocation.contractAddress,
326
- entry_point_selector: getSelectorFromName(invocation.entrypoint),
327
335
  calldata: invocation.calldata ?? [],
328
336
  signature: bigNumberishArrayToDecimalStringArray(invocation.signature || []),
329
- version: toHex(toBN(invocationDetails?.version || 0)),
337
+ version: toHex(toBN(invocationDetails?.version || 1)),
338
+ nonce: toHex(toBN(invocationDetails.nonce)),
330
339
  }
331
340
  ).then(this.responseParser.parseFeeEstimateResponse);
332
341
  }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable max-classes-per-file */
1
2
  import type { BlockNumber } from '../types';
2
3
  import { BigNumberish, isHex, toBN, toHex } from '../utils/number';
3
4
 
@@ -33,73 +34,59 @@ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string
33
34
  // null appends nothing to the request url
34
35
 
35
36
  export type BlockIdentifier = BlockNumber | BigNumberish;
36
- type BlockIdentifierObject =
37
- | { type: 'BLOCK_NUMBER'; data: BlockNumber }
38
- | { type: 'BLOCK_HASH'; data: BigNumberish };
39
37
 
40
- export class BlockIdentifierClass {
41
- blockIdentifier: BlockIdentifier;
38
+ export class Block {
39
+ hash: BlockIdentifier = null;
42
40
 
43
- constructor(blockIdentifier: BlockIdentifier) {
44
- this.blockIdentifier = blockIdentifier;
41
+ number: BlockIdentifier = null;
42
+
43
+ tag: BlockIdentifier = null;
44
+
45
+ private setIdentifier: (_identifier: BlockIdentifier) => void;
46
+
47
+ constructor(_identifier: BlockIdentifier) {
48
+ this.setIdentifier = function (__identifier: BlockIdentifier) {
49
+ if (typeof __identifier === 'string' && isHex(__identifier)) {
50
+ this.hash = __identifier;
51
+ } else if (typeof __identifier === 'number') {
52
+ this.number = __identifier;
53
+ } else {
54
+ this.tag = __identifier;
55
+ }
56
+ };
57
+
58
+ this.setIdentifier(_identifier);
45
59
  }
46
60
 
47
- getIdentifier() {
48
- if (typeof this.blockIdentifier === 'string' && isHex(this.blockIdentifier)) {
49
- return { block_hash: this.blockIdentifier };
61
+ get queryIdentifier(): any {
62
+ if (this.number !== null) {
63
+ return `blockNumber=${this.number}`;
50
64
  }
51
65
 
52
- if (typeof this.blockIdentifier === 'number') {
53
- return { block_number: this.blockIdentifier };
66
+ if (this.hash !== null) {
67
+ return `blockHash=${this.hash}`;
54
68
  }
55
69
 
56
- return this.blockIdentifier;
70
+ return `blockNumber=${this.tag}`;
57
71
  }
58
- }
59
72
 
60
- /**
61
- * Identifies the block to be queried.
62
- *
63
- * @param blockIdentifier - block identifier
64
- * @returns block identifier object
65
- */
66
- export function getBlockIdentifier(blockIdentifier: BlockIdentifier): BlockIdentifierObject {
67
- if (blockIdentifier === null || blockIdentifier === 'latest') {
68
- return { type: 'BLOCK_NUMBER', data: 'latest' }; // default to latest block
69
- }
70
- if (blockIdentifier === 'pending') {
71
- return { type: 'BLOCK_NUMBER', data: 'pending' };
72
- }
73
- if (typeof blockIdentifier === 'number' || typeof blockIdentifier === 'bigint') {
74
- return { type: 'BLOCK_NUMBER', data: blockIdentifier };
75
- }
76
- if (typeof blockIdentifier === 'string' && blockIdentifier.startsWith('0x')) {
77
- return { type: 'BLOCK_HASH', data: blockIdentifier };
78
- }
79
- if (typeof blockIdentifier === 'string' && !Number.isNaN(parseInt(blockIdentifier, 10))) {
80
- return { type: 'BLOCK_NUMBER', data: parseInt(blockIdentifier, 10) };
81
- }
82
- if (typeof blockIdentifier === 'string') {
83
- throw new Error(`Invalid block identifier: ${blockIdentifier}`);
84
- }
85
- return { type: 'BLOCK_HASH', data: blockIdentifier };
86
- }
73
+ get identifier(): any {
74
+ if (this.number !== null) {
75
+ return { block_number: this.number };
76
+ }
87
77
 
88
- /**
89
- * Gets the block identifier for API request
90
- *
91
- * [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L164-L173)
92
- *
93
- * @param blockIdentifier
94
- * @returns block identifier for API request
95
- */
96
- export function getFormattedBlockIdentifier(blockIdentifier: BlockIdentifier = null): string {
97
- const blockIdentifierObject = getBlockIdentifier(blockIdentifier);
98
- if (blockIdentifierObject.type === 'BLOCK_NUMBER' && blockIdentifierObject.data === null) {
99
- return '';
78
+ if (this.hash !== null) {
79
+ return { block_hash: this.hash };
80
+ }
81
+
82
+ return this.tag;
100
83
  }
101
- if (blockIdentifierObject.type === 'BLOCK_NUMBER') {
102
- return `blockNumber=${blockIdentifierObject.data}`;
84
+
85
+ set identifier(_identifier: BlockIdentifier) {
86
+ this.setIdentifier(_identifier);
103
87
  }
104
- return `blockHash=${toHex(toBN(blockIdentifierObject.data))}`;
88
+
89
+ valueOf = () => this.number;
90
+
91
+ toString = () => this.hash;
105
92
  }
@@ -1,7 +1,7 @@
1
- import { Abi, Invocation, InvocationsSignerDetails, KeyPair, Signature } from '../types';
1
+ import { Abi, Call, InvocationsSignerDetails, KeyPair, Signature } from '../types';
2
2
  import { genKeyPair, getStarkKey, sign } from '../utils/ellipticCurve';
3
- import { calculcateTransactionHash, getSelectorFromName } from '../utils/hash';
4
- import { fromCallsToExecuteCalldataWithNonce } from '../utils/transaction';
3
+ import { calculateTransactionHash } from '../utils/hash';
4
+ import { fromCallsToExecuteCalldata } from '../utils/transaction';
5
5
  import { TypedData, getMessageHash } from '../utils/typedData';
6
6
  import { SignerInterface } from './interface';
7
7
 
@@ -17,7 +17,7 @@ export class Signer implements SignerInterface {
17
17
  }
18
18
 
19
19
  public async signTransaction(
20
- transactions: Invocation[],
20
+ transactions: Call[],
21
21
  transactionsDetail: InvocationsSignerDetails,
22
22
  abis?: Abi[]
23
23
  ): Promise<Signature> {
@@ -26,15 +26,15 @@ export class Signer implements SignerInterface {
26
26
  }
27
27
  // now use abi to display decoded data somewhere, but as this signer is headless, we can't do that
28
28
 
29
- const calldata = fromCallsToExecuteCalldataWithNonce(transactions, transactionsDetail.nonce);
29
+ const calldata = fromCallsToExecuteCalldata(transactions);
30
30
 
31
- const msgHash = calculcateTransactionHash(
31
+ const msgHash = calculateTransactionHash(
32
32
  transactionsDetail.walletAddress,
33
33
  transactionsDetail.version,
34
- getSelectorFromName('__execute__'),
35
34
  calldata,
36
35
  transactionsDetail.maxFee,
37
- transactionsDetail.chainId
36
+ transactionsDetail.chainId,
37
+ transactionsDetail.nonce
38
38
  );
39
39
 
40
40
  return sign(this.keyPair, msgHash);
@@ -1,4 +1,4 @@
1
- import { Abi, Invocation, InvocationsSignerDetails, Signature } from '../types';
1
+ import { Abi, Call, InvocationsSignerDetails, Signature } from '../types';
2
2
  import { TypedData } from '../utils/typedData';
3
3
 
4
4
  export abstract class SignerInterface {
@@ -33,7 +33,7 @@ export abstract class SignerInterface {
33
33
  * @returns signature
34
34
  */
35
35
  public abstract signTransaction(
36
- transactions: Invocation[],
36
+ transactions: Call[],
37
37
  transactionsDetail: InvocationsSignerDetails,
38
38
  abis?: Abi[]
39
39
  ): Promise<Signature>;