viem 2.55.10 → 2.55.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/_cjs/actions/wallet/prepareTransactionRequest.js +12 -12
  3. package/_cjs/actions/wallet/prepareTransactionRequest.js.map +1 -1
  4. package/_cjs/actions/wallet/sendTransaction.js +24 -12
  5. package/_cjs/actions/wallet/sendTransaction.js.map +1 -1
  6. package/_cjs/actions/wallet/sendTransactionSync.js +24 -12
  7. package/_cjs/actions/wallet/sendTransactionSync.js.map +1 -1
  8. package/_cjs/chains/definitions/story.js +7 -7
  9. package/_cjs/chains/definitions/story.js.map +1 -1
  10. package/_cjs/chains/definitions/storyAeneid.js +8 -8
  11. package/_cjs/chains/definitions/storyAeneid.js.map +1 -1
  12. package/_cjs/clients/createClient.js +1 -0
  13. package/_cjs/clients/createClient.js.map +1 -1
  14. package/_cjs/errors/typedData.js +11 -1
  15. package/_cjs/errors/typedData.js.map +1 -1
  16. package/_cjs/errors/version.js +1 -1
  17. package/_cjs/index.js +5 -4
  18. package/_cjs/index.js.map +1 -1
  19. package/_cjs/tempo/Abis.js +642 -253
  20. package/_cjs/tempo/Abis.js.map +1 -1
  21. package/_cjs/tempo/Decorator.js +7 -0
  22. package/_cjs/tempo/Decorator.js.map +1 -1
  23. package/_cjs/tempo/actions/earn/deployment.js +654 -0
  24. package/_cjs/tempo/actions/earn/deployment.js.map +1 -0
  25. package/_cjs/tempo/actions/earn.js +60 -17
  26. package/_cjs/tempo/actions/earn.js.map +1 -1
  27. package/_cjs/tempo/actions/token.js +18 -6
  28. package/_cjs/tempo/actions/token.js.map +1 -1
  29. package/_cjs/tempo/actions/zone.js +11 -1
  30. package/_cjs/tempo/actions/zone.js.map +1 -1
  31. package/_cjs/tempo/chainConfig.js +24 -23
  32. package/_cjs/tempo/chainConfig.js.map +1 -1
  33. package/_cjs/tempo/internal/WithdrawalSenderTag.js +2 -2
  34. package/_cjs/tempo/internal/WithdrawalSenderTag.js.map +1 -1
  35. package/_cjs/tempo/zones/Abis.js +17 -0
  36. package/_cjs/tempo/zones/Abis.js.map +1 -1
  37. package/_cjs/tokens/definitions/usdc.js +7 -0
  38. package/_cjs/tokens/definitions/usdc.js.map +1 -1
  39. package/_cjs/utils/promise/withRetry.js +2 -2
  40. package/_cjs/utils/promise/withRetry.js.map +1 -1
  41. package/_cjs/utils/typedData.js +3 -0
  42. package/_cjs/utils/typedData.js.map +1 -1
  43. package/_esm/actions/wallet/prepareTransactionRequest.js +14 -13
  44. package/_esm/actions/wallet/prepareTransactionRequest.js.map +1 -1
  45. package/_esm/actions/wallet/sendTransaction.js +24 -12
  46. package/_esm/actions/wallet/sendTransaction.js.map +1 -1
  47. package/_esm/actions/wallet/sendTransactionSync.js +24 -12
  48. package/_esm/actions/wallet/sendTransactionSync.js.map +1 -1
  49. package/_esm/chains/definitions/story.js +7 -7
  50. package/_esm/chains/definitions/story.js.map +1 -1
  51. package/_esm/chains/definitions/storyAeneid.js +8 -8
  52. package/_esm/chains/definitions/storyAeneid.js.map +1 -1
  53. package/_esm/clients/createClient.js +4 -3
  54. package/_esm/clients/createClient.js.map +1 -1
  55. package/_esm/errors/typedData.js +9 -0
  56. package/_esm/errors/typedData.js.map +1 -1
  57. package/_esm/errors/version.js +1 -1
  58. package/_esm/index.js +1 -1
  59. package/_esm/index.js.map +1 -1
  60. package/_esm/tempo/Abis.js +643 -254
  61. package/_esm/tempo/Abis.js.map +1 -1
  62. package/_esm/tempo/Decorator.js +7 -0
  63. package/_esm/tempo/Decorator.js.map +1 -1
  64. package/_esm/tempo/actions/earn/deployment.js +967 -0
  65. package/_esm/tempo/actions/earn/deployment.js.map +1 -0
  66. package/_esm/tempo/actions/earn.js +47 -17
  67. package/_esm/tempo/actions/earn.js.map +1 -1
  68. package/_esm/tempo/actions/token.js +21 -8
  69. package/_esm/tempo/actions/token.js.map +1 -1
  70. package/_esm/tempo/actions/zone.js +11 -1
  71. package/_esm/tempo/actions/zone.js.map +1 -1
  72. package/_esm/tempo/chainConfig.js +26 -28
  73. package/_esm/tempo/chainConfig.js.map +1 -1
  74. package/_esm/tempo/internal/WithdrawalSenderTag.js +3 -3
  75. package/_esm/tempo/internal/WithdrawalSenderTag.js.map +1 -1
  76. package/_esm/tempo/zones/Abis.js +17 -0
  77. package/_esm/tempo/zones/Abis.js.map +1 -1
  78. package/_esm/tokens/definitions/usdc.js +7 -0
  79. package/_esm/tokens/definitions/usdc.js.map +1 -1
  80. package/_esm/utils/promise/withRetry.js +2 -2
  81. package/_esm/utils/promise/withRetry.js.map +1 -1
  82. package/_esm/utils/typedData.js +4 -1
  83. package/_esm/utils/typedData.js.map +1 -1
  84. package/_types/actions/wallet/prepareTransactionRequest.d.ts.map +1 -1
  85. package/_types/actions/wallet/sendTransaction.d.ts.map +1 -1
  86. package/_types/actions/wallet/sendTransactionSync.d.ts.map +1 -1
  87. package/_types/chains/definitions/story.d.ts +7 -7
  88. package/_types/chains/definitions/storyAeneid.d.ts +8 -8
  89. package/_types/clients/createClient.d.ts +3 -3
  90. package/_types/clients/createClient.d.ts.map +1 -1
  91. package/_types/errors/typedData.d.ts +8 -0
  92. package/_types/errors/typedData.d.ts.map +1 -1
  93. package/_types/errors/version.d.ts +1 -1
  94. package/_types/index.d.ts +1 -1
  95. package/_types/index.d.ts.map +1 -1
  96. package/_types/tempo/Abis.d.ts +945 -388
  97. package/_types/tempo/Abis.d.ts.map +1 -1
  98. package/_types/tempo/Decorator.d.ts +18 -0
  99. package/_types/tempo/Decorator.d.ts.map +1 -1
  100. package/_types/tempo/actions/earn/deployment.d.ts +1710 -0
  101. package/_types/tempo/actions/earn/deployment.d.ts.map +1 -0
  102. package/_types/tempo/actions/earn.d.ts +1142 -535
  103. package/_types/tempo/actions/earn.d.ts.map +1 -1
  104. package/_types/tempo/actions/token.d.ts +1 -1
  105. package/_types/tempo/actions/token.d.ts.map +1 -1
  106. package/_types/tempo/actions/zone.d.ts.map +1 -1
  107. package/_types/tempo/chainConfig.d.ts.map +1 -1
  108. package/_types/tempo/internal/WithdrawalSenderTag.d.ts +2 -1
  109. package/_types/tempo/internal/WithdrawalSenderTag.d.ts.map +1 -1
  110. package/_types/tempo/zones/Abis.d.ts +48 -0
  111. package/_types/tempo/zones/Abis.d.ts.map +1 -1
  112. package/_types/tokens/definitions/usdc.d.ts +7 -0
  113. package/_types/tokens/definitions/usdc.d.ts.map +1 -1
  114. package/_types/tokens/sets.d.ts +14 -0
  115. package/_types/tokens/sets.d.ts.map +1 -1
  116. package/_types/utils/typedData.d.ts.map +1 -1
  117. package/actions/wallet/prepareTransactionRequest.ts +18 -17
  118. package/actions/wallet/sendTransaction.ts +25 -10
  119. package/actions/wallet/sendTransactionSync.ts +25 -10
  120. package/chains/definitions/story.ts +7 -7
  121. package/chains/definitions/storyAeneid.ts +8 -8
  122. package/clients/createClient.ts +4 -3
  123. package/errors/typedData.ts +13 -0
  124. package/errors/version.ts +1 -1
  125. package/index.ts +2 -0
  126. package/package.json +1 -1
  127. package/tempo/Abis.ts +644 -254
  128. package/tempo/Decorator.ts +41 -0
  129. package/tempo/actions/earn/deployment.ts +1427 -0
  130. package/tempo/actions/earn.ts +83 -63
  131. package/tempo/actions/token.ts +60 -9
  132. package/tempo/actions/zone.ts +10 -1
  133. package/tempo/chainConfig.ts +30 -27
  134. package/tempo/internal/WithdrawalSenderTag.ts +5 -4
  135. package/tempo/zones/Abis.ts +17 -0
  136. package/tokens/definitions/usdc.ts +7 -0
  137. package/utils/promise/withRetry.ts +4 -4
  138. package/utils/typedData.ts +5 -0
@@ -67,6 +67,9 @@ import * as policyActions from './policy.js'
67
67
  import * as tokenActions from './token.js'
68
68
  import * as zoneActions from './zone.js'
69
69
 
70
+ // biome-ignore lint/performance/noBarrelFile: namespace module
71
+ export * from './earn/deployment.js'
72
+
70
73
  /** TIP-403 policy ID that allows every sender, recipient, and mint recipient. */
71
74
  export const alwaysAllowPolicyId = 1n
72
75
 
@@ -923,7 +926,7 @@ export async function depositSharesSync<
923
926
  caller: args.caller,
924
927
  earnShareAmount: args.earnShares,
925
928
  receipt,
926
- receivedVenueShareAmount: args.receivedVenueShares,
929
+ receivedVenueShareAmount: args.receivedEngineShares,
927
930
  recipient: args.receiver,
928
931
  venueShareAmount: args.requestedVenueShares,
929
932
  }
@@ -1039,7 +1042,9 @@ export namespace privateDeposit {
1039
1042
  zonePortal: portalAddress,
1040
1043
  }),
1041
1044
  ])
1042
- const assetToken = parameters.assetToken ?? config.vaultAsset
1045
+ const assetToken = parameters.assetToken ?? config.privateAsset
1046
+ if (!isAddressEqual(assetToken, config.privateAsset))
1047
+ throw new Error('`assetToken` must match the Zone gateway private asset.')
1043
1048
  const { encrypted, keyIndex } =
1044
1049
  await zoneActions.encryptedDeposit.prepareRecipient(client, {
1045
1050
  ...readParameters,
@@ -1049,18 +1054,13 @@ export namespace privateDeposit {
1049
1054
  zoneId: config.zoneId,
1050
1055
  })
1051
1056
  const shareAmountMin = resolveMinimumShareAmount(parameters)
1052
- const direct = isAddressEqual(assetToken, config.vaultAsset)
1053
1057
  const data = encodeAbiParameters(Abis.earnRouterCallbackData, [
1054
1058
  {
1055
1059
  actionId,
1056
- earnVault: config.vault,
1057
1060
  flow: 0,
1058
1061
  minEarnShares: shareAmountMin,
1059
1062
  minOutputAmount: 0n,
1060
- minVaultAssets: direct
1061
- ? assetAmount
1062
- : (parameters.vaultAssetAmountMin ?? 0n),
1063
- outputToken: config.shareToken,
1063
+ minVaultAssets: parameters.vaultAssetAmountMin ?? assetAmount,
1064
1064
  zoneReturn: { encrypted, keyIndex, refundRecipient: recoveryRecipient },
1065
1065
  },
1066
1066
  ])
@@ -1084,9 +1084,9 @@ export namespace privateDeposit {
1084
1084
  export type Args = PrivatePreparationParameters & {
1085
1085
  /** Assets withdrawn from the Zone, base units. */
1086
1086
  assetAmount: bigint
1087
- /** Asset token withdrawn from the Zone. @default vault asset */
1087
+ /** Private asset withdrawn from the Zone. @default gateway private asset */
1088
1088
  assetToken?: Address | undefined
1089
- /** Minimum vault assets accepted after swapping `assetToken`. @default `0n` */
1089
+ /** Minimum vault assets accepted after conversion. @default `assetAmount` */
1090
1090
  vaultAssetAmountMin?: bigint | undefined
1091
1091
  } & MinimumShareAmountParameters
1092
1092
  export type ReturnValue = PreparedZoneRequest
@@ -1429,15 +1429,15 @@ export type FeeConfig = {
1429
1429
  excess: {
1430
1430
  /** Excess fee recipient. */
1431
1431
  account: Address
1432
- /** Annual target growth rate, scaled to 18 decimals. */
1433
- annualTargetRate: bigint
1432
+ /** Annual target growth rate in basis points. */
1433
+ annualTargetRateBps: number
1434
1434
  /** Whether the excess fee is active. */
1435
1435
  enabled: boolean
1436
- /** Rate applied above the target, scaled to 18 decimals. */
1437
- excessFeeRate: bigint
1436
+ /** Rate applied above the target in basis points. */
1437
+ excessFeeRateBps: number
1438
1438
  }
1439
- /** Fixed fee recipients and their 18-decimal rates. */
1440
- fixedFees: readonly { account: Address; rate: bigint }[]
1439
+ /** Fixed fee recipients and their rates in basis points. */
1440
+ fixedFees: readonly { account: Address; rateBps: number }[]
1441
1441
  }
1442
1442
 
1443
1443
  /** Pending vault fee amounts. */
@@ -2419,9 +2419,9 @@ export namespace privateRedeem {
2419
2419
  zonePortal: portalAddress,
2420
2420
  }),
2421
2421
  ])
2422
- const assetToken = parameters.assetToken ?? config.vaultAsset
2423
- if (isAddressEqual(assetToken, config.shareToken))
2424
- throw new Error('`assetToken` cannot be the Earn share token.')
2422
+ const assetToken = parameters.assetToken ?? config.privateAsset
2423
+ if (!isAddressEqual(assetToken, config.privateAsset))
2424
+ throw new Error('`assetToken` must match the Zone gateway private asset.')
2425
2425
 
2426
2426
  const [{ encrypted, keyIndex }, assetAmountMin] = await Promise.all([
2427
2427
  zoneActions.encryptedDeposit.prepareRecipient(client, {
@@ -2447,16 +2447,13 @@ export namespace privateRedeem {
2447
2447
  return EarnShares.minimumOutput(assetAmount, parameters.slippageBps)
2448
2448
  })(),
2449
2449
  ])
2450
- const direct = isAddressEqual(assetToken, config.vaultAsset)
2451
2450
  const data = encodeAbiParameters(Abis.earnRouterCallbackData, [
2452
2451
  {
2453
2452
  actionId,
2454
- earnVault: config.vault,
2455
2453
  flow: 1,
2456
2454
  minEarnShares: 0n,
2457
- minOutputAmount: direct ? 0n : assetAmountMin,
2458
- minVaultAssets: direct ? assetAmountMin : 1n,
2459
- outputToken: assetToken,
2455
+ minOutputAmount: assetAmountMin,
2456
+ minVaultAssets: assetAmountMin,
2460
2457
  zoneReturn: { encrypted, keyIndex, refundRecipient: recoveryRecipient },
2461
2458
  },
2462
2459
  ])
@@ -2480,31 +2477,24 @@ export namespace privateRedeem {
2480
2477
  PrivatePreparationParameters & {
2481
2478
  /** Earn shares withdrawn from the Zone, base units. */
2482
2479
  shareAmount: bigint
2483
- } & (
2484
- | ({
2485
- /** Asset token returned to the Zone. @default vault asset */
2486
- assetToken?: undefined
2487
- } & OneOf<
2488
- | {
2489
- /** Minimum assets returned to the Zone. */
2490
- assetAmountMin: bigint
2491
- }
2492
- | {
2493
- /** Quoted assets returned to the Zone. */
2494
- assetAmount: bigint
2495
- /** Slippage tolerance under `assetAmount` (50 = 0.5%). */
2496
- slippageBps: number
2497
- }
2498
- | {
2499
- /** Slippage tolerance under a live vault quote (50 = 0.5%). */
2500
- slippageBps: number
2501
- }
2502
- >)
2503
- | ({
2504
- /** Asset token returned to the Zone after a swap. */
2505
- assetToken: Address
2506
- } & MinimumAssetAmountParameters)
2507
- )
2480
+ /** Private asset returned to the Zone. Must match the gateway. @default gateway private asset */
2481
+ assetToken?: Address | undefined
2482
+ } & OneOf<
2483
+ | {
2484
+ /** Minimum assets returned to the Zone. */
2485
+ assetAmountMin: bigint
2486
+ }
2487
+ | {
2488
+ /** Quoted assets returned to the Zone. */
2489
+ assetAmount: bigint
2490
+ /** Slippage tolerance under `assetAmount` (50 = 0.5%). */
2491
+ slippageBps: number
2492
+ }
2493
+ | {
2494
+ /** Slippage tolerance under a live vault quote (50 = 0.5%). */
2495
+ slippageBps: number
2496
+ }
2497
+ >
2508
2498
  export type ReturnValue = PreparedZoneRequest
2509
2499
  export type ErrorType = BaseErrorType
2510
2500
  }
@@ -3006,19 +2996,6 @@ export namespace withdrawExactSync {
3006
2996
  export type ErrorType = BaseErrorType
3007
2997
  }
3008
2998
 
3009
- type MinimumAssetAmountParameters = OneOf<
3010
- | {
3011
- /** Minimum assets returned to the Zone. */
3012
- assetAmountMin: bigint
3013
- }
3014
- | {
3015
- /** Quoted assets returned to the Zone. */
3016
- assetAmount: bigint
3017
- /** Slippage tolerance under `assetAmount` (50 = 0.5%). */
3018
- slippageBps: number
3019
- }
3020
- >
3021
-
3022
2999
  type MinimumShareAmountParameters = OneOf<
3023
3000
  | {
3024
3001
  /** Minimum Earn shares returned to the Zone. */
@@ -3132,7 +3109,16 @@ async function getZoneGatewayConfig<chain extends Chain | undefined>(
3132
3109
  },
3133
3110
  ) {
3134
3111
  const { flow, gateway, vault, zoneId, zonePortal, ...rest } = parameters
3135
- const [vaultAsset, shareToken, supportsFlow] = await multicall(client, {
3112
+ const [
3113
+ vaultAsset,
3114
+ shareToken,
3115
+ allowedZoneId,
3116
+ routerVault,
3117
+ privateAsset,
3118
+ routerVaultAsset,
3119
+ routerShareToken,
3120
+ supportsFlow,
3121
+ ] = await multicall(client, {
3136
3122
  ...rest,
3137
3123
  allowFailure: false,
3138
3124
  contracts: [
@@ -3146,6 +3132,31 @@ async function getZoneGatewayConfig<chain extends Chain | undefined>(
3146
3132
  address: vault,
3147
3133
  functionName: 'earnShare',
3148
3134
  },
3135
+ {
3136
+ abi: Abis.earnRouter,
3137
+ address: gateway,
3138
+ functionName: 'allowedZoneId',
3139
+ },
3140
+ {
3141
+ abi: Abis.earnRouter,
3142
+ address: gateway,
3143
+ functionName: 'earnVault',
3144
+ },
3145
+ {
3146
+ abi: Abis.earnRouter,
3147
+ address: gateway,
3148
+ functionName: 'privateAsset',
3149
+ },
3150
+ {
3151
+ abi: Abis.earnRouter,
3152
+ address: gateway,
3153
+ functionName: 'vaultAsset',
3154
+ },
3155
+ {
3156
+ abi: Abis.earnRouter,
3157
+ address: gateway,
3158
+ functionName: 'earnShare',
3159
+ },
3149
3160
  {
3150
3161
  abi: Abis.earnRouter,
3151
3162
  address: gateway,
@@ -3156,7 +3167,16 @@ async function getZoneGatewayConfig<chain extends Chain | undefined>(
3156
3167
  deployless: true,
3157
3168
  })
3158
3169
  if (!supportsFlow) throw new Error('Zone gateway flow is not supported.')
3170
+ if (allowedZoneId !== zoneId)
3171
+ throw new Error('Zone gateway is configured for a different Zone.')
3172
+ if (!isAddressEqual(routerVault, vault))
3173
+ throw new Error('Zone gateway is configured for a different Earn vault.')
3174
+ if (!isAddressEqual(routerVaultAsset, vaultAsset))
3175
+ throw new Error('Zone gateway vault asset does not match the Earn vault.')
3176
+ if (!isAddressEqual(routerShareToken, shareToken))
3177
+ throw new Error('Zone gateway share token does not match the Earn vault.')
3159
3178
  return {
3179
+ privateAsset,
3160
3180
  shareToken,
3161
3181
  vault,
3162
3182
  vaultAsset,
@@ -4,9 +4,15 @@ import { TokenId, TokenRole } from 'ox/tempo'
4
4
  import type { Account } from '../../accounts/types.js'
5
5
  import { parseAccount } from '../../accounts/utils/parseAccount.js'
6
6
  import { estimateContractGas } from '../../actions/public/estimateContractGas.js'
7
- import { multicall } from '../../actions/public/multicall.js'
8
- import type { ReadContractReturnType } from '../../actions/public/readContract.js'
9
- import { readContract } from '../../actions/public/readContract.js'
7
+ import {
8
+ type MulticallParameters,
9
+ type MulticallReturnType,
10
+ multicall,
11
+ } from '../../actions/public/multicall.js'
12
+ import {
13
+ type ReadContractReturnType,
14
+ readContract,
15
+ } from '../../actions/public/readContract.js'
10
16
  import {
11
17
  type SimulateContractReturnType,
12
18
  simulateContract,
@@ -1399,7 +1405,7 @@ export async function getMetadata<chain extends Chain | undefined>(
1399
1405
  }
1400
1406
 
1401
1407
  if (TokenId.fromAddress(address) === TokenId.fromAddress(Addresses.pathUsd))
1402
- return multicall(client, {
1408
+ return readMetadataContracts(client, {
1403
1409
  ...rest,
1404
1410
  contracts: [
1405
1411
  {
@@ -1433,8 +1439,6 @@ export async function getMetadata<chain extends Chain | undefined>(
1433
1439
  functionName: 'totalSupply',
1434
1440
  },
1435
1441
  ] as const,
1436
- allowFailure: true,
1437
- deployless: true,
1438
1442
  }).then(([currency, decimals, logoURI, name, symbol, totalSupply]) => ({
1439
1443
  name: unwrapMulticallResult(name),
1440
1444
  symbol: unwrapMulticallResult(symbol),
@@ -1445,7 +1449,7 @@ export async function getMetadata<chain extends Chain | undefined>(
1445
1449
  ...overrides,
1446
1450
  }))
1447
1451
 
1448
- return multicall(client, {
1452
+ return readMetadataContracts(client, {
1449
1453
  ...rest,
1450
1454
  contracts: [
1451
1455
  {
@@ -1499,8 +1503,6 @@ export async function getMetadata<chain extends Chain | undefined>(
1499
1503
  functionName: 'transferPolicyId',
1500
1504
  },
1501
1505
  ] as const,
1502
- allowFailure: true,
1503
- deployless: true,
1504
1506
  }).then(
1505
1507
  ([
1506
1508
  currency,
@@ -1529,6 +1531,55 @@ export async function getMetadata<chain extends Chain | undefined>(
1529
1531
  )
1530
1532
  }
1531
1533
 
1534
+ async function readMetadataContracts<
1535
+ chain extends Chain | undefined,
1536
+ const contracts extends readonly unknown[],
1537
+ >(
1538
+ client: Client<Transport, chain>,
1539
+ parameters: Pick<
1540
+ MulticallParameters<contracts>,
1541
+ | 'blockNumber'
1542
+ | 'blockOverrides'
1543
+ | 'blockTag'
1544
+ | 'contracts'
1545
+ | 'stateOverride'
1546
+ >,
1547
+ ): Promise<MulticallReturnType<contracts>>
1548
+ async function readMetadataContracts<chain extends Chain | undefined>(
1549
+ client: Client<Transport, chain>,
1550
+ parameters: Pick<
1551
+ MulticallParameters,
1552
+ | 'blockNumber'
1553
+ | 'blockOverrides'
1554
+ | 'blockTag'
1555
+ | 'contracts'
1556
+ | 'stateOverride'
1557
+ >,
1558
+ ): Promise<MulticallReturnType> {
1559
+ // Preserve the action's deployless default unless the client overrides it.
1560
+ if (client.batch?.multicall === undefined)
1561
+ return multicall(client, {
1562
+ ...parameters,
1563
+ allowFailure: true,
1564
+ deployless: true,
1565
+ })
1566
+
1567
+ const { contracts, ...rest } = parameters
1568
+ const results = await Promise.allSettled(
1569
+ contracts.map((contract) =>
1570
+ readContract(client, {
1571
+ ...rest,
1572
+ ...contract,
1573
+ }),
1574
+ ),
1575
+ )
1576
+ return results.map((result) =>
1577
+ result.status === 'fulfilled'
1578
+ ? { result: result.value, status: 'success' }
1579
+ : { error: result.reason, status: 'failure' },
1580
+ )
1581
+ }
1582
+
1532
1583
  function unwrapMulticallResult<result>(
1533
1584
  response:
1534
1585
  | { result: result; status: 'success' }
@@ -29,6 +29,7 @@ import { zeroHash } from '../../constants/bytes.js'
29
29
  import type { BaseErrorType } from '../../errors/base.js'
30
30
  import type { Chain, GetChainParameter } from '../../types/chain.js'
31
31
  import type { Compute, UnionOmit } from '../../types/utils.js'
32
+ import { parseEventLogs } from '../../utils/abi/parseEventLogs.js'
32
33
  import type { RequestErrorType } from '../../utils/buildRequest.js'
33
34
  import { type ObserveErrorType, observe } from '../../utils/observe.js'
34
35
  import { type PollErrorType, poll } from '../../utils/poll.js'
@@ -1547,8 +1548,16 @@ export async function requestWithdrawalSync<
1547
1548
  gas: parameters.gas ?? defaultWithdrawalGas,
1548
1549
  throwOnReceiptRevert,
1549
1550
  } as never)
1551
+ const [event] = parseEventLogs({
1552
+ abi: ZoneAbis.zoneOutbox,
1553
+ logs: receipt.logs,
1554
+ eventName: 'WithdrawalRequested',
1555
+ strict: true,
1556
+ })
1557
+ if (!event) throw new Error('`WithdrawalRequested` event not found.')
1550
1558
  const senderTag = WithdrawalSenderTag.from({
1551
- sender: account_.address,
1559
+ fallbackNonce: event.args.fallbackNonce,
1560
+ sender: event.args.sender,
1552
1561
  transactionHash: receipt.transactionHash,
1553
1562
  })
1554
1563
  return { receipt, senderTag }
@@ -116,6 +116,36 @@ export const chainConfig = {
116
116
  if (request.account?.source !== 'multisig') delete request.account
117
117
  }
118
118
 
119
+ // Register concurrency before account preparation performs storage or
120
+ // network I/O so overlapping requests cannot miss each other.
121
+ const useExpiringNonce = await (async () => {
122
+ if (request.nonceKey === 'expiring' || request.nonceKey === maxUint256)
123
+ return true
124
+ if (multisig) return false
125
+ if (request.feePayer && typeof request.nonceKey === 'undefined')
126
+ return true
127
+ const account = request.account as
128
+ | Account
129
+ | MultisigAccount
130
+ | Address
131
+ | undefined
132
+ const address = typeof account === 'string' ? account : account?.address
133
+ if (address && typeof request.nonceKey === 'undefined')
134
+ return await Concurrent.detect(address.toLowerCase())
135
+ return false
136
+ })()
137
+
138
+ if (useExpiringNonce) {
139
+ request.nonceKey = maxUint256
140
+ request.nonce = 0
141
+ if (typeof request.validAfter === 'undefined')
142
+ request.validAfter = randomValidAfter()
143
+ if (typeof request.validBefore === 'undefined')
144
+ request.validBefore = Math.floor(Date.now() / 1000) + maxExpirySecs
145
+ } else if (typeof request.nonceKey !== 'undefined') {
146
+ request.nonce = typeof request.nonce === 'number' ? request.nonce : 0
147
+ }
148
+
119
149
  if (
120
150
  !request.keyAuthorization &&
121
151
  request.account?.source === 'accessKey'
@@ -156,33 +186,6 @@ export const chainConfig = {
156
186
  }
157
187
  }
158
188
 
159
- // Use expiring nonces for concurrent transactions (TIP-1009).
160
- // When nonceKey is 'expiring', feePayer is specified, or concurrent requests
161
- // are detected, we use expiring nonces (nonceKey = uint256.max) with a
162
- // validBefore timestamp.
163
- const useExpiringNonce = await (async () => {
164
- if (request.nonceKey === 'expiring') return true
165
- if (multisig) return false
166
- if (request.feePayer && typeof request.nonceKey === 'undefined')
167
- return true
168
- const address = request.account?.address
169
- if (address && typeof request.nonceKey === 'undefined')
170
- return await Concurrent.detect(address)
171
- return false
172
- })()
173
-
174
- if (useExpiringNonce) {
175
- request.nonceKey = maxUint256
176
- request.nonce = 0
177
- if (typeof request.validAfter === 'undefined')
178
- request.validAfter = randomValidAfter()
179
- if (typeof request.validBefore === 'undefined')
180
- request.validBefore = Math.floor(Date.now() / 1000) + maxExpirySecs
181
- } else if (typeof request.nonceKey !== 'undefined') {
182
- // Explicit nonceKey provided (2D nonce mode)
183
- request.nonce = typeof request.nonce === 'number' ? request.nonce : 0
184
- }
185
-
186
189
  if (!request.feeToken && request.chain?.feeToken)
187
190
  request.feeToken = request.chain.feeToken
188
191
 
@@ -1,19 +1,20 @@
1
1
  import type { Address } from 'abitype'
2
2
  import { AbiParameters, Hash, type Hex } from 'ox'
3
3
 
4
- /** Derives a withdrawal sender tag from its sender and transaction hash. @internal */
4
+ /** Derives a user withdrawal sender tag. @internal */
5
5
  export function from(options: from.Options): Hex.Hex {
6
- const { sender, transactionHash } = options
6
+ const { fallbackNonce, sender, transactionHash } = options
7
7
  return Hash.keccak256(
8
8
  AbiParameters.encodePacked(
9
- ['address', 'bytes32'],
10
- [sender, transactionHash],
9
+ ['address', 'bytes32', 'uint64'],
10
+ [sender, transactionHash, fallbackNonce],
11
11
  ),
12
12
  )
13
13
  }
14
14
 
15
15
  export declare namespace from {
16
16
  type Options = {
17
+ fallbackNonce: bigint
17
18
  sender: Address
18
19
  transactionHash: Hex.Hex
19
20
  }
@@ -168,6 +168,23 @@ export const zonePortal = [
168
168
  ] as const
169
169
 
170
170
  export const zoneOutbox = [
171
+ {
172
+ name: 'WithdrawalRequested',
173
+ type: 'event',
174
+ inputs: [
175
+ { name: 'withdrawalIndex', type: 'uint64', indexed: true },
176
+ { name: 'sender', type: 'address', indexed: true },
177
+ { name: 'token', type: 'address', indexed: false },
178
+ { name: 'to', type: 'address', indexed: false },
179
+ { name: 'amount', type: 'uint128', indexed: false },
180
+ { name: 'fee', type: 'uint128', indexed: false },
181
+ { name: 'memo', type: 'bytes32', indexed: false },
182
+ { name: 'gasLimit', type: 'uint64', indexed: false },
183
+ { name: 'fallbackNonce', type: 'uint64', indexed: false },
184
+ { name: 'data', type: 'bytes', indexed: false },
185
+ { name: 'revealTo', type: 'bytes', indexed: false },
186
+ ],
187
+ },
171
188
  {
172
189
  name: 'requestWithdrawal',
173
190
  type: 'function',
@@ -40,6 +40,7 @@ export const usdc = /*#__PURE__*/ defineToken({
40
40
  137: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', // polygon
41
41
  143: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603', // monad
42
42
  146: '0x29219dd400f2Bf60E5a23d13Be72B486D4038894', // sonic
43
+ 196: '0xB6CEceAB302E2E4948951eE7843FC24E92933061', // xLayer
43
44
  300: '0xAe045DE5638162fa134807Cb558E15A3F5A7F853', // zksyncSepoliaTestnet
44
45
  324: '0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4', // zksync
45
46
  338: '0xEb33dc5fac03833e132593659e1dE7256aB59794', // cronosTestnet
@@ -50,11 +51,16 @@ export const usdc = /*#__PURE__*/ defineToken({
50
51
  1328: '0x4fCF1784B31630811181f670Aea7A7bEF803eaED', // seiTestnet
51
52
  1329: '0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392', // sei
52
53
  1439: '0x0C382e685bbeeFE5d3d9C29e29E341fEE8E84C5d', // injectiveTestnet
54
+ 1672: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815', // pharos
53
55
  1776: '0xa00C59fF5a080D2b954d0c75e46E22a0c371235a', // injective
56
+ 1952: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3', // xLayerTestnet
54
57
  2818: '0xCfb1186F4e93D60E60a8bDd997427D1F33bc372B', // morph
58
+ 2910: '0x7433b41C6c5e1d58D4Da99483609520255ab661B', // morphHoodi
59
+ 3343: '0x98d2919b9A214E6Fa5384AC81E6864bA686Ad74c', // edge
55
60
  4801: '0x66145f38cBAC35Ca6F1Dfb4914dF98F1614aeA88', // worldchainSepolia
56
61
  8453: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // base
57
62
  10143: '0x534b2f3A21130d7a60830c2Df862319e593943A3', // monadTestnet
63
+ 33431: '0x2d9F7CAD728051AA35Ecdc472a14cf8cDF5CFD6B', // edgeTestnet
58
64
  42161: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // arbitrum
59
65
  42220: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', // celo
60
66
  43113: '0x5425890298aed601595a70AB815c96711a31Bc65', // avalancheFuji
@@ -70,6 +76,7 @@ export const usdc = /*#__PURE__*/ defineToken({
70
76
  98866: '0x222365EF19F7947e5484218551B56bb3965Aa7aF', // plumeMainnet
71
77
  98867: '0xcB5f30e335672893c7eb944B374c196392C19D18', // plumeSepolia
72
78
  421614: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', // arbitrumSepolia
79
+ 688689: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B', // pharosTestnet
73
80
  763373: '0xFabab97dCE620294D2B0b0e46C68964e326300Ac', // inkSepolia
74
81
  812242: '0x6d7f141b6819C2c9CC2f818e6ad549E7Ca090F8f', // codexTestnet
75
82
  5042002: '0x3600000000000000000000000000000000000000', // arcTestnet
@@ -39,13 +39,13 @@ export function withRetry<data>(
39
39
  }: WithRetryParameters = {},
40
40
  ) {
41
41
  return new Promise<data>((resolve, reject) => {
42
- const attemptRetry = async ({ count = 0 } = {}) => {
42
+ const attemptRetry = async ({ count = 0 } = {}): Promise<void> => {
43
43
  if (signal?.aborted) {
44
44
  reject(getAbortError(signal))
45
45
  return
46
46
  }
47
47
 
48
- const retry = async ({ error }: { error: Error }) => {
48
+ const retry = async ({ error }: { error: Error }): Promise<void> => {
49
49
  const delay =
50
50
  typeof delay_ === 'function' ? delay_({ count, error }) : delay_
51
51
  if (delay) {
@@ -56,7 +56,7 @@ export function withRetry<data>(
56
56
  return
57
57
  }
58
58
  }
59
- attemptRetry({ count: count + 1 })
59
+ return attemptRetry({ count: count + 1 })
60
60
  }
61
61
 
62
62
  try {
@@ -79,6 +79,6 @@ export function withRetry<data>(
79
79
  reject(err)
80
80
  }
81
81
  }
82
- attemptRetry()
82
+ void attemptRetry().catch(reject)
83
83
  })
84
84
  }
@@ -6,6 +6,7 @@ import {
6
6
  InvalidDomainError,
7
7
  InvalidPrimaryTypeError,
8
8
  InvalidStructTypeError,
9
+ InvalidTypedDataTypeError,
9
10
  } from '../errors/typedData.js'
10
11
  import type { ErrorType } from '../errors/utils.js'
11
12
  import type { Hex } from '../types/misc.js'
@@ -86,6 +87,10 @@ export function validateTypedData<
86
87
  const { name, type } = param
87
88
  const value = data[name]
88
89
 
90
+ const baseType = type.replace(/(\[[0-9]*\])+$/, '')
91
+ if (baseType === 'int' || baseType === 'uint')
92
+ throw new InvalidTypedDataTypeError({ type })
93
+
89
94
  const integerMatch = type.match(integerRegex)
90
95
  if (
91
96
  integerMatch &&