starknet 10.7.1 → 10.7.2

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## [10.7.2](https://github.com/starknet-io/starknet.js/compare/v10.7.1...v10.7.2) (2026-09-08)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **paymaster:** accept a raw shortstring for the paymaster typed-data domain chainId ([4abd5ae](https://github.com/starknet-io/starknet.js/commit/4abd5aeec079e8ca14ce098d0ff8790a89aa1c62))
6
+ - **paymaster:** bind paymaster typed-data domain to the account's provider chain ([f194c61](https://github.com/starknet-io/starknet.js/commit/f194c612cd2fa2ecb6515e484f89d6f2bb72892a))
7
+ - **paymaster:** reject paymaster typed data declaring both "calls" and "Calls" ([e618f70](https://github.com/starknet-io/starknet.js/commit/e618f706fe543aa5dbce5b560098ad15d4ca341b))
8
+ - **paymaster:** validate selector and calldata shape of the appended gas-token call ([4b72d35](https://github.com/starknet-io/starknet.js/commit/4b72d35cfe19424fb707dbfdfd4e3877532f86b5))
9
+ - **paymaster:** validate the full u256 gas-token amount unconditionally ([3d1a1ec](https://github.com/starknet-io/starknet.js/commit/3d1a1ec420a769f31bb7fc94b2a68f36ae56630e))
10
+ - **paymaster:** verify calls equality for sponsored paymaster transactions too ([c403643](https://github.com/starknet-io/starknet.js/commit/c403643b580ab5953a2e737d1aa39e083d5f0262))
11
+
1
12
  ## [10.7.1](https://github.com/starknet-io/starknet.js/compare/v10.7.0...v10.7.1) (2026-08-21)
2
13
 
3
14
  ### Bug Fixes
package/dist/index.d.ts CHANGED
@@ -8936,10 +8936,38 @@ declare const getDefaultPaymasterNodeUrl: (networkName?: _NetworkName, mute?: bo
8936
8936
  * Asserts that the given calls are strictly equal, otherwise throws an error.
8937
8937
  * @param {Call[]} originalCalls - The original calls.
8938
8938
  * @param {Call[]} unsafeCalls - The unsafe calls.
8939
+ * @param {boolean} [isSponsored] - Whether the transaction is sponsored. A sponsored
8940
+ * transaction appends no gas-token fee-transfer call; a non-sponsored one appends exactly
8941
+ * one. Defaults to `false` for backward compatibility.
8939
8942
  * @throws {Error} Throws an error if the calls are not strictly equal.
8943
+ * @example
8944
+ * ```typescript
8945
+ * paymaster.assertCallsAreStrictlyEqual(originalCalls, unsafeCalls, true); // sponsored: no fee call
8946
+ * ```
8947
+ */
8948
+ declare function assertCallsAreStrictlyEqual(originalCalls: Call[], unsafeCalls: (OutsideCallV1 | OutsideCallV2)[], isSponsored?: boolean): void;
8949
+ /**
8950
+ * Asserts that a paymaster-prepared transaction is safe to sign: the typed-data domain is
8951
+ * bound to the account's own chain, and — for non-sponsored transactions — the calls and the
8952
+ * appended gas-token transfer match what the user actually requested.
8953
+ * @param {PreparedTransaction} preparedTransaction - The transaction returned by the paymaster.
8954
+ * @param {Call[]} calls - The calls originally requested by the user.
8955
+ * @param {PaymasterDetails} paymasterDetails - The fee mode and related paymaster details.
8956
+ * @param {StarknetChainId} chainId - The chain id of the account's own provider.
8957
+ * @param {BigNumberish} [maxFeeInGasToken] - Optional user-approved ceiling on the gas-token fee.
8958
+ * @throws {Error} Throws an error if any of the above safety properties do not hold.
8959
+ * @example
8960
+ * ```typescript
8961
+ * assertPaymasterTransactionSafety(
8962
+ * preparedTransaction,
8963
+ * calls,
8964
+ * { feeMode: { mode: 'default', gasToken: strkAddress } },
8965
+ * constants.StarknetChainId.SN_SEPOLIA
8966
+ * );
8967
+ * // does not throw if preparedTransaction is exactly what was requested
8968
+ * ```
8940
8969
  */
8941
- declare function assertCallsAreStrictlyEqual(originalCalls: Call[], unsafeCalls: (OutsideCallV1 | OutsideCallV2)[]): void;
8942
- declare const assertPaymasterTransactionSafety: (preparedTransaction: PreparedTransaction, calls: Call[], paymasterDetails: PaymasterDetails, maxFeeInGasToken?: BigNumberish) => void;
8970
+ declare const assertPaymasterTransactionSafety: (preparedTransaction: PreparedTransaction, calls: Call[], paymasterDetails: PaymasterDetails, chainId: _StarknetChainId, maxFeeInGasToken?: BigNumberish) => void;
8943
8971
 
8944
8972
  declare const paymaster_assertCallsAreStrictlyEqual: typeof assertCallsAreStrictlyEqual;
8945
8973
  declare const paymaster_assertPaymasterTransactionSafety: typeof assertPaymasterTransactionSafety;
@@ -16553,9 +16553,12 @@ ${indent}}` : "}";
16553
16553
  var assertGasFeeFromUnsafeCalls = (unsafeCalls, fees) => {
16554
16554
  const unsafeCall = toOutsideCallV2(unsafeCalls[unsafeCalls.length - 1]);
16555
16555
  const unsafeGasTokenCalldata = CallData.toCalldata(unsafeCall.Calldata);
16556
- const unsafeGasTokenValue = unsafeGasTokenCalldata[1];
16556
+ const unsafeGasTokenValue = uint256ToBN({
16557
+ low: unsafeGasTokenCalldata[1],
16558
+ high: unsafeGasTokenCalldata[2]
16559
+ });
16557
16560
  assert(
16558
- BigInt(unsafeGasTokenValue) === BigInt(fees),
16561
+ unsafeGasTokenValue === BigInt(fees),
16559
16562
  "Gas token value is not equal to the provided gas fees"
16560
16563
  );
16561
16564
  };
@@ -16565,12 +16568,21 @@ ${indent}}` : "}";
16565
16568
  BigInt(unsafeCall.To) === BigInt(gasToken),
16566
16569
  "Gas token address is not equal to the provided gas token"
16567
16570
  );
16571
+ assert(
16572
+ unsafeCall.Selector === getSelectorFromName("transfer"),
16573
+ "Gas token call selector is not a transfer"
16574
+ );
16575
+ assert(
16576
+ CallData.toCalldata(unsafeCall.Calldata).length === 3,
16577
+ "Gas token transfer calldata does not match the expected recipient/amount shape"
16578
+ );
16568
16579
  };
16569
- function assertCallsAreStrictlyEqual(originalCalls, unsafeCalls) {
16580
+ function assertCallsAreStrictlyEqual(originalCalls, unsafeCalls, isSponsored = false) {
16570
16581
  const baseError = "Provided calls are not strictly equal to the returned calls";
16582
+ const expectedExtraCalls = isSponsored ? 0 : 1;
16571
16583
  assert(
16572
- unsafeCalls.length - 1 === originalCalls.length,
16573
- `${baseError}: Expected ${originalCalls.length + 1} calls, got ${unsafeCalls.length}`
16584
+ unsafeCalls.length - expectedExtraCalls === originalCalls.length,
16585
+ `${baseError}: Expected ${originalCalls.length + expectedExtraCalls} calls, got ${unsafeCalls.length}`
16574
16586
  );
16575
16587
  for (let callIndex = 0; callIndex < originalCalls.length; callIndex += 1) {
16576
16588
  const originalCall = originalCalls[callIndex];
@@ -16604,21 +16616,42 @@ ${indent}}` : "}";
16604
16616
  }
16605
16617
  }
16606
16618
  }
16607
- var assertPaymasterTransactionSafety = (preparedTransaction, calls, paymasterDetails, maxFeeInGasToken) => {
16608
- if (paymasterDetails.feeMode.mode !== "sponsored") {
16609
- if (preparedTransaction.type === "invoke" || preparedTransaction.type === "deploy_and_invoke") {
16610
- const unsafeCalls = "calls" in preparedTransaction.typed_data.message ? preparedTransaction.typed_data.message.calls : preparedTransaction.typed_data.message.Calls;
16611
- assertCallsAreStrictlyEqual(calls, unsafeCalls);
16619
+ var domainFieldToFelt = (value) => {
16620
+ try {
16621
+ return toBigInt(value);
16622
+ } catch {
16623
+ return toBigInt(encodeShortString(String(value)));
16624
+ }
16625
+ };
16626
+ var assertChainIdFromTypedData = (typedData, chainId) => {
16627
+ assert(
16628
+ typedData.domain.chainId !== void 0 && domainFieldToFelt(typedData.domain.chainId) === BigInt(chainId),
16629
+ "Paymaster typed data domain chainId does not match the account's provider chain"
16630
+ );
16631
+ };
16632
+ var assertPaymasterTransactionSafety = (preparedTransaction, calls, paymasterDetails, chainId, maxFeeInGasToken) => {
16633
+ if (preparedTransaction.type === "invoke" || preparedTransaction.type === "deploy_and_invoke") {
16634
+ assertChainIdFromTypedData(preparedTransaction.typed_data, chainId);
16635
+ const { message } = preparedTransaction.typed_data;
16636
+ const hasV1Calls = "calls" in message;
16637
+ const hasV2Calls = "Calls" in message;
16638
+ assert(
16639
+ hasV1Calls !== hasV2Calls,
16640
+ 'Paymaster typed data must declare exactly one of "calls" (SNIP-9 V1) or "Calls" (SNIP-9 V2)'
16641
+ );
16642
+ const unsafeCalls = hasV1Calls ? message.calls : message.Calls;
16643
+ assertCallsAreStrictlyEqual(calls, unsafeCalls, paymasterDetails.feeMode.mode === "sponsored");
16644
+ if (paymasterDetails.feeMode.mode !== "sponsored") {
16612
16645
  assertGasTokenFromUnsafeCalls(unsafeCalls, paymasterDetails.feeMode.gasToken);
16646
+ assertGasFeeFromUnsafeCalls(
16647
+ unsafeCalls,
16648
+ preparedTransaction.fee.suggested_max_fee_in_gas_token
16649
+ );
16613
16650
  if (maxFeeInGasToken) {
16614
16651
  assert(
16615
16652
  preparedTransaction.fee.suggested_max_fee_in_gas_token <= maxFeeInGasToken,
16616
16653
  "Gas token price is too high"
16617
16654
  );
16618
- assertGasFeeFromUnsafeCalls(
16619
- unsafeCalls,
16620
- preparedTransaction.fee.suggested_max_fee_in_gas_token
16621
- );
16622
16655
  }
16623
16656
  }
16624
16657
  }
@@ -17743,6 +17776,7 @@ ${indent}}` : "}";
17743
17776
  preparedTransaction,
17744
17777
  calls,
17745
17778
  paymasterDetails,
17779
+ await this.provider.getChainId(),
17746
17780
  maxFeeInGasToken
17747
17781
  );
17748
17782
  const transaction = await this.preparePaymasterTransaction(preparedTransaction);