starknet 4.8.0 → 4.10.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 (107) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +1 -3
  3. package/__mocks__/ERC20.json +32561 -29055
  4. package/__tests__/account.test.ts +32 -24
  5. package/__tests__/contract.test.ts +25 -14
  6. package/__tests__/defaultProvider.test.ts +91 -240
  7. package/__tests__/fixtures.ts +10 -2
  8. package/__tests__/rpcProvider.test.ts +8 -16
  9. package/__tests__/sequencerProvider.test.ts +17 -10
  10. package/__tests__/udc.test.ts +41 -0
  11. package/__tests__/utils/merkle.test.ts +98 -3
  12. package/__tests__/utils/typedData.test.ts +3 -3
  13. package/account/default.d.ts +12 -44
  14. package/account/default.js +305 -61
  15. package/account/interface.d.ts +96 -8
  16. package/constants.d.ts +8 -1
  17. package/constants.js +8 -1
  18. package/contract/default.d.ts +11 -27
  19. package/contract/default.js +105 -121
  20. package/contract/interface.d.ts +5 -2
  21. package/dist/account/default.d.ts +12 -44
  22. package/dist/account/default.js +305 -61
  23. package/dist/account/interface.d.ts +96 -8
  24. package/dist/constants.d.ts +8 -1
  25. package/dist/constants.js +8 -1
  26. package/dist/contract/default.d.ts +11 -27
  27. package/dist/contract/default.js +105 -121
  28. package/dist/contract/interface.d.ts +5 -2
  29. package/dist/provider/default.d.ts +8 -3
  30. package/dist/provider/default.js +31 -4
  31. package/dist/provider/interface.d.ts +67 -5
  32. package/dist/provider/rpc.d.ts +10 -3
  33. package/dist/provider/rpc.js +98 -10
  34. package/dist/provider/sequencer.d.ts +11 -4
  35. package/dist/provider/sequencer.js +89 -18
  36. package/dist/signer/default.d.ts +5 -2
  37. package/dist/signer/default.js +25 -3
  38. package/dist/signer/interface.d.ts +29 -2
  39. package/dist/types/api/index.d.ts +0 -6
  40. package/dist/types/api/openrpc.d.ts +24 -2
  41. package/dist/types/api/sequencer.d.ts +22 -7
  42. package/dist/types/index.d.ts +1 -1
  43. package/dist/types/lib.d.ts +36 -2
  44. package/dist/types/provider.d.ts +15 -10
  45. package/dist/types/signer.d.ts +14 -1
  46. package/dist/utils/hash.d.ts +2 -0
  47. package/dist/utils/hash.js +13 -2
  48. package/dist/utils/merkle.js +2 -4
  49. package/dist/utils/number.d.ts +1 -0
  50. package/dist/utils/number.js +3 -1
  51. package/dist/utils/responseParser/rpc.d.ts +2 -6
  52. package/dist/utils/responseParser/rpc.js +0 -11
  53. package/dist/utils/responseParser/sequencer.js +4 -14
  54. package/package.json +1 -1
  55. package/provider/default.d.ts +8 -3
  56. package/provider/default.js +31 -4
  57. package/provider/interface.d.ts +67 -5
  58. package/provider/rpc.d.ts +10 -3
  59. package/provider/rpc.js +98 -10
  60. package/provider/sequencer.d.ts +11 -4
  61. package/provider/sequencer.js +89 -18
  62. package/signer/default.d.ts +5 -2
  63. package/signer/default.js +25 -3
  64. package/signer/interface.d.ts +29 -2
  65. package/src/account/default.ts +243 -55
  66. package/src/account/interface.ts +132 -7
  67. package/src/constants.ts +8 -0
  68. package/src/contract/default.ts +124 -141
  69. package/src/contract/interface.ts +5 -2
  70. package/src/provider/default.ts +43 -5
  71. package/src/provider/interface.ts +92 -7
  72. package/src/provider/rpc.ts +93 -15
  73. package/src/provider/sequencer.ts +87 -14
  74. package/src/signer/default.ts +56 -4
  75. package/src/signer/interface.ts +33 -2
  76. package/src/types/api/index.ts +0 -4
  77. package/src/types/api/openrpc.ts +28 -2
  78. package/src/types/api/sequencer.ts +32 -9
  79. package/src/types/index.ts +1 -1
  80. package/src/types/lib.ts +43 -2
  81. package/src/types/provider.ts +27 -11
  82. package/src/types/signer.ts +18 -1
  83. package/src/utils/hash.ts +46 -1
  84. package/src/utils/merkle.ts +2 -4
  85. package/src/utils/number.ts +2 -0
  86. package/src/utils/responseParser/rpc.ts +4 -20
  87. package/src/utils/responseParser/sequencer.ts +2 -0
  88. package/types/api/index.d.ts +0 -6
  89. package/types/api/openrpc.d.ts +24 -2
  90. package/types/api/sequencer.d.ts +22 -7
  91. package/types/index.d.ts +1 -1
  92. package/types/lib.d.ts +36 -2
  93. package/types/provider.d.ts +15 -10
  94. package/types/signer.d.ts +14 -1
  95. package/utils/hash.d.ts +2 -0
  96. package/utils/hash.js +13 -2
  97. package/utils/merkle.js +2 -4
  98. package/utils/number.d.ts +1 -0
  99. package/utils/number.js +3 -1
  100. package/utils/responseParser/rpc.d.ts +2 -6
  101. package/utils/responseParser/rpc.js +0 -11
  102. package/utils/responseParser/sequencer.js +4 -14
  103. package/www/docs/API/account.md +170 -11
  104. package/www/docs/API/contract.md +39 -3
  105. package/www/docs/API/provider.md +310 -17
  106. package/www/docs/API/signer.md +56 -2
  107. package/www/guides/erc20.md +13 -7
@@ -2,7 +2,6 @@ import { StarknetChainId } from '../constants';
2
2
  import {
3
3
  Call,
4
4
  CallContractResponse,
5
- DeclareContractPayload,
6
5
  DeclareContractResponse,
7
6
  DeployContractPayload,
8
7
  DeployContractResponse,
@@ -16,6 +15,11 @@ import {
16
15
  InvokeFunctionResponse,
17
16
  } from '../types';
18
17
  import { RPC } from '../types/api';
18
+ import {
19
+ DeclareContractTransaction,
20
+ DeployAccountContractPayload,
21
+ DeployAccountContractTransaction,
22
+ } from '../types/lib';
19
23
  import fetch from '../utils/fetchPonyfill';
20
24
  import { getSelectorFromName } from '../utils/hash';
21
25
  import { stringify } from '../utils/json';
@@ -34,6 +38,7 @@ import { Block, BlockIdentifier } from './utils';
34
38
  export type RpcProviderOptions = {
35
39
  nodeUrl: string;
36
40
  retries?: number;
41
+ headers?: object;
37
42
  };
38
43
 
39
44
  export class RpcProvider implements ProviderInterface {
@@ -42,14 +47,17 @@ export class RpcProvider implements ProviderInterface {
42
47
  // from interface
43
48
  public chainId!: StarknetChainId;
44
49
 
50
+ public headers: object;
51
+
45
52
  private responseParser = new RPCResponseParser();
46
53
 
47
54
  private retries: number;
48
55
 
49
56
  constructor(optionsOrProvider: RpcProviderOptions) {
50
- const { nodeUrl, retries } = optionsOrProvider;
57
+ const { nodeUrl, retries, headers } = optionsOrProvider;
51
58
  this.nodeUrl = nodeUrl;
52
59
  this.retries = retries || 200;
60
+ this.headers = { 'Content-Type': 'application/json', ...headers };
53
61
 
54
62
  this.getChainId().then((chainId) => {
55
63
  this.chainId = chainId;
@@ -60,7 +68,7 @@ export class RpcProvider implements ProviderInterface {
60
68
  return fetch(this.nodeUrl, {
61
69
  method: 'POST',
62
70
  body: stringify({ method, jsonrpc: '2.0', params, id: 0 }),
63
- headers: { 'Content-Type': 'application/json' },
71
+ headers: this.headers,
64
72
  });
65
73
  }
66
74
 
@@ -183,9 +191,7 @@ export class RpcProvider implements ProviderInterface {
183
191
  }
184
192
 
185
193
  public async getTransactionReceipt(txHash: string): Promise<GetTransactionReceiptResponse> {
186
- return this.fetchEndpoint('starknet_getTransactionReceipt', { transaction_hash: txHash }).then(
187
- this.responseParser.parseGetTransactionReceiptResponse
188
- );
194
+ return this.fetchEndpoint('starknet_getTransactionReceipt', { transaction_hash: txHash });
189
195
  }
190
196
 
191
197
  public async getClass(classHash: RPC.Felt): Promise<RPC.ContractClass> {
@@ -194,7 +200,7 @@ export class RpcProvider implements ProviderInterface {
194
200
 
195
201
  public async getClassAt(
196
202
  contractAddress: string,
197
- blockIdentifier: BlockIdentifier
203
+ blockIdentifier: BlockIdentifier = 'pending'
198
204
  ): Promise<RPC.ContractClass> {
199
205
  const block_id = new Block(blockIdentifier).identifier;
200
206
  return this.fetchEndpoint('starknet_getClassAt', {
@@ -214,33 +220,93 @@ export class RpcProvider implements ProviderInterface {
214
220
  invocation: Invocation,
215
221
  invocationDetails: InvocationsDetailsWithNonce,
216
222
  blockIdentifier: BlockIdentifier = 'pending'
223
+ ): Promise<EstimateFeeResponse> {
224
+ return this.getInvokeEstimateFee(invocation, invocationDetails, blockIdentifier);
225
+ }
226
+
227
+ public async getInvokeEstimateFee(
228
+ invocation: Invocation,
229
+ invocationDetails: InvocationsDetailsWithNonce,
230
+ blockIdentifier: BlockIdentifier = 'pending'
217
231
  ): Promise<EstimateFeeResponse> {
218
232
  const block_id = new Block(blockIdentifier).identifier;
219
233
  return this.fetchEndpoint('starknet_estimateFee', {
220
234
  request: {
235
+ type: 'INVOKE',
221
236
  contract_address: invocation.contractAddress,
222
237
  calldata: parseCalldata(invocation.calldata),
223
238
  signature: bigNumberishArrayToHexadecimalStringArray(invocation.signature || []),
224
239
  version: toHex(toBN(invocationDetails?.version || 0)),
240
+ nonce: toHex(toBN(invocationDetails.nonce)),
225
241
  max_fee: toHex(toBN(invocationDetails?.maxFee || 0)),
226
242
  },
227
243
  block_id,
228
244
  }).then(this.responseParser.parseFeeEstimateResponse);
229
245
  }
230
246
 
231
- public async declareContract({
232
- contract,
233
- version,
234
- }: DeclareContractPayload): Promise<DeclareContractResponse> {
235
- const contractDefinition = parseContract(contract);
247
+ // TODO: Revisit after Pathfinder release with JSON-RPC v0.2.1 RPC Spec
236
248
 
249
+ public async getDeclareEstimateFee(
250
+ { senderAddress, contractDefinition, signature }: DeclareContractTransaction,
251
+ details: InvocationsDetailsWithNonce,
252
+ blockIdentifier: BlockIdentifier = 'pending'
253
+ ): Promise<EstimateFeeResponse> {
254
+ const block_id = new Block(blockIdentifier).identifier;
255
+ return this.fetchEndpoint('starknet_estimateFee', {
256
+ request: {
257
+ type: 'DECLARE',
258
+ contract_class: {
259
+ program: contractDefinition.program,
260
+ entry_points_by_type: contractDefinition.entry_points_by_type,
261
+ abi: contractDefinition.abi, // rpc 2.0
262
+ },
263
+ sender_address: senderAddress,
264
+ signature: bigNumberishArrayToHexadecimalStringArray(signature || []),
265
+ version: toHex(toBN(details?.version || 0)),
266
+ nonce: toHex(toBN(details.nonce)),
267
+ max_fee: toHex(toBN(details?.maxFee || 0)),
268
+ },
269
+ block_id,
270
+ }).then(this.responseParser.parseFeeEstimateResponse);
271
+ }
272
+
273
+ public async getDeployAccountEstimateFee(
274
+ { classHash, constructorCalldata, addressSalt, signature }: DeployAccountContractTransaction,
275
+ details: InvocationsDetailsWithNonce,
276
+ blockIdentifier: BlockIdentifier = 'pending'
277
+ ): Promise<EstimateFeeResponse> {
278
+ const block_id = new Block(blockIdentifier).identifier;
279
+ return this.fetchEndpoint('starknet_estimateFee', {
280
+ request: {
281
+ type: 'DEPLOY_ACCOUNT',
282
+ constructor_calldata: bigNumberishArrayToHexadecimalStringArray(constructorCalldata || []),
283
+ class_hash: toHex(toBN(classHash)),
284
+ contract_address_salt: toHex(toBN(addressSalt || 0)),
285
+ signature: bigNumberishArrayToHexadecimalStringArray(signature || []),
286
+ version: toHex(toBN(details?.version || 0)),
287
+ nonce: toHex(toBN(details.nonce)),
288
+ max_fee: toHex(toBN(details?.maxFee || 0)),
289
+ },
290
+ block_id,
291
+ }).then(this.responseParser.parseFeeEstimateResponse);
292
+ }
293
+
294
+ // TODO: Revisit after Pathfinder release with JSON-RPC v0.2.1 RPC Spec
295
+ public async declareContract(
296
+ { contractDefinition, signature, senderAddress }: DeclareContractTransaction,
297
+ details: InvocationsDetailsWithNonce
298
+ ): Promise<DeclareContractResponse> {
237
299
  return this.fetchEndpoint('starknet_addDeclareTransaction', {
238
300
  contract_class: {
239
301
  program: contractDefinition.program,
240
302
  entry_points_by_type: contractDefinition.entry_points_by_type,
241
303
  abi: contractDefinition.abi, // rpc 2.0
242
304
  },
243
- version: toHex(toBN(version || 0)),
305
+ version: toHex(toBN(details.version || 0)),
306
+ max_fee: toHex(toBN(details.maxFee || 0)),
307
+ signature: bigNumberishArrayToHexadecimalStringArray(signature || []),
308
+ sender_address: senderAddress,
309
+ nonce: toHex(toBN(details.nonce)),
244
310
  });
245
311
  }
246
312
 
@@ -262,6 +328,18 @@ export class RpcProvider implements ProviderInterface {
262
328
  });
263
329
  }
264
330
 
331
+ public async deployAccountContract({
332
+ classHash,
333
+ constructorCalldata,
334
+ addressSalt,
335
+ }: DeployAccountContractPayload): Promise<DeployContractResponse> {
336
+ return this.fetchEndpoint('starknet_addDeployAccountTransaction', {
337
+ constructor_calldata: bigNumberishArrayToHexadecimalStringArray(constructorCalldata || []),
338
+ class_hash: toHex(toBN(classHash)),
339
+ contract_address_salt: toHex(toBN(addressSalt || 0)),
340
+ });
341
+ }
342
+
265
343
  public async invokeFunction(
266
344
  functionInvocation: Invocation,
267
345
  details: InvocationsDetailsWithNonce
@@ -317,9 +395,9 @@ export class RpcProvider implements ProviderInterface {
317
395
  // eslint-disable-next-line no-await-in-loop
318
396
  const res = await this.getTransactionReceipt(txHash);
319
397
 
320
- if (successStates.includes(res.status)) {
398
+ if (res.status && successStates.includes(res.status)) {
321
399
  onchain = true;
322
- } else if (errorStates.includes(res.status)) {
400
+ } else if (res.status && errorStates.includes(res.status)) {
323
401
  const message = res.status;
324
402
  const error = new Error(message) as Error & { response: any };
325
403
  error.response = res;
@@ -1,11 +1,10 @@
1
1
  import urljoin from 'url-join';
2
2
 
3
- import { ONE, StarknetChainId, ZERO } from '../constants';
3
+ import { StarknetChainId } from '../constants';
4
4
  import {
5
5
  Call,
6
6
  CallContractResponse,
7
7
  ContractClass,
8
- DeclareContractPayload,
9
8
  DeclareContractResponse,
10
9
  DeployContractPayload,
11
10
  DeployContractResponse,
@@ -24,6 +23,7 @@ import {
24
23
  GetTransactionTraceResponse,
25
24
  Sequencer,
26
25
  } from '../types/api';
26
+ import { DeclareContractTransaction, DeployAccountContractTransaction } from '../types/lib';
27
27
  import fetch from '../utils/fetchPonyfill';
28
28
  import { getSelector, getSelectorFromName } from '../utils/hash';
29
29
  import { parse, parseAlwaysAsBig, stringify } from '../utils/json';
@@ -44,7 +44,7 @@ import { GatewayError, HttpError } from './errors';
44
44
  import { ProviderInterface } from './interface';
45
45
  import { Block, BlockIdentifier } from './utils';
46
46
 
47
- type NetworkName = 'mainnet-alpha' | 'goerli-alpha';
47
+ type NetworkName = 'mainnet-alpha' | 'goerli-alpha' | 'goerli-alpha-2';
48
48
 
49
49
  function isEmptyQueryObject(obj?: Record<any, any>): obj is undefined {
50
50
  return (
@@ -62,6 +62,7 @@ export type SequencerProviderOptions =
62
62
  feederGatewayUrl?: string;
63
63
  gatewayUrl?: string;
64
64
  chainId?: StarknetChainId;
65
+ headers?: object;
65
66
  };
66
67
 
67
68
  export class SequencerProvider implements ProviderInterface {
@@ -73,9 +74,11 @@ export class SequencerProvider implements ProviderInterface {
73
74
 
74
75
  public chainId: StarknetChainId;
75
76
 
77
+ public headers: object | undefined;
78
+
76
79
  private responseParser = new SequencerAPIResponseParser();
77
80
 
78
- constructor(optionsOrProvider: SequencerProviderOptions = { network: 'goerli-alpha' }) {
81
+ constructor(optionsOrProvider: SequencerProviderOptions = { network: 'goerli-alpha-2' }) {
79
82
  if ('network' in optionsOrProvider) {
80
83
  this.baseUrl = SequencerProvider.getNetworkFromName(optionsOrProvider.network);
81
84
  this.chainId = SequencerProvider.getChainIdFromBaseUrl(this.baseUrl);
@@ -93,6 +96,8 @@ export class SequencerProvider implements ProviderInterface {
93
96
  this.chainId =
94
97
  optionsOrProvider.chainId ??
95
98
  SequencerProvider.getChainIdFromBaseUrl(optionsOrProvider.baseUrl);
99
+
100
+ this.headers = optionsOrProvider?.headers;
96
101
  }
97
102
  }
98
103
 
@@ -101,6 +106,9 @@ export class SequencerProvider implements ProviderInterface {
101
106
  case 'mainnet-alpha':
102
107
  return 'https://alpha-mainnet.starknet.io';
103
108
  case 'goerli-alpha':
109
+ return 'https://alpha4.starknet.io';
110
+ case 'goerli-alpha-2':
111
+ return 'https://alpha4-2.starknet.io';
104
112
  default:
105
113
  return 'https://alpha4.starknet.io';
106
114
  }
@@ -153,19 +161,20 @@ export class SequencerProvider implements ProviderInterface {
153
161
  return `?${queryString}`;
154
162
  }
155
163
 
156
- private getHeaders(method: 'POST' | 'GET'): Record<string, string> | undefined {
164
+ private getHeaders(method: 'POST' | 'GET'): object | undefined {
157
165
  if (method === 'POST') {
158
166
  return {
159
167
  'Content-Type': 'application/json',
168
+ ...this.headers,
160
169
  };
161
170
  }
162
- return undefined;
171
+ return this.headers;
163
172
  }
164
173
 
165
174
  // typesafe fetch
166
175
  protected async fetchEndpoint<T extends keyof Sequencer.Endpoints>(
167
176
  endpoint: T,
168
- // typescript type magiuc to create a nice fitting function interface
177
+ // typescript type magic to create a nice fitting function interface
169
178
  ...[query, request]: Sequencer.Endpoints[T]['QUERY'] extends never
170
179
  ? Sequencer.Endpoints[T]['REQUEST'] extends never
171
180
  ? [] // when no query and no request is needed, we can omit the query and request parameters
@@ -321,17 +330,34 @@ export class SequencerProvider implements ProviderInterface {
321
330
  }).then(this.responseParser.parseDeployContractResponse);
322
331
  }
323
332
 
324
- public async declareContract({
325
- contract,
326
- }: DeclareContractPayload): Promise<DeclareContractResponse> {
327
- const contractDefinition = parseContract(contract);
333
+ public async deployAccountContract(
334
+ { classHash, constructorCalldata, addressSalt, signature }: DeployAccountContractTransaction,
335
+ details: InvocationsDetailsWithNonce
336
+ ): Promise<DeployContractResponse> {
337
+ return this.fetchEndpoint('add_transaction', undefined, {
338
+ type: 'DEPLOY_ACCOUNT',
339
+ contract_address_salt: addressSalt ?? randomAddress(),
340
+ constructor_calldata: bigNumberishArrayToDecimalStringArray(constructorCalldata ?? []),
341
+ class_hash: toHex(toBN(classHash)),
342
+ max_fee: toHex(toBN(details.maxFee || 0)),
343
+ version: toHex(toBN(details.version || 0)),
344
+ nonce: toHex(toBN(details.nonce)),
345
+ signature: bigNumberishArrayToDecimalStringArray(signature || []),
346
+ }).then(this.responseParser.parseDeployContractResponse);
347
+ }
328
348
 
349
+ public async declareContract(
350
+ { senderAddress, contractDefinition, signature }: DeclareContractTransaction,
351
+ details: InvocationsDetailsWithNonce
352
+ ): Promise<DeclareContractResponse> {
329
353
  return this.fetchEndpoint('add_transaction', undefined, {
330
354
  type: 'DECLARE',
331
355
  contract_class: contractDefinition,
332
- nonce: toHex(ZERO),
333
- signature: [],
334
- sender_address: toHex(ONE),
356
+ nonce: toHex(toBN(details.nonce)),
357
+ signature: bigNumberishArrayToDecimalStringArray(signature || []),
358
+ sender_address: senderAddress,
359
+ max_fee: toHex(toBN(details.maxFee || 0)),
360
+ version: toHex(toBN(details.version || 1)),
335
361
  }).then(this.responseParser.parseDeclareContractResponse);
336
362
  }
337
363
 
@@ -339,6 +365,14 @@ export class SequencerProvider implements ProviderInterface {
339
365
  invocation: Invocation,
340
366
  invocationDetails: InvocationsDetailsWithNonce,
341
367
  blockIdentifier: BlockIdentifier = 'pending'
368
+ ): Promise<EstimateFeeResponse> {
369
+ return this.getInvokeEstimateFee(invocation, invocationDetails, blockIdentifier);
370
+ }
371
+
372
+ public async getInvokeEstimateFee(
373
+ invocation: Invocation,
374
+ invocationDetails: InvocationsDetailsWithNonce,
375
+ blockIdentifier: BlockIdentifier = 'pending'
342
376
  ): Promise<EstimateFeeResponse> {
343
377
  return this.fetchEndpoint(
344
378
  'estimate_fee',
@@ -354,6 +388,45 @@ export class SequencerProvider implements ProviderInterface {
354
388
  ).then(this.responseParser.parseFeeEstimateResponse);
355
389
  }
356
390
 
391
+ public async getDeclareEstimateFee(
392
+ { senderAddress, contractDefinition, signature }: DeclareContractTransaction,
393
+ details: InvocationsDetailsWithNonce,
394
+ blockIdentifier: BlockIdentifier = 'pending'
395
+ ): Promise<EstimateFeeResponse> {
396
+ return this.fetchEndpoint(
397
+ 'estimate_fee',
398
+ { blockIdentifier },
399
+ {
400
+ type: 'DECLARE',
401
+ sender_address: senderAddress,
402
+ contract_class: contractDefinition,
403
+ signature: bigNumberishArrayToDecimalStringArray(signature || []),
404
+ version: toHex(toBN(details?.version || 1)),
405
+ nonce: toHex(toBN(details.nonce)),
406
+ }
407
+ ).then(this.responseParser.parseFeeEstimateResponse);
408
+ }
409
+
410
+ public async getDeployAccountEstimateFee(
411
+ { classHash, addressSalt, constructorCalldata, signature }: DeployAccountContractTransaction,
412
+ details: InvocationsDetailsWithNonce,
413
+ blockIdentifier: BlockIdentifier = 'pending'
414
+ ): Promise<EstimateFeeResponse> {
415
+ return this.fetchEndpoint(
416
+ 'estimate_fee',
417
+ { blockIdentifier },
418
+ {
419
+ type: 'DEPLOY_ACCOUNT',
420
+ class_hash: toHex(toBN(classHash)),
421
+ constructor_calldata: bigNumberishArrayToDecimalStringArray(constructorCalldata || []),
422
+ contract_address_salt: toHex(toBN(addressSalt || 0)),
423
+ signature: bigNumberishArrayToDecimalStringArray(signature || []),
424
+ version: toHex(toBN(details?.version || 0)),
425
+ nonce: toHex(toBN(details.nonce)),
426
+ }
427
+ ).then(this.responseParser.parseFeeEstimateResponse);
428
+ }
429
+
357
430
  public async getCode(
358
431
  contractAddress: string,
359
432
  blockIdentifier: BlockIdentifier = 'pending'
@@ -1,6 +1,18 @@
1
- import { Abi, Call, InvocationsSignerDetails, KeyPair, Signature } from '../types';
1
+ import {
2
+ Abi,
3
+ Call,
4
+ DeclareSignerDetails,
5
+ InvocationsSignerDetails,
6
+ KeyPair,
7
+ Signature,
8
+ } from '../types';
9
+ import { DeployAccountSignerDetails } from '../types/signer';
2
10
  import { genKeyPair, getStarkKey, sign } from '../utils/ellipticCurve';
3
- import { calculateTransactionHash } from '../utils/hash';
11
+ import {
12
+ calculateDeclareTransactionHash,
13
+ calculateDeployAccountTransactionHash,
14
+ calculateTransactionHash,
15
+ } from '../utils/hash';
4
16
  import { fromCallsToExecuteCalldata } from '../utils/transaction';
5
17
  import { TypedData, getMessageHash } from '../utils/typedData';
6
18
  import { SignerInterface } from './interface';
@@ -16,6 +28,11 @@ export class Signer implements SignerInterface {
16
28
  return getStarkKey(this.keyPair);
17
29
  }
18
30
 
31
+ public async signMessage(typedData: TypedData, accountAddress: string): Promise<Signature> {
32
+ const msgHash = getMessageHash(typedData, accountAddress);
33
+ return sign(this.keyPair, msgHash);
34
+ }
35
+
19
36
  public async signTransaction(
20
37
  transactions: Call[],
21
38
  transactionsDetail: InvocationsSignerDetails,
@@ -40,8 +57,43 @@ export class Signer implements SignerInterface {
40
57
  return sign(this.keyPair, msgHash);
41
58
  }
42
59
 
43
- public async signMessage(typedData: TypedData, accountAddress: string): Promise<Signature> {
44
- const msgHash = getMessageHash(typedData, accountAddress);
60
+ public async signDeployAccountTransaction({
61
+ classHash,
62
+ contractAddress,
63
+ constructorCalldata,
64
+ addressSalt,
65
+ maxFee,
66
+ version,
67
+ chainId,
68
+ nonce,
69
+ }: DeployAccountSignerDetails) {
70
+ const msgHash = calculateDeployAccountTransactionHash(
71
+ contractAddress,
72
+ classHash,
73
+ constructorCalldata,
74
+ addressSalt,
75
+ version,
76
+ maxFee,
77
+ chainId,
78
+ nonce
79
+ );
80
+
81
+ return sign(this.keyPair, msgHash);
82
+ }
83
+
84
+ public async signDeclareTransaction(
85
+ // contractClass: ContractClass, // Should be used once class hash is present in ContractClass
86
+ { classHash, senderAddress, chainId, maxFee, version, nonce }: DeclareSignerDetails
87
+ ) {
88
+ const msgHash = calculateDeclareTransactionHash(
89
+ classHash,
90
+ senderAddress,
91
+ version,
92
+ maxFee,
93
+ chainId,
94
+ nonce
95
+ );
96
+
45
97
  return sign(this.keyPair, msgHash);
46
98
  }
47
99
  }
@@ -1,4 +1,5 @@
1
- import { Abi, Call, InvocationsSignerDetails, Signature } from '../types';
1
+ import { Abi, Call, DeclareSignerDetails, InvocationsSignerDetails, Signature } from '../types';
2
+ import { DeployAccountSignerDetails } from '../types/signer';
2
3
  import { TypedData } from '../utils/typedData';
3
4
 
4
5
  export abstract class SignerInterface {
@@ -27,7 +28,6 @@ export abstract class SignerInterface {
27
28
  * - contractAddress - the address of the contract
28
29
  * - entrypoint - the entrypoint of the contract
29
30
  * - calldata - (defaults to []) the calldata
30
- * - signature - (defaults to []) the signature
31
31
  * @param abi (optional) the abi of the contract for better displaying
32
32
  *
33
33
  * @returns signature
@@ -37,4 +37,35 @@ export abstract class SignerInterface {
37
37
  transactionsDetail: InvocationsSignerDetails,
38
38
  abis?: Abi[]
39
39
  ): Promise<Signature>;
40
+
41
+ /**
42
+ * Signs a DEPLOY_ACCOUNT transaction with the starknet private key and returns the signature
43
+ *
44
+ * @param transaction
45
+ * - contractAddress - the computed address of the contract
46
+ * - constructorCalldata - calldata to be passed in deploy constructor
47
+ * - addressSalt - contract address salt
48
+ * - chainId - the chainId to declare contract on
49
+ * - maxFee - maxFee for the declare transaction
50
+ * - version - transaction version
51
+ * - nonce - Nonce of the declare transaction
52
+ * @returns signature
53
+ */
54
+ public abstract signDeployAccountTransaction(
55
+ transaction: DeployAccountSignerDetails
56
+ ): Promise<Signature>;
57
+
58
+ /**
59
+ * Signs a DECLARE transaction with the starknet private key and returns the signature
60
+ *
61
+ * @param transaction
62
+ * - classHash - computed class hash. Will be replaced by ContractClass in future once class hash is present in CompiledContract
63
+ * - senderAddress - the address of the sender
64
+ * - chainId - the chainId to declare contract on
65
+ * - maxFee - maxFee for the declare transaction
66
+ * - version - transaction version
67
+ * - nonce - Nonce of the declare transaction
68
+ * @returns signature
69
+ */
70
+ public abstract signDeclareTransaction(transaction: DeclareSignerDetails): Promise<Signature>;
40
71
  }
@@ -1,10 +1,6 @@
1
1
  import { BigNumberish } from '../../utils/number';
2
2
  import { Signature } from '../lib';
3
3
 
4
- export type RawArgs = {
5
- [inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish };
6
- };
7
-
8
4
  export type Calldata = string[];
9
5
 
10
6
  export type Overrides = {
@@ -18,7 +18,7 @@ type BLOCK_HASH = FELT;
18
18
  type TXN_HASH = FELT;
19
19
  type PROTOCOL_VERSION = string;
20
20
  type TXN_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
21
- type TXN_TYPE = 'DECLARE' | 'DEPLOY' | 'INVOKE' | 'L1_HANDLER';
21
+ type TXN_TYPE = 'DECLARE' | 'DEPLOY' | 'DEPLOY_ACCOUNT' | 'INVOKE' | 'L1_HANDLER';
22
22
  type BLOCK_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
23
23
  enum BLOCK_TAG {
24
24
  'latest',
@@ -104,6 +104,15 @@ type DECLARE_TXN = COMMON_TXN_PROPERTIES & {
104
104
  class_hash: FELT;
105
105
  sender_address: ADDRESS;
106
106
  };
107
+ type DEPLOY_ACCOUNT_TXN_REQUEST = COMMON_TXN_PROPERTIES & {
108
+ class_hash: FELT;
109
+ contract_address_salt: FELT;
110
+ constructor_calldata: Array<FELT>;
111
+ };
112
+ type DECLARE_TXN_REQUEST = COMMON_TXN_PROPERTIES & {
113
+ contract_class: CONTRACT_CLASS;
114
+ sender_address: ADDRESS;
115
+ };
107
116
  type DEPLOY_TXN = {
108
117
  transaction_hash: TXN_HASH;
109
118
  class_hash: FELT;
@@ -328,7 +337,10 @@ export namespace OPENRPC {
328
337
  | Errors.INVALID_BLOCK_ID;
329
338
  };
330
339
  starknet_estimateFee: {
331
- params: { request: INVOKE_TXN; block_id: BLOCK_ID };
340
+ params: {
341
+ request: INVOKE_TXN | DECLARE_TXN_REQUEST | DEPLOY_ACCOUNT_TXN_REQUEST;
342
+ block_id: BLOCK_ID;
343
+ };
332
344
  result: FEE_ESTIMATE;
333
345
  errors:
334
346
  | Errors.CONTRACT_NOT_FOUND
@@ -384,7 +396,11 @@ export namespace OPENRPC {
384
396
  starknet_addDeclareTransaction: {
385
397
  params: {
386
398
  contract_class: CONTRACT_CLASS;
399
+ sender_address: ADDRESS;
400
+ signature: SIGNATURE;
401
+ max_fee: NUM_AS_HEX;
387
402
  version: NUM_AS_HEX;
403
+ nonce: FELT;
388
404
  };
389
405
  result: DeclaredTransaction;
390
406
  errors: Errors.INVALID_CONTRACT_CLASS;
@@ -399,6 +415,16 @@ export namespace OPENRPC {
399
415
  errors: Errors.INVALID_CONTRACT_CLASS;
400
416
  };
401
417
 
418
+ starknet_addDeployAccountTransaction: {
419
+ params: {
420
+ contract_address_salt: FELT;
421
+ constructor_calldata: Array<FELT>;
422
+ class_hash: FELT;
423
+ };
424
+ result: DeployedTransaction;
425
+ errors: Errors.INVALID_CONTRACT_CLASS;
426
+ };
427
+
402
428
  // Trace API
403
429
  starknet_traceTransaction: {
404
430
  params: { transaction_hash: TXN_HASH };
@@ -5,13 +5,13 @@ import { BigNumberish } from '../../utils/number';
5
5
  import {
6
6
  Abi,
7
7
  BlockNumber,
8
+ ContractClass,
8
9
  EntryPointType,
9
10
  RawCalldata,
10
11
  Signature,
11
12
  Status,
12
13
  TransactionStatus,
13
14
  } from '../lib';
14
- import { ContractClass } from '../provider';
15
15
 
16
16
  export type GetTransactionStatusResponse = {
17
17
  tx_status: Status;
@@ -76,10 +76,12 @@ export type CallL1Handler = {
76
76
  export namespace Sequencer {
77
77
  export type DeclareTransaction = {
78
78
  type: 'DECLARE';
79
+ sender_address: string;
79
80
  contract_class: ContractClass;
81
+ signature?: Signature;
80
82
  nonce: BigNumberish;
81
- sender_address: BigNumberish;
82
- signature: Signature;
83
+ max_fee?: BigNumberish;
84
+ version?: BigNumberish;
83
85
  };
84
86
 
85
87
  export type DeployTransaction = {
@@ -90,6 +92,17 @@ export namespace Sequencer {
90
92
  nonce?: BigNumberish;
91
93
  };
92
94
 
95
+ export type DeployAccountTransaction = {
96
+ type: 'DEPLOY_ACCOUNT';
97
+ class_hash: string;
98
+ contract_address_salt: BigNumberish;
99
+ constructor_calldata: string[];
100
+ signature?: Signature;
101
+ max_fee?: BigNumberish;
102
+ version?: BigNumberish;
103
+ nonce?: BigNumberish;
104
+ };
105
+
93
106
  export type InvokeFunctionTransaction = {
94
107
  type: 'INVOKE_FUNCTION';
95
108
  contract_address: string;
@@ -101,7 +114,11 @@ export namespace Sequencer {
101
114
  version?: BigNumberish;
102
115
  };
103
116
 
104
- export type Transaction = DeclareTransaction | DeployTransaction | InvokeFunctionTransaction;
117
+ export type Transaction =
118
+ | DeclareTransaction
119
+ | DeployTransaction
120
+ | InvokeFunctionTransaction
121
+ | DeployAccountTransaction;
105
122
 
106
123
  export type AddTransactionResponse = {
107
124
  transaction_hash: string;
@@ -209,10 +226,16 @@ export namespace Sequencer {
209
226
  result: string[];
210
227
  };
211
228
 
212
- export type EstimateFeeTransaction = Omit<
213
- InvokeFunctionTransaction,
214
- 'max_fee' | 'entry_point_type'
215
- >;
229
+ export type InvokeEstimateFee = Omit<InvokeFunctionTransaction, 'max_fee' | 'entry_point_type'>;
230
+ export type DeclareEstimateFee = Omit<DeclareTransaction, 'max_fee'>;
231
+ export type DeployAccountEstimateFee = Omit<DeployAccountTransaction, 'max_fee'>;
232
+ export type DeployEstimateFee = DeployTransaction;
233
+
234
+ export type EstimateFeeRequest =
235
+ | InvokeEstimateFee
236
+ | DeclareEstimateFee
237
+ | DeployEstimateFee
238
+ | DeployAccountEstimateFee;
216
239
 
217
240
  // Support 0.9.1 changes in a backward-compatible way
218
241
  export type EstimateFeeResponse =
@@ -308,7 +331,7 @@ export namespace Sequencer {
308
331
  QUERY: {
309
332
  blockIdentifier: BlockIdentifier;
310
333
  };
311
- REQUEST: EstimateFeeTransaction;
334
+ REQUEST: EstimateFeeRequest;
312
335
  RESPONSE: EstimateFeeResponse;
313
336
  };
314
337
  get_class_by_hash: {