starknet 4.13.2 → 4.14.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 (46) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/CODE_OF_CONDUCT.md +128 -0
  3. package/README.md +2 -2
  4. package/__tests__/account.test.ts +38 -14
  5. package/__tests__/contract.test.ts +70 -57
  6. package/__tests__/defaultProvider.test.ts +14 -13
  7. package/__tests__/fixtures.ts +26 -27
  8. package/__tests__/rpcProvider.test.ts +19 -16
  9. package/__tests__/sequencerProvider.test.ts +47 -55
  10. package/__tests__/utils/utils.test.ts +10 -0
  11. package/dist/index.d.ts +112 -28
  12. package/dist/index.global.js +511 -453
  13. package/dist/index.global.js.map +1 -1
  14. package/dist/index.js +107 -49
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +107 -49
  17. package/dist/index.mjs.map +1 -1
  18. package/index.d.ts +112 -28
  19. package/index.global.js +511 -453
  20. package/index.global.js.map +1 -1
  21. package/index.js +107 -49
  22. package/index.js.map +1 -1
  23. package/index.mjs +107 -49
  24. package/index.mjs.map +1 -1
  25. package/package.json +2 -2
  26. package/src/account/default.ts +29 -7
  27. package/src/account/interface.ts +71 -5
  28. package/src/contract/contractFactory.ts +20 -13
  29. package/src/contract/default.ts +10 -1
  30. package/src/provider/default.ts +26 -11
  31. package/src/provider/interface.ts +9 -3
  32. package/src/provider/rpc.ts +15 -11
  33. package/src/provider/sequencer.ts +11 -6
  34. package/src/provider/utils.ts +19 -11
  35. package/src/types/account.ts +21 -1
  36. package/src/types/lib.ts +5 -2
  37. package/src/types/provider.ts +0 -5
  38. package/src/utils/events.ts +32 -0
  39. package/src/utils/number.ts +6 -0
  40. package/www/docs/API/account.md +156 -2
  41. package/www/docs/API/contractFactory.md +7 -11
  42. package/www/docs/API/provider.md +5 -9
  43. package/www/docs/API/utils.md +8 -0
  44. package/www/guides/account.md +89 -38
  45. package/www/guides/erc20.md +115 -59
  46. package/www/guides/intro.md +11 -4
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ __export(src_exports, {
62
62
  module.exports = __toCommonJS(src_exports);
63
63
 
64
64
  // src/contract/default.ts
65
- var import_bn2 = __toESM(require("bn.js"));
65
+ var import_bn3 = __toESM(require("bn.js"));
66
66
  var import_minimalistic_assert4 = __toESM(require("minimalistic-assert"));
67
67
 
68
68
  // src/utils/fetchPonyfill.ts
@@ -119,6 +119,7 @@ __export(number_exports, {
119
119
  assertInRange: () => assertInRange,
120
120
  bigNumberishArrayToDecimalStringArray: () => bigNumberishArrayToDecimalStringArray,
121
121
  bigNumberishArrayToHexadecimalStringArray: () => bigNumberishArrayToHexadecimalStringArray,
122
+ cleanHex: () => cleanHex,
122
123
  getDecimalString: () => getDecimalString,
123
124
  getHexString: () => getHexString,
124
125
  getHexStringArray: () => getHexStringArray,
@@ -221,6 +222,7 @@ function toFelt(num) {
221
222
  }
222
223
  return toBN(num).toString();
223
224
  }
225
+ var cleanHex = (hex) => hex.toLowerCase().replace(/^(0x)0+/, "$1");
224
226
  function assertInRange(input, lowerBound, upperBound, inputName = "") {
225
227
  const messageSuffix = inputName === "" ? "invalid length" : `invalid ${inputName} length`;
226
228
  const inputBn = toBN(input);
@@ -2652,6 +2654,8 @@ var RPCResponseParser = class {
2652
2654
  };
2653
2655
 
2654
2656
  // src/provider/utils.ts
2657
+ var import_bn2 = require("bn.js");
2658
+ var validBlockTags = ["latest", "pending"];
2655
2659
  var Block = class {
2656
2660
  constructor(_identifier) {
2657
2661
  this.hash = null;
@@ -2659,17 +2663,21 @@ var Block = class {
2659
2663
  this.tag = null;
2660
2664
  this.valueOf = () => this.number;
2661
2665
  this.toString = () => this.hash;
2662
- this.setIdentifier = function(__identifier) {
2663
- if (typeof __identifier === "string" && isHex(__identifier)) {
2664
- this.hash = __identifier;
2665
- } else if (typeof __identifier === "number") {
2666
- this.number = __identifier;
2667
- } else {
2668
- this.tag = __identifier;
2669
- }
2670
- };
2671
2666
  this.setIdentifier(_identifier);
2672
2667
  }
2668
+ setIdentifier(__identifier) {
2669
+ if (typeof __identifier === "string" && isHex(__identifier)) {
2670
+ this.hash = __identifier;
2671
+ } else if (import_bn2.BN.isBN(__identifier)) {
2672
+ this.hash = toHex(__identifier);
2673
+ } else if (typeof __identifier === "number") {
2674
+ this.number = __identifier;
2675
+ } else if (typeof __identifier === "string" && validBlockTags.includes(__identifier)) {
2676
+ this.tag = __identifier;
2677
+ } else {
2678
+ this.tag = "pending";
2679
+ }
2680
+ }
2673
2681
  get queryIdentifier() {
2674
2682
  if (this.number !== null) {
2675
2683
  return `blockNumber=${this.number}`;
@@ -2756,7 +2764,7 @@ var RpcProvider = class {
2756
2764
  contract_address: contractAddress
2757
2765
  });
2758
2766
  }
2759
- async getNonce(contractAddress, blockIdentifier = "pending") {
2767
+ async getNonceForAddress(contractAddress, blockIdentifier = "pending") {
2760
2768
  const block_id = new Block(blockIdentifier).identifier;
2761
2769
  return this.fetchEndpoint("starknet_getNonce", {
2762
2770
  contract_address: contractAddress,
@@ -2941,25 +2949,25 @@ var RpcProvider = class {
2941
2949
  async traceBlockTransactions(blockHash) {
2942
2950
  return this.fetchEndpoint("starknet_traceBlockTransactions", { block_hash: blockHash });
2943
2951
  }
2944
- async waitForTransaction(txHash, retryInterval = 8e3) {
2952
+ async waitForTransaction(txHash, successStates = ["ACCEPTED_ON_L1", "ACCEPTED_ON_L2", "PENDING"], retryInterval = 8e3) {
2953
+ const errorStates = ["REJECTED", "NOT_RECEIVED"];
2945
2954
  let { retries } = this;
2946
2955
  let onchain = false;
2956
+ let txReceipt = {};
2947
2957
  while (!onchain) {
2948
- const successStates = ["ACCEPTED_ON_L1", "ACCEPTED_ON_L2", "PENDING"];
2949
- const errorStates = ["REJECTED", "NOT_RECEIVED"];
2950
2958
  await wait(retryInterval);
2951
2959
  try {
2952
- const res = await this.getTransactionReceipt(txHash);
2953
- if (!("status" in res)) {
2960
+ txReceipt = await this.getTransactionReceipt(txHash);
2961
+ if (!("status" in txReceipt)) {
2954
2962
  const error = new Error("pending transaction");
2955
2963
  throw error;
2956
2964
  }
2957
- if (res.status && successStates.includes(res.status)) {
2965
+ if (txReceipt.status && successStates.includes(txReceipt.status)) {
2958
2966
  onchain = true;
2959
- } else if (res.status && errorStates.includes(res.status)) {
2960
- const message = res.status;
2967
+ } else if (txReceipt.status && errorStates.includes(txReceipt.status)) {
2968
+ const message = txReceipt.status;
2961
2969
  const error = new Error(message);
2962
- error.response = res;
2970
+ error.response = txReceipt;
2963
2971
  throw error;
2964
2972
  }
2965
2973
  } catch (error) {
@@ -2973,6 +2981,7 @@ var RpcProvider = class {
2973
2981
  retries -= 1;
2974
2982
  }
2975
2983
  await wait(retryInterval);
2984
+ return txReceipt;
2976
2985
  }
2977
2986
  async getTransactionCount(blockIdentifier = "pending") {
2978
2987
  const block_id = new Block(blockIdentifier).identifier;
@@ -3271,7 +3280,7 @@ var SequencerProvider = class {
3271
3280
  this.responseParser.parseGetBlockResponse
3272
3281
  );
3273
3282
  }
3274
- async getNonce(contractAddress, blockIdentifier = "pending") {
3283
+ async getNonceForAddress(contractAddress, blockIdentifier = "pending") {
3275
3284
  return this.fetchEndpoint("get_nonce", { contractAddress, blockIdentifier });
3276
3285
  }
3277
3286
  async getStorageAt(contractAddress, key, blockIdentifier = "pending") {
@@ -3401,13 +3410,13 @@ var SequencerProvider = class {
3401
3410
  async getCode(contractAddress, blockIdentifier = "pending") {
3402
3411
  return this.fetchEndpoint("get_code", { contractAddress, blockIdentifier });
3403
3412
  }
3404
- async waitForTransaction(txHash, retryInterval = 8e3) {
3413
+ async waitForTransaction(txHash, successStates = ["ACCEPTED_ON_L1", "ACCEPTED_ON_L2", "PENDING"], retryInterval = 8e3) {
3414
+ const errorStates = ["REJECTED", "NOT_RECEIVED"];
3405
3415
  let onchain = false;
3416
+ let res;
3406
3417
  while (!onchain) {
3407
3418
  await wait(retryInterval);
3408
- const res = await this.getTransactionStatus(txHash);
3409
- const successStates = ["ACCEPTED_ON_L1", "ACCEPTED_ON_L2", "PENDING"];
3410
- const errorStates = ["REJECTED", "NOT_RECEIVED"];
3419
+ res = await this.getTransactionStatus(txHash);
3411
3420
  if (successStates.includes(res.tx_status)) {
3412
3421
  onchain = true;
3413
3422
  } else if (errorStates.includes(res.tx_status)) {
@@ -3418,6 +3427,8 @@ ${res.tx_failure_reason.error_message}` : res.tx_status;
3418
3427
  throw error;
3419
3428
  }
3420
3429
  }
3430
+ const txReceipt = await this.getTransactionReceipt(txHash);
3431
+ return txReceipt;
3421
3432
  }
3422
3433
  async getTransactionStatus(txHash) {
3423
3434
  const txHashHex = toHex(toBN(txHash));
@@ -3444,11 +3455,13 @@ ${res.tx_failure_reason.error_message}` : res.tx_status;
3444
3455
  // src/provider/default.ts
3445
3456
  var Provider = class {
3446
3457
  constructor(providerOrOptions) {
3447
- if (providerOrOptions && "chainId" in providerOrOptions) {
3458
+ if (providerOrOptions instanceof Provider) {
3459
+ this.provider = providerOrOptions.provider;
3460
+ } else if (providerOrOptions instanceof RpcProvider || providerOrOptions instanceof SequencerProvider) {
3448
3461
  this.provider = providerOrOptions;
3449
- } else if (providerOrOptions == null ? void 0 : providerOrOptions.rpc) {
3462
+ } else if (providerOrOptions && "rpc" in providerOrOptions) {
3450
3463
  this.provider = new RpcProvider(providerOrOptions.rpc);
3451
- } else if (providerOrOptions == null ? void 0 : providerOrOptions.sequencer) {
3464
+ } else if (providerOrOptions && "sequencer" in providerOrOptions) {
3452
3465
  this.provider = new SequencerProvider(providerOrOptions.sequencer);
3453
3466
  } else {
3454
3467
  this.provider = new SequencerProvider();
@@ -3482,8 +3495,8 @@ var Provider = class {
3482
3495
  blockIdentifier
3483
3496
  );
3484
3497
  }
3485
- async getNonce(contractAddress, blockIdentifier) {
3486
- return this.provider.getNonce(contractAddress, blockIdentifier);
3498
+ async getNonceForAddress(contractAddress, blockIdentifier) {
3499
+ return this.provider.getNonceForAddress(contractAddress, blockIdentifier);
3487
3500
  }
3488
3501
  async getStorageAt(contractAddress, key, blockIdentifier = "pending") {
3489
3502
  return this.provider.getStorageAt(contractAddress, key, blockIdentifier);
@@ -3518,8 +3531,8 @@ var Provider = class {
3518
3531
  async getCode(contractAddress, blockIdentifier) {
3519
3532
  return this.provider.getCode(contractAddress, blockIdentifier);
3520
3533
  }
3521
- async waitForTransaction(txHash, retryInterval) {
3522
- return this.provider.waitForTransaction(txHash, retryInterval);
3534
+ async waitForTransaction(txHash, successStates, retryInterval) {
3535
+ return this.provider.waitForTransaction(txHash, successStates, retryInterval);
3523
3536
  }
3524
3537
  };
3525
3538
 
@@ -3540,7 +3553,13 @@ function parseFelt(candidate) {
3540
3553
  }
3541
3554
  function buildCall(contract, functionAbi) {
3542
3555
  return async function(...args) {
3543
- return contract.call(functionAbi.name, args);
3556
+ let blockIdentifier = null;
3557
+ args.forEach((arg) => {
3558
+ if (arg.blockIdentifier) {
3559
+ blockIdentifier = arg.blockIdentifier;
3560
+ }
3561
+ });
3562
+ return contract.call(functionAbi.name, args, { blockIdentifier });
3544
3563
  };
3545
3564
  }
3546
3565
  function buildInvoke(contract, functionAbi) {
@@ -3765,7 +3784,7 @@ var Contract = class {
3765
3784
  }
3766
3785
  if (input.type === "felt") {
3767
3786
  (0, import_minimalistic_assert4.default)(
3768
- typeof args[argPosition] === "string" || typeof args[argPosition] === "number" || args[argPosition] instanceof import_bn2.default,
3787
+ typeof args[argPosition] === "string" || typeof args[argPosition] === "number" || args[argPosition] instanceof import_bn3.default,
3769
3788
  `arg ${input.name} should be a felt (string, number, BigNumber)`
3770
3789
  );
3771
3790
  argPosition += 1;
@@ -3790,7 +3809,7 @@ var Contract = class {
3790
3809
  if (input.type === "felt*") {
3791
3810
  args[argPosition].forEach((felt) => {
3792
3811
  (0, import_minimalistic_assert4.default)(
3793
- typeof felt === "string" || typeof felt === "number" || felt instanceof import_bn2.default,
3812
+ typeof felt === "string" || typeof felt === "number" || felt instanceof import_bn3.default,
3794
3813
  `arg ${input.name} should be an array of string, number or BigNumber`
3795
3814
  );
3796
3815
  });
@@ -3803,7 +3822,7 @@ var Contract = class {
3803
3822
  );
3804
3823
  args[argPosition].forEach((felt) => {
3805
3824
  (0, import_minimalistic_assert4.default)(
3806
- typeof felt === "string" || typeof felt === "number" || felt instanceof import_bn2.default,
3825
+ typeof felt === "string" || typeof felt === "number" || felt instanceof import_bn3.default,
3807
3826
  `arg ${input.name} should be an array of string, number or BigNumber`
3808
3827
  );
3809
3828
  });
@@ -3960,32 +3979,36 @@ var ContractInterface = class {
3960
3979
  // src/contract/contractFactory.ts
3961
3980
  var import_minimalistic_assert5 = __toESM(require("minimalistic-assert"));
3962
3981
  var ContractFactory = class {
3963
- constructor(compiledContract, providerOrAccount = defaultProvider, abi = compiledContract.abi) {
3982
+ constructor(compiledContract, classHash, account, abi = compiledContract.abi) {
3964
3983
  this.abi = abi;
3965
3984
  this.compiledContract = compiledContract;
3966
- this.providerOrAccount = providerOrAccount;
3985
+ this.account = account;
3986
+ this.classHash = classHash;
3967
3987
  }
3968
3988
  async deploy(constructorCalldata, addressSalt) {
3969
- const { contract_address, transaction_hash } = await this.providerOrAccount.deployContract({
3989
+ const {
3990
+ deploy: { contract_address, transaction_hash }
3991
+ } = await this.account.declareDeploy({
3970
3992
  contract: this.compiledContract,
3993
+ classHash: this.classHash,
3971
3994
  constructorCalldata,
3972
- addressSalt
3995
+ salt: addressSalt
3973
3996
  });
3974
3997
  (0, import_minimalistic_assert5.default)(Boolean(contract_address), "Deployment of the contract failed");
3975
3998
  const contractInstance = new Contract(
3976
3999
  this.compiledContract.abi,
3977
4000
  contract_address,
3978
- this.providerOrAccount
4001
+ this.account
3979
4002
  );
3980
4003
  contractInstance.deployTransactionHash = transaction_hash;
3981
4004
  return contractInstance;
3982
4005
  }
3983
- connect(providerOrAccount) {
3984
- this.providerOrAccount = providerOrAccount;
4006
+ connect(account) {
4007
+ this.account = account;
3985
4008
  return this;
3986
4009
  }
3987
4010
  attach(address) {
3988
- return new Contract(this.abi, address, this.providerOrAccount);
4011
+ return new Contract(this.abi, address, this.account);
3989
4012
  }
3990
4013
  };
3991
4014
 
@@ -4329,6 +4352,29 @@ var Signer = class {
4329
4352
  }
4330
4353
  };
4331
4354
 
4355
+ // src/utils/events.ts
4356
+ function parseUDCEvent(txReceipt) {
4357
+ if (!txReceipt.events) {
4358
+ throw new Error("UDC emited event is empty");
4359
+ }
4360
+ const event = txReceipt.events.find(
4361
+ (it) => cleanHex(it.from_address) === cleanHex(UDC.ADDRESS)
4362
+ ) || {
4363
+ data: []
4364
+ };
4365
+ return {
4366
+ transaction_hash: txReceipt.transaction_hash,
4367
+ contract_address: event.data[0],
4368
+ address: event.data[0],
4369
+ deployer: event.data[1],
4370
+ unique: event.data[2],
4371
+ classHash: event.data[3],
4372
+ calldata_len: event.data[4],
4373
+ calldata: event.data.slice(5, 5 + parseInt(event.data[4], 16)),
4374
+ salt: event.data[event.data.length - 1]
4375
+ };
4376
+ }
4377
+
4332
4378
  // src/account/default.ts
4333
4379
  var Account = class extends Provider {
4334
4380
  constructor(providerOrOptions, address, keyPairOrSigner) {
@@ -4337,7 +4383,7 @@ var Account = class extends Provider {
4337
4383
  this.signer = "getPubKey" in keyPairOrSigner ? keyPairOrSigner : new Signer(keyPairOrSigner);
4338
4384
  }
4339
4385
  async getNonce(blockIdentifier) {
4340
- return super.getNonce(this.address, blockIdentifier);
4386
+ return super.getNonceForAddress(this.address, blockIdentifier);
4341
4387
  }
4342
4388
  async estimateFee(calls, estimateFeeDetails) {
4343
4389
  return this.estimateInvokeFee(calls, estimateFeeDetails);
@@ -4424,7 +4470,7 @@ var Account = class extends Provider {
4424
4470
  }
4425
4471
  async estimateDeployFee({
4426
4472
  classHash,
4427
- salt,
4473
+ salt = "0",
4428
4474
  unique = true,
4429
4475
  constructorCalldata = [],
4430
4476
  additionalCalls = []
@@ -4505,9 +4551,10 @@ var Account = class extends Provider {
4505
4551
  unique = true,
4506
4552
  constructorCalldata = [],
4507
4553
  additionalCalls = []
4508
- }, transactionsDetail = {}) {
4554
+ }, invocationsDetails = {}) {
4509
4555
  const compiledConstructorCallData = compileCalldata(constructorCalldata);
4510
4556
  const callsArray = Array.isArray(additionalCalls) ? additionalCalls : [additionalCalls];
4557
+ const deploySalt = salt ?? randomAddress();
4511
4558
  return this.execute(
4512
4559
  [
4513
4560
  {
@@ -4515,7 +4562,7 @@ var Account = class extends Provider {
4515
4562
  entrypoint: UDC.ENTRYPOINT,
4516
4563
  calldata: [
4517
4564
  classHash,
4518
- salt,
4565
+ deploySalt,
4519
4566
  toCairoBool(unique),
4520
4567
  compiledConstructorCallData.length,
4521
4568
  ...compiledConstructorCallData
@@ -4524,9 +4571,20 @@ var Account = class extends Provider {
4524
4571
  ...callsArray
4525
4572
  ],
4526
4573
  void 0,
4527
- transactionsDetail
4574
+ invocationsDetails
4528
4575
  );
4529
4576
  }
4577
+ async deployContract(payload, details = {}) {
4578
+ const deployTx = await this.deploy(payload, details);
4579
+ const txReceipt = await this.waitForTransaction(deployTx.transaction_hash, ["ACCEPTED_ON_L2"]);
4580
+ return parseUDCEvent(txReceipt);
4581
+ }
4582
+ async declareDeploy({ classHash, contract, constructorCalldata }, details) {
4583
+ const { transaction_hash } = await this.declare({ contract, classHash }, details);
4584
+ const declare = await this.waitForTransaction(transaction_hash, ["ACCEPTED_ON_L2"]);
4585
+ const deploy = await this.deployContract({ classHash, constructorCalldata }, details);
4586
+ return { declare: { ...declare, class_hash: classHash }, deploy };
4587
+ }
4530
4588
  async deployAccount({
4531
4589
  classHash,
4532
4590
  constructorCalldata = [],