viem 2.49.2 → 2.50.3

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 (260) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/_cjs/actions/ens/getEnsAddress.js +21 -6
  3. package/_cjs/actions/ens/getEnsAddress.js.map +1 -1
  4. package/_cjs/actions/public/call.js +76 -41
  5. package/_cjs/actions/public/call.js.map +1 -1
  6. package/_cjs/actions/public/getBalance.js +11 -4
  7. package/_cjs/actions/public/getBalance.js.map +1 -1
  8. package/_cjs/actions/public/getCode.js +12 -5
  9. package/_cjs/actions/public/getCode.js.map +1 -1
  10. package/_cjs/actions/public/getProof.js +9 -5
  11. package/_cjs/actions/public/getProof.js.map +1 -1
  12. package/_cjs/actions/public/getStorageAt.js +9 -4
  13. package/_cjs/actions/public/getStorageAt.js.map +1 -1
  14. package/_cjs/actions/public/getTransactionCount.js +10 -7
  15. package/_cjs/actions/public/getTransactionCount.js.map +1 -1
  16. package/_cjs/actions/public/multicall.js +3 -1
  17. package/_cjs/actions/public/multicall.js.map +1 -1
  18. package/_cjs/actions/public/readContract.js.map +1 -1
  19. package/_cjs/actions/wallet/prepareTransactionRequest.js.map +1 -1
  20. package/_cjs/actions/wallet/sendTransaction.js +14 -0
  21. package/_cjs/actions/wallet/sendTransaction.js.map +1 -1
  22. package/_cjs/actions/wallet/sendTransactionSync.js +15 -0
  23. package/_cjs/actions/wallet/sendTransactionSync.js.map +1 -1
  24. package/_cjs/chains/definitions/arc.js +19 -0
  25. package/_cjs/chains/definitions/arc.js.map +1 -0
  26. package/_cjs/chains/definitions/mizuhikiTestnetAwaji.js +29 -0
  27. package/_cjs/chains/definitions/mizuhikiTestnetAwaji.js.map +1 -0
  28. package/_cjs/chains/definitions/morphHolesky.js +1 -1
  29. package/_cjs/chains/definitions/morphHolesky.js.map +1 -1
  30. package/_cjs/chains/definitions/sentrix.js +29 -0
  31. package/_cjs/chains/definitions/sentrix.js.map +1 -0
  32. package/_cjs/chains/definitions/sentrixTestnet.js +30 -0
  33. package/_cjs/chains/definitions/sentrixTestnet.js.map +1 -0
  34. package/_cjs/chains/definitions/sova.js +1 -1
  35. package/_cjs/chains/definitions/sova.js.map +1 -1
  36. package/_cjs/chains/index.js +23 -15
  37. package/_cjs/chains/index.js.map +1 -1
  38. package/_cjs/constants/solidity.js.map +1 -1
  39. package/_cjs/errors/version.js +1 -1
  40. package/_cjs/index.js +5 -3
  41. package/_cjs/index.js.map +1 -1
  42. package/_cjs/tempo/Chain.js +19 -0
  43. package/_cjs/tempo/Chain.js.map +1 -0
  44. package/_cjs/tempo/Decorator.js +1 -0
  45. package/_cjs/tempo/Decorator.js.map +1 -1
  46. package/_cjs/tempo/Formatters.js +1 -1
  47. package/_cjs/tempo/Formatters.js.map +1 -1
  48. package/_cjs/tempo/Transaction.js +5 -2
  49. package/_cjs/tempo/Transaction.js.map +1 -1
  50. package/_cjs/tempo/actions/fee.js +61 -0
  51. package/_cjs/tempo/actions/fee.js.map +1 -1
  52. package/_cjs/tempo/chainConfig.js +16 -6
  53. package/_cjs/tempo/chainConfig.js.map +1 -1
  54. package/_cjs/tempo/chains/index.js +11 -0
  55. package/_cjs/tempo/chains/index.js.map +1 -0
  56. package/_cjs/tempo/errors.js +58 -0
  57. package/_cjs/tempo/errors.js.map +1 -0
  58. package/_cjs/tempo/index.js +17 -1
  59. package/_cjs/tempo/index.js.map +1 -1
  60. package/_cjs/utils/abi/encodeEventTopics.js +4 -2
  61. package/_cjs/utils/abi/encodeEventTopics.js.map +1 -1
  62. package/_cjs/utils/block/formatBlockParameter.js +16 -0
  63. package/_cjs/utils/block/formatBlockParameter.js.map +1 -0
  64. package/_cjs/utils/ccipTunnel.js +65 -0
  65. package/_cjs/utils/ccipTunnel.js.map +1 -0
  66. package/_cjs/utils/index.js +6 -4
  67. package/_cjs/utils/index.js.map +1 -1
  68. package/_cjs/utils/nonceManager.js +7 -3
  69. package/_cjs/utils/nonceManager.js.map +1 -1
  70. package/_cjs/utils/observe.js +7 -1
  71. package/_cjs/utils/observe.js.map +1 -1
  72. package/_cjs/utils/rpc/socket.js +19 -2
  73. package/_cjs/utils/rpc/socket.js.map +1 -1
  74. package/_esm/actions/ens/getEnsAddress.js +21 -6
  75. package/_esm/actions/ens/getEnsAddress.js.map +1 -1
  76. package/_esm/actions/public/call.js +76 -41
  77. package/_esm/actions/public/call.js.map +1 -1
  78. package/_esm/actions/public/getBalance.js +11 -4
  79. package/_esm/actions/public/getBalance.js.map +1 -1
  80. package/_esm/actions/public/getCode.js +12 -5
  81. package/_esm/actions/public/getCode.js.map +1 -1
  82. package/_esm/actions/public/getProof.js +9 -5
  83. package/_esm/actions/public/getProof.js.map +1 -1
  84. package/_esm/actions/public/getStorageAt.js +9 -4
  85. package/_esm/actions/public/getStorageAt.js.map +1 -1
  86. package/_esm/actions/public/getTransactionCount.js +10 -7
  87. package/_esm/actions/public/getTransactionCount.js.map +1 -1
  88. package/_esm/actions/public/multicall.js +3 -1
  89. package/_esm/actions/public/multicall.js.map +1 -1
  90. package/_esm/actions/public/readContract.js.map +1 -1
  91. package/_esm/actions/wallet/prepareTransactionRequest.js.map +1 -1
  92. package/_esm/actions/wallet/sendTransaction.js +14 -0
  93. package/_esm/actions/wallet/sendTransaction.js.map +1 -1
  94. package/_esm/actions/wallet/sendTransactionSync.js +15 -0
  95. package/_esm/actions/wallet/sendTransactionSync.js.map +1 -1
  96. package/_esm/chains/definitions/arc.js +16 -0
  97. package/_esm/chains/definitions/arc.js.map +1 -0
  98. package/_esm/chains/definitions/mizuhikiTestnetAwaji.js +26 -0
  99. package/_esm/chains/definitions/mizuhikiTestnetAwaji.js.map +1 -0
  100. package/_esm/chains/definitions/morphHolesky.js +1 -1
  101. package/_esm/chains/definitions/morphHolesky.js.map +1 -1
  102. package/_esm/chains/definitions/sentrix.js +26 -0
  103. package/_esm/chains/definitions/sentrix.js.map +1 -0
  104. package/_esm/chains/definitions/sentrixTestnet.js +27 -0
  105. package/_esm/chains/definitions/sentrixTestnet.js.map +1 -0
  106. package/_esm/chains/definitions/sova.js +1 -1
  107. package/_esm/chains/definitions/sova.js.map +1 -1
  108. package/_esm/chains/index.js +4 -0
  109. package/_esm/chains/index.js.map +1 -1
  110. package/_esm/constants/solidity.js.map +1 -1
  111. package/_esm/errors/version.js +1 -1
  112. package/_esm/index.js +1 -0
  113. package/_esm/index.js.map +1 -1
  114. package/_esm/tempo/Chain.js +6 -0
  115. package/_esm/tempo/Chain.js.map +1 -0
  116. package/_esm/tempo/Decorator.js +1 -0
  117. package/_esm/tempo/Decorator.js.map +1 -1
  118. package/_esm/tempo/Formatters.js +10 -4
  119. package/_esm/tempo/Formatters.js.map +1 -1
  120. package/_esm/tempo/Transaction.js +16 -6
  121. package/_esm/tempo/Transaction.js.map +1 -1
  122. package/_esm/tempo/actions/fee.js +83 -0
  123. package/_esm/tempo/actions/fee.js.map +1 -1
  124. package/_esm/tempo/actions/wallet.js +2 -2
  125. package/_esm/tempo/chainConfig.js +18 -8
  126. package/_esm/tempo/chainConfig.js.map +1 -1
  127. package/_esm/tempo/chains/index.js +3 -0
  128. package/_esm/tempo/chains/index.js.map +1 -0
  129. package/_esm/tempo/errors.js +51 -0
  130. package/_esm/tempo/errors.js.map +1 -0
  131. package/_esm/tempo/index.js +2 -0
  132. package/_esm/tempo/index.js.map +1 -1
  133. package/_esm/utils/abi/encodeEventTopics.js +6 -2
  134. package/_esm/utils/abi/encodeEventTopics.js.map +1 -1
  135. package/_esm/utils/block/formatBlockParameter.js +39 -0
  136. package/_esm/utils/block/formatBlockParameter.js.map +1 -0
  137. package/_esm/utils/ccipTunnel.js +62 -0
  138. package/_esm/utils/ccipTunnel.js.map +1 -0
  139. package/_esm/utils/index.js +1 -0
  140. package/_esm/utils/index.js.map +1 -1
  141. package/_esm/utils/nonceManager.js +7 -3
  142. package/_esm/utils/nonceManager.js.map +1 -1
  143. package/_esm/utils/observe.js +7 -1
  144. package/_esm/utils/observe.js.map +1 -1
  145. package/_esm/utils/rpc/socket.js +20 -2
  146. package/_esm/utils/rpc/socket.js.map +1 -1
  147. package/_types/actions/ens/getEnsAddress.d.ts +3 -1
  148. package/_types/actions/ens/getEnsAddress.d.ts.map +1 -1
  149. package/_types/actions/public/call.d.ts +17 -6
  150. package/_types/actions/public/call.d.ts.map +1 -1
  151. package/_types/actions/public/getBalance.d.ts +15 -3
  152. package/_types/actions/public/getBalance.d.ts.map +1 -1
  153. package/_types/actions/public/getCode.d.ts +15 -4
  154. package/_types/actions/public/getCode.d.ts.map +1 -1
  155. package/_types/actions/public/getProof.d.ts +14 -3
  156. package/_types/actions/public/getProof.d.ts.map +1 -1
  157. package/_types/actions/public/getStorageAt.d.ts +15 -4
  158. package/_types/actions/public/getStorageAt.d.ts.map +1 -1
  159. package/_types/actions/public/getTransactionCount.d.ts +15 -3
  160. package/_types/actions/public/getTransactionCount.d.ts.map +1 -1
  161. package/_types/actions/public/multicall.d.ts +1 -1
  162. package/_types/actions/public/multicall.d.ts.map +1 -1
  163. package/_types/actions/public/readContract.d.ts +1 -1
  164. package/_types/actions/public/readContract.d.ts.map +1 -1
  165. package/_types/actions/wallet/prepareTransactionRequest.d.ts +4 -2
  166. package/_types/actions/wallet/prepareTransactionRequest.d.ts.map +1 -1
  167. package/_types/actions/wallet/sendTransaction.d.ts.map +1 -1
  168. package/_types/actions/wallet/sendTransactionSync.d.ts.map +1 -1
  169. package/_types/chains/definitions/arc.d.ts +54 -0
  170. package/_types/chains/definitions/arc.d.ts.map +1 -0
  171. package/_types/chains/definitions/mizuhikiTestnetAwaji.d.ts +46 -0
  172. package/_types/chains/definitions/mizuhikiTestnetAwaji.d.ts.map +1 -0
  173. package/_types/chains/definitions/morphHolesky.d.ts +1 -1
  174. package/_types/chains/definitions/sentrix.d.ts +46 -0
  175. package/_types/chains/definitions/sentrix.d.ts.map +1 -0
  176. package/_types/chains/definitions/sentrixTestnet.d.ts +46 -0
  177. package/_types/chains/definitions/sentrixTestnet.d.ts.map +1 -0
  178. package/_types/chains/definitions/sova.d.ts +1 -1
  179. package/_types/chains/index.d.ts +4 -0
  180. package/_types/chains/index.d.ts.map +1 -1
  181. package/_types/constants/solidity.d.ts +16 -3
  182. package/_types/constants/solidity.d.ts.map +1 -1
  183. package/_types/errors/version.d.ts +1 -1
  184. package/_types/index.d.ts +1 -0
  185. package/_types/index.d.ts.map +1 -1
  186. package/_types/tempo/Chain.d.ts +5 -0
  187. package/_types/tempo/Chain.d.ts.map +1 -0
  188. package/_types/tempo/Decorator.d.ts +23 -0
  189. package/_types/tempo/Decorator.d.ts.map +1 -1
  190. package/_types/tempo/Formatters.d.ts.map +1 -1
  191. package/_types/tempo/Transaction.d.ts.map +1 -1
  192. package/_types/tempo/actions/fee.d.ts +38 -0
  193. package/_types/tempo/actions/fee.d.ts.map +1 -1
  194. package/_types/tempo/actions/wallet.d.ts +9 -6
  195. package/_types/tempo/actions/wallet.d.ts.map +1 -1
  196. package/_types/tempo/chainConfig.d.ts.map +1 -1
  197. package/_types/tempo/chains/index.d.ts +2 -0
  198. package/_types/tempo/chains/index.d.ts.map +1 -0
  199. package/_types/tempo/errors.d.ts +36 -0
  200. package/_types/tempo/errors.d.ts.map +1 -0
  201. package/_types/tempo/index.d.ts +2 -0
  202. package/_types/tempo/index.d.ts.map +1 -1
  203. package/_types/types/block.d.ts +3 -4
  204. package/_types/types/block.d.ts.map +1 -1
  205. package/_types/types/eip1193.d.ts +1 -1
  206. package/_types/types/eip1193.d.ts.map +1 -1
  207. package/_types/utils/abi/encodeEventTopics.d.ts +6 -2
  208. package/_types/utils/abi/encodeEventTopics.d.ts.map +1 -1
  209. package/_types/utils/block/formatBlockParameter.d.ts +45 -0
  210. package/_types/utils/block/formatBlockParameter.d.ts.map +1 -0
  211. package/_types/utils/ccipTunnel.d.ts +9 -0
  212. package/_types/utils/ccipTunnel.d.ts.map +1 -0
  213. package/_types/utils/index.d.ts +1 -0
  214. package/_types/utils/index.d.ts.map +1 -1
  215. package/_types/utils/nonceManager.d.ts.map +1 -1
  216. package/_types/utils/observe.d.ts.map +1 -1
  217. package/_types/utils/rpc/socket.d.ts.map +1 -1
  218. package/actions/ens/getEnsAddress.ts +34 -6
  219. package/actions/public/call.ts +125 -51
  220. package/actions/public/getBalance.ts +30 -9
  221. package/actions/public/getCode.ts +35 -11
  222. package/actions/public/getProof.ts +27 -11
  223. package/actions/public/getStorageAt.ts +33 -10
  224. package/actions/public/getTransactionCount.ts +33 -11
  225. package/actions/public/multicall.ts +6 -0
  226. package/actions/public/readContract.ts +2 -0
  227. package/actions/wallet/prepareTransactionRequest.ts +11 -15
  228. package/actions/wallet/sendTransaction.ts +13 -0
  229. package/actions/wallet/sendTransactionSync.ts +16 -0
  230. package/chains/definitions/arc.ts +16 -0
  231. package/chains/definitions/mizuhikiTestnetAwaji.ts +26 -0
  232. package/chains/definitions/morphHolesky.ts +1 -1
  233. package/chains/definitions/sentrix.ts +26 -0
  234. package/chains/definitions/sentrixTestnet.ts +27 -0
  235. package/chains/definitions/sova.ts +1 -1
  236. package/chains/index.ts +4 -0
  237. package/constants/solidity.ts +4 -4
  238. package/errors/version.ts +1 -1
  239. package/index.ts +4 -0
  240. package/package.json +11 -3
  241. package/tempo/Chain.ts +20 -0
  242. package/tempo/Decorator.ts +27 -0
  243. package/tempo/Formatters.ts +15 -4
  244. package/tempo/Transaction.ts +16 -6
  245. package/tempo/actions/fee.ts +117 -1
  246. package/tempo/actions/wallet.ts +9 -6
  247. package/tempo/chainConfig.ts +18 -12
  248. package/tempo/chains/index.ts +9 -0
  249. package/tempo/chains/package.json +6 -0
  250. package/tempo/errors.ts +78 -0
  251. package/tempo/index.ts +2 -0
  252. package/types/block.ts +3 -5
  253. package/types/eip1193.ts +1 -1
  254. package/utils/abi/encodeEventTopics.ts +25 -6
  255. package/utils/block/formatBlockParameter.ts +63 -0
  256. package/utils/ccipTunnel.ts +67 -0
  257. package/utils/index.ts +4 -0
  258. package/utils/nonceManager.ts +7 -3
  259. package/utils/observe.ts +7 -4
  260. package/utils/rpc/socket.ts +21 -2
@@ -1389,6 +1389,31 @@ export type Decorator<
1389
1389
  ) => () => void
1390
1390
  }
1391
1391
  fee: {
1392
+ /**
1393
+ * Validates that a token can be used as a Tempo fee token.
1394
+ *
1395
+ * @example
1396
+ * ```ts
1397
+ * import { createClient, http } from 'viem'
1398
+ * import { tempo } from 'viem/chains'
1399
+ * import { tempoActions } from 'viem/tempo'
1400
+ *
1401
+ * const client = createClient({
1402
+ * chain: tempo
1403
+ * transport: http(),
1404
+ * }).extend(tempoActions())
1405
+ *
1406
+ * const { address } = await client.fee.validateToken({
1407
+ * token: '0x20c0000000000000000000000000000000000001',
1408
+ * })
1409
+ * ```
1410
+ *
1411
+ * @param parameters - Parameters.
1412
+ * @returns The fee token address, ID, and metadata.
1413
+ */
1414
+ validateToken: (
1415
+ parameters: feeActions.validateToken.Parameters,
1416
+ ) => Promise<feeActions.validateToken.ReturnValue>
1392
1417
  /**
1393
1418
  * Gets the user's default fee token.
1394
1419
  *
@@ -4321,6 +4346,8 @@ export function decorator() {
4321
4346
  nonceActions.watchNonceIncremented(client, parameters),
4322
4347
  },
4323
4348
  fee: {
4349
+ validateToken: (parameters) =>
4350
+ feeActions.validateToken(client, parameters),
4324
4351
  // @ts-expect-error
4325
4352
  getUserToken: (parameters) =>
4326
4353
  // @ts-expect-error
@@ -72,6 +72,10 @@ export function formatTransactionRequest(
72
72
  ): TransactionRequestRpc {
73
73
  const request = r as TransactionRequest & {
74
74
  account?: viem_Account | Address | undefined
75
+ feePayerSignature?:
76
+ | { r: Hex.Hex; s: Hex.Hex; yParity: number; v?: number | undefined }
77
+ | null
78
+ | undefined
75
79
  keyData?: Hex.Hex | undefined
76
80
  keyId?: Address | undefined
77
81
  keyType?: 'p256' | 'secp256k1' | 'webAuthn' | undefined
@@ -100,10 +104,17 @@ export function formatTransactionRequest(
100
104
  },
101
105
  ]
102
106
 
103
- // If we have marked the transaction as intended to be paid
104
- // by a fee payer (feePayer: true), we will not use the fee token
105
- // as the fee payer will choose their fee token.
106
- if (request.feePayer === true) delete request.feeToken
107
+ // If we have marked the transaction as intended to be paid by a fee
108
+ // payer (feePayer: true), we strip the fee token from the sender's
109
+ // sign payload — per TIP-76 the sender does not commit to it; the fee
110
+ // payer chooses and commits to the token via its own signature.
111
+ //
112
+ // Once the fee payer has signed (`feePayerSignature` is populated),
113
+ // the relay has chosen a token and signed over it. The broadcast
114
+ // envelope must therefore include `feeToken` so the chain can verify
115
+ // the fee payer's signature and identify which token to charge.
116
+ if (request.feePayer === true && !request.feePayerSignature)
117
+ delete request.feeToken
107
118
 
108
119
  const rpc = ox_TransactionRequest.toRpc({
109
120
  ...request,
@@ -325,10 +325,16 @@ async function serializeTempo(
325
325
  ...(nonce ? { nonce: BigInt(nonce) } : {}),
326
326
  } satisfies TxTempo.TxEnvelopeTempo
327
327
 
328
- // If we have marked the transaction as intended to be paid
329
- // by a fee payer (feePayer: true), we will not use the fee token
330
- // as the fee payer will choose their fee token.
331
- if (feePayer === true) delete transaction_ox.feeToken
328
+ // If we have marked the transaction as intended to be paid by a fee
329
+ // payer (feePayer: true), we strip the fee token from the sender's
330
+ // sign payload — per TIP-76 the sender does not commit to it; the fee
331
+ // payer chooses and commits to the token via its own signature.
332
+ //
333
+ // Once the fee payer has signed (`feePayerSignature` is populated),
334
+ // the relay has chosen a token and signed over it. The broadcast
335
+ // envelope must therefore include `feeToken` so the chain can verify
336
+ // the fee payer's signature and identify which token to charge.
337
+ if (feePayer === true && !feePayerSignature) delete transaction_ox.feeToken
332
338
 
333
339
  if (signature && typeof transaction.feePayer === 'object') {
334
340
  const tx = TxTempo.from(transaction_ox, {
@@ -372,8 +378,12 @@ async function serializeTempo(
372
378
 
373
379
  return TxTempo.serialize(
374
380
  // If we have specified a fee payer, the user will not be signing over the fee token.
375
- // Defer the fee token signing to the fee payer.
376
- { ...transaction_ox, ...(feePayer ? { feeToken: undefined } : {}) },
381
+ // Defer the fee token signing to the fee payer. Once the fee payer has signed,
382
+ // keep `feeToken` so the broadcast envelope carries the token the chain must charge.
383
+ {
384
+ ...transaction_ox,
385
+ ...(feePayer && !feePayerSignature ? { feeToken: undefined } : {}),
386
+ },
377
387
  {
378
388
  feePayerSignature: undefined,
379
389
  signature,
@@ -11,7 +11,7 @@ import { writeContractSync } from '../../actions/wallet/writeContractSync.js'
11
11
  import type { Client } from '../../clients/createClient.js'
12
12
  import type { Transport } from '../../clients/transports/createTransport.js'
13
13
  import { zeroAddress } from '../../constants/address.js'
14
- import type { BaseErrorType } from '../../errors/base.js'
14
+ import type { BaseError, BaseErrorType } from '../../errors/base.js'
15
15
  import type { Chain } from '../../types/chain.js'
16
16
  import type { ExtractAbiItem, GetEventArgs } from '../../types/contract.js'
17
17
  import type { Log, Log as viem_Log } from '../../types/log.js'
@@ -19,6 +19,12 @@ import type { Compute, UnionOmit } from '../../types/utils.js'
19
19
  import { parseEventLogs } from '../../utils/abi/parseEventLogs.js'
20
20
  import * as Abis from '../Abis.js'
21
21
  import * as Addresses from '../Addresses.js'
22
+ import {
23
+ FeeTokenNotTip20Error,
24
+ FeeTokenNotUsdError,
25
+ FeeTokenPausedError,
26
+ InvalidFeeTokenError,
27
+ } from '../errors.js'
22
28
  import type {
23
29
  GetAccountParameter,
24
30
  ReadParameters,
@@ -26,6 +32,116 @@ import type {
26
32
  } from '../internal/types.js'
27
33
  import { defineCall } from '../internal/utils.js'
28
34
  import type { TransactionReceipt } from '../Transaction.js'
35
+ import * as tokenActions from './token.js'
36
+
37
+ const tip20AddressPrefix = '0x20c0'
38
+
39
+ /**
40
+ * Validates that a token can be used as a Tempo fee token.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { createClient, http } from 'viem'
45
+ * import { tempo } from 'viem/chains'
46
+ * import { Actions } from 'viem/tempo'
47
+ *
48
+ * const client = createClient({
49
+ * chain: tempo,
50
+ * transport: http(),
51
+ * })
52
+ *
53
+ * const { address, metadata } = await Actions.fee.validateToken(client, {
54
+ * token: '0x20c0000000000000000000000000000000000001',
55
+ * })
56
+ * ```
57
+ *
58
+ * @param client - Client.
59
+ * @param parameters - Parameters.
60
+ * @returns The fee token address, ID, and metadata.
61
+ */
62
+ export async function validateToken<chain extends Chain | undefined>(
63
+ client: Client<Transport, chain>,
64
+ parameters: validateToken.Parameters,
65
+ ): Promise<validateToken.ReturnValue> {
66
+ const { token, ...rest } = parameters
67
+ const token_ = String(token)
68
+ const address = (() => {
69
+ try {
70
+ return TokenId.toAddress(token)
71
+ } catch (cause) {
72
+ throw new InvalidFeeTokenError({
73
+ cause: cause as BaseError | Error,
74
+ token: token_,
75
+ })
76
+ }
77
+ })()
78
+
79
+ if (!address.toLowerCase().startsWith(tip20AddressPrefix))
80
+ throw new FeeTokenNotTip20Error({ token: address })
81
+
82
+ const isPathUsd = address.toLowerCase() === Addresses.pathUsd.toLowerCase()
83
+ if (!isPathUsd) {
84
+ const isTip20 = await readContract(client, {
85
+ ...rest,
86
+ address: Addresses.tip20Factory,
87
+ abi: Abis.tip20Factory,
88
+ functionName: 'isTIP20',
89
+ args: [address],
90
+ }).catch((cause) => {
91
+ throw new InvalidFeeTokenError({
92
+ cause: cause as BaseError | Error,
93
+ token: address,
94
+ })
95
+ })
96
+ if (!isTip20) throw new FeeTokenNotTip20Error({ token: address })
97
+ }
98
+
99
+ const metadata = await tokenActions
100
+ .getMetadata(client, {
101
+ ...rest,
102
+ token: address,
103
+ })
104
+ .catch((cause) => {
105
+ throw new InvalidFeeTokenError({
106
+ cause: cause as BaseError | Error,
107
+ token: address,
108
+ })
109
+ })
110
+
111
+ if (metadata.currency !== 'USD')
112
+ throw new FeeTokenNotUsdError({
113
+ currency: metadata.currency,
114
+ token: address,
115
+ })
116
+ if (metadata.paused === true)
117
+ throw new FeeTokenPausedError({ token: address })
118
+
119
+ return {
120
+ address,
121
+ id: TokenId.fromAddress(address),
122
+ metadata,
123
+ }
124
+ }
125
+
126
+ export declare namespace validateToken {
127
+ export type Parameters = ReadParameters & {
128
+ /** Address or ID of the TIP20 token. */
129
+ token: TokenId.TokenIdOrAddress
130
+ }
131
+
132
+ export type ReturnValue = Compute<{
133
+ address: Address
134
+ id: bigint
135
+ metadata: tokenActions.getMetadata.ReturnValue
136
+ }>
137
+
138
+ export type ErrorType =
139
+ | FeeTokenNotTip20Error
140
+ | FeeTokenNotUsdError
141
+ | FeeTokenPausedError
142
+ | InvalidFeeTokenError
143
+ | BaseErrorType
144
+ }
29
145
 
30
146
  /**
31
147
  * Gets the user's default fee token.
@@ -213,8 +213,8 @@ export declare namespace swap {
213
213
  * })
214
214
  *
215
215
  * const result = await Actions.wallet.deposit(client, {
216
- * token: '0x...',
217
- * value: '1.5',
216
+ * amount: '1.5',
217
+ * token: 'pathUsd',
218
218
  * })
219
219
  * ```
220
220
  *
@@ -243,14 +243,17 @@ export declare namespace deposit {
243
243
  export type Parameters = {
244
244
  /** Deposit address to pre-fill. */
245
245
  address?: Address | undefined
246
+ /** Human-readable amount to pre-fill (for example, "1.5"). */
247
+ amount?: string | undefined
246
248
  /** Source chain ID to pre-fill. */
247
249
  chainId?: number | undefined
248
250
  /** Human-readable account display name. */
249
251
  displayName?: string | undefined
250
- /** Token contract address to pre-fill. Omit to let the user choose. */
251
- token?: Address | undefined
252
- /** Human-readable amount to pre-fill (for example, "1.5"). */
253
- value?: string | undefined
252
+ /**
253
+ * Token to pre-fill, accepted as either a contract address or a supported
254
+ * deposit token symbol. Omit to let the user choose.
255
+ */
256
+ token?: Address | string | undefined
254
257
  }
255
258
 
256
259
  export type ReturnValue =
@@ -1,6 +1,4 @@
1
- import * as Address from 'ox/Address'
2
1
  import * as Hex from 'ox/Hex'
3
- import * as PublicKey from 'ox/PublicKey'
4
2
  import { SignatureEnvelope, type TokenId } from 'ox/tempo'
5
3
  import { getCode } from '../actions/public/getCode.js'
6
4
  import { verifyHash } from '../actions/public/verifyHash.js'
@@ -115,9 +113,24 @@ export const chainConfig = {
115
113
  // Access key (keychain) signature verification: check the key is
116
114
  // authorized, not expired, and not revoked on the AccountKeychain.
117
115
  if (envelope?.type === 'keychain' && mode === 'allowAccessKey') {
118
- const accessKeyAddress = Address.fromPublicKey(
119
- PublicKey.from(envelope.inner.publicKey as PublicKey.PublicKey),
120
- )
116
+ // For v2 keychain envelopes, the inner signature signs
117
+ // keccak256(0x04 || hash || userAddress).
118
+ const innerPayload =
119
+ envelope.version === 'v2'
120
+ ? keccak256(Hex.concat('0x04', hash, address))
121
+ : hash
122
+
123
+ const accessKeyAddress = (() => {
124
+ try {
125
+ return SignatureEnvelope.extractAddress({
126
+ payload: innerPayload,
127
+ signature: envelope.inner,
128
+ })
129
+ } catch {
130
+ return undefined
131
+ }
132
+ })()
133
+ if (!accessKeyAddress) return false
121
134
 
122
135
  const keyInfo = await getMetadata(client, {
123
136
  account: address,
@@ -129,13 +142,6 @@ export const chainConfig = {
129
142
  if (keyInfo.isRevoked) return false
130
143
  if (keyInfo.expiry <= BigInt(Math.floor(Date.now() / 1000)))
131
144
  return false
132
-
133
- // For v2 keychain envelopes, the inner signature signs
134
- // keccak256(0x04 || hash || userAddress).
135
- const innerPayload =
136
- envelope.version === 'v2'
137
- ? keccak256(Hex.concat('0x04', hash, address))
138
- : hash
139
145
  return SignatureEnvelope.verify(envelope.inner, {
140
146
  address: accessKeyAddress,
141
147
  payload: innerPayload,
@@ -0,0 +1,9 @@
1
+ // biome-ignore lint/performance/noBarrelFile: entrypoint module
2
+ export {
3
+ tempo,
4
+ tempoDevnet,
5
+ tempoLocalnet,
6
+ tempoMainnet,
7
+ tempoModerato,
8
+ tempoTestnet,
9
+ } from '../Chain.js'
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "module",
3
+ "types": "../../_types/tempo/chains/index.d.ts",
4
+ "module": "../../_esm/tempo/chains/index.js",
5
+ "main": "../../_cjs/tempo/chains/index.js"
6
+ }
@@ -0,0 +1,78 @@
1
+ import { BaseError } from '../errors/base.js'
2
+
3
+ export type InvalidFeeTokenErrorType = InvalidFeeTokenError & {
4
+ name: 'InvalidFeeTokenError'
5
+ }
6
+ export class InvalidFeeTokenError extends BaseError {
7
+ constructor({
8
+ cause,
9
+ token,
10
+ }: {
11
+ cause?: BaseError | Error | undefined
12
+ token: string
13
+ }) {
14
+ super(`Fee token "${token}" is invalid.`, {
15
+ cause,
16
+ docsPath: '/tempo/transactions',
17
+ docsSlug: 'pay-fees-with-stablecoins',
18
+ metaMessages: [
19
+ 'Fee tokens must be unpaused USD-denominated TIP-20 tokens.',
20
+ 'Use `client.fee.validateToken({ token })` before sending transactions or setting fee preferences.',
21
+ ],
22
+ name: 'InvalidFeeTokenError',
23
+ })
24
+ }
25
+ }
26
+
27
+ export type FeeTokenNotTip20ErrorType = FeeTokenNotTip20Error & {
28
+ name: 'FeeTokenNotTip20Error'
29
+ }
30
+ export class FeeTokenNotTip20Error extends BaseError {
31
+ constructor({ token }: { token: string }) {
32
+ super(`Fee token "${token}" is not a TIP-20 token.`, {
33
+ docsPath: '/tempo/transactions',
34
+ docsSlug: 'pay-fees-with-stablecoins',
35
+ metaMessages: [
36
+ 'Fee tokens must be TIP-20 token addresses or token IDs.',
37
+ 'TIP-20 token addresses use the `0x20c0...` address prefix.',
38
+ ],
39
+ name: 'FeeTokenNotTip20Error',
40
+ })
41
+ }
42
+ }
43
+
44
+ export type FeeTokenNotUsdErrorType = FeeTokenNotUsdError & {
45
+ name: 'FeeTokenNotUsdError'
46
+ }
47
+ export class FeeTokenNotUsdError extends BaseError {
48
+ constructor({
49
+ currency,
50
+ token,
51
+ }: {
52
+ currency: string
53
+ token: string
54
+ }) {
55
+ super(`Fee token "${token}" is denominated in "${currency}", not "USD".`, {
56
+ docsPath: '/tempo/transactions',
57
+ docsSlug: 'pay-fees-with-stablecoins',
58
+ metaMessages: [
59
+ 'Only USD-denominated TIP-20 tokens can be used as fee tokens.',
60
+ ],
61
+ name: 'FeeTokenNotUsdError',
62
+ })
63
+ }
64
+ }
65
+
66
+ export type FeeTokenPausedErrorType = FeeTokenPausedError & {
67
+ name: 'FeeTokenPausedError'
68
+ }
69
+ export class FeeTokenPausedError extends BaseError {
70
+ constructor({ token }: { token: string }) {
71
+ super(`Fee token "${token}" is paused.`, {
72
+ docsPath: '/tempo/transactions',
73
+ docsSlug: 'pay-fees-with-stablecoins',
74
+ metaMessages: ['Paused TIP-20 tokens cannot be used as fee tokens.'],
75
+ name: 'FeeTokenPausedError',
76
+ })
77
+ }
78
+ }
package/tempo/index.ts CHANGED
@@ -24,11 +24,13 @@ export * as Account from './Account.js'
24
24
  export * as Addresses from './Addresses.js'
25
25
  export * as Actions from './actions/index.js'
26
26
  export * as Capabilities from './Capabilities.js'
27
+ export * as Chain from './Chain.js'
27
28
  export {
28
29
  type Decorator as TempoActions,
29
30
  decorator as tempoActions,
30
31
  } from './Decorator.js'
31
32
  export * as Expiry from './Expiry.js'
33
+ export * from './errors.js'
32
34
  export * as Formatters from './Formatters.js'
33
35
  export * as Hardfork from './Hardfork.js'
34
36
  export * as P256 from './P256.js'
package/types/block.ts CHANGED
@@ -69,10 +69,7 @@ export type Block<
69
69
  withdrawalsRoot?: Hex | undefined
70
70
  }
71
71
 
72
- export type BlockIdentifier<quantity = bigint> = {
73
- /** Whether or not to throw an error if the block is not in the canonical chain as described below. Only allowed in conjunction with the blockHash tag. Defaults to false. */
74
- requireCanonical?: boolean | undefined
75
- } & (
72
+ export type BlockIdentifier<quantity = bigint> =
76
73
  | {
77
74
  /** The block in the canonical chain with this number */
78
75
  blockNumber: BlockNumber<quantity>
@@ -80,8 +77,9 @@ export type BlockIdentifier<quantity = bigint> = {
80
77
  | {
81
78
  /** The block uniquely identified by this hash. The `blockNumber` and `blockHash` properties are mutually exclusive; exactly one of them must be set. */
82
79
  blockHash: Hash
80
+ /** Whether or not to throw an error if the block is not in the canonical chain as described below. Only allowed in conjunction with the blockHash tag. Defaults to false. */
81
+ requireCanonical?: boolean | undefined
83
82
  }
84
- )
85
83
 
86
84
  /** Represents a block number in the blockchain. */
87
85
  export type BlockNumber<quantity = bigint> = quantity
package/types/eip1193.ts CHANGED
@@ -974,7 +974,7 @@ export type PublicRpcSchema = [
974
974
  address: Address,
975
975
  /** An array of storage-keys that should be proofed and included. */
976
976
  storageKeys: Hash[],
977
- block: BlockNumber | BlockTag,
977
+ block: BlockNumber | BlockTag | BlockIdentifier,
978
978
  ]
979
979
  ReturnType: Proof
980
980
  },
@@ -66,7 +66,22 @@ export type EncodeEventTopicsParameters<
66
66
  > &
67
67
  (hasEvents extends true ? unknown : never)
68
68
 
69
- export type EncodeEventTopicsReturnType = [Hex, ...(Hex | Hex[] | null)[]]
69
+ export type EncodeEventTopicsReturnType<
70
+ abi extends Abi | readonly unknown[] = Abi,
71
+ eventName extends ContractEventName<abi> | undefined = undefined,
72
+ ///
73
+ resolvedEvent = abi extends Abi
74
+ ? eventName extends string
75
+ ? Extract<ExtractAbiEvents<abi>, { name: eventName }>
76
+ : abi['length'] extends 1
77
+ ? abi[0]
78
+ : ExtractAbiEvents<abi>
79
+ : unknown,
80
+ > = IsNarrowable<abi, Abi> extends true
81
+ ? [resolvedEvent] extends [{ anonymous: true }]
82
+ ? (Hex | Hex[] | null)[]
83
+ : [Hex, ...(Hex | Hex[] | null)[]]
84
+ : (Hex | Hex[] | null)[]
70
85
 
71
86
  export type EncodeEventTopicsErrorType =
72
87
  | AbiEventNotFoundErrorType
@@ -81,7 +96,7 @@ export function encodeEventTopics<
81
96
  eventName extends ContractEventName<abi> | undefined = undefined,
82
97
  >(
83
98
  parameters: EncodeEventTopicsParameters<abi, eventName>,
84
- ): EncodeEventTopicsReturnType {
99
+ ): EncodeEventTopicsReturnType<abi, eventName> {
85
100
  const { abi, eventName, args } = parameters as EncodeEventTopicsParameters
86
101
 
87
102
  let abiItem = abi[0]
@@ -94,9 +109,6 @@ export function encodeEventTopics<
94
109
  if (abiItem.type !== 'event')
95
110
  throw new AbiEventNotFoundError(undefined, { docsPath })
96
111
 
97
- const definition = formatAbiItem(abiItem)
98
- const signature = toEventSelector(definition as EventDefinition)
99
-
100
112
  let topics: (Hex | Hex[] | null)[] = []
101
113
  if (args && 'inputs' in abiItem) {
102
114
  const indexedInputs = abiItem.inputs?.filter(
@@ -121,7 +133,14 @@ export function encodeEventTopics<
121
133
  }) ?? []
122
134
  }
123
135
  }
124
- return [signature, ...topics]
136
+ // Anonymous events are not identified by a signature topic, so the event
137
+ // selector must not be prepended.
138
+ if (abiItem.anonymous)
139
+ return topics as EncodeEventTopicsReturnType<abi, eventName>
140
+
141
+ const definition = formatAbiItem(abiItem)
142
+ const signature = toEventSelector(definition as EventDefinition)
143
+ return [signature, ...topics] as EncodeEventTopicsReturnType<abi, eventName>
125
144
  }
126
145
 
127
146
  export type EncodeArgErrorType =
@@ -0,0 +1,63 @@
1
+ import { BaseError, type BaseErrorType } from '../../errors/base.js'
2
+ import type { BlockTag } from '../../types/block.js'
3
+ import type { Hash, Hex } from '../../types/misc.js'
4
+ import type { RpcBlockIdentifier } from '../../types/rpc.js'
5
+ import type { NumberToHexErrorType } from '../encoding/toHex.js'
6
+ import { numberToHex } from '../encoding/toHex.js'
7
+
8
+ type FormatBlockParameterParameters = {
9
+ blockHash?: Hash | undefined
10
+ blockNumber?: bigint | undefined
11
+ blockTag?: BlockTag | undefined
12
+ requireCanonical?: boolean | undefined
13
+ }
14
+
15
+ type RpcBlockHashIdentifier = Extract<RpcBlockIdentifier, { blockHash: Hash }>
16
+
17
+ type FormatBlockParameterReturnType = Hex | BlockTag | RpcBlockHashIdentifier
18
+
19
+ export type FormatBlockParameterErrorType = BaseErrorType | NumberToHexErrorType
20
+
21
+ /**
22
+ * Formats block parameters for RPC calls according to EIP-1898.
23
+ *
24
+ * @param parameters - Block parameters
25
+ * @returns Formatted block parameter for RPC call
26
+ *
27
+ * @example
28
+ * // Using block tag
29
+ * formatBlockParameter({ blockTag: 'latest' })
30
+ * // => 'latest'
31
+ *
32
+ * @example
33
+ * // Using block number
34
+ * formatBlockParameter({ blockNumber: 69420n })
35
+ * // => '0x10f2c'
36
+ *
37
+ * @example
38
+ * // Using block hash (EIP-1898)
39
+ * formatBlockParameter({ blockHash: '0x...' })
40
+ * // => { blockHash: '0x...' }
41
+ *
42
+ * @example
43
+ * // Using block hash with requireCanonical (EIP-1898)
44
+ * formatBlockParameter({ blockHash: '0x...', requireCanonical: true })
45
+ * // => { blockHash: '0x...', requireCanonical: true }
46
+ */
47
+ export function formatBlockParameter(
48
+ parameters: FormatBlockParameterParameters,
49
+ ): FormatBlockParameterReturnType {
50
+ const { blockHash, blockNumber, blockTag, requireCanonical } = parameters
51
+
52
+ if (requireCanonical !== undefined && !blockHash)
53
+ throw new BaseError(
54
+ '`requireCanonical` can only be provided when `blockHash` is set.',
55
+ )
56
+
57
+ if (blockHash)
58
+ return requireCanonical ? { blockHash, requireCanonical } : { blockHash }
59
+
60
+ if (typeof blockNumber === 'bigint') return numberToHex(blockNumber)
61
+
62
+ return blockTag ?? 'latest'
63
+ }
@@ -0,0 +1,67 @@
1
+ import { batchGatewayAbi } from '../constants/abis.js'
2
+ import { solidityError } from '../constants/solidity.js'
3
+ import { HttpRequestError } from '../errors/request.js'
4
+ import { decodeErrorResult } from './abi/decodeErrorResult.js'
5
+ import { decodeFunctionResult } from './abi/decodeFunctionResult.js'
6
+ import { encodeFunctionData } from './abi/encodeFunctionData.js'
7
+ import { ccipRequest as ccipRequest_ } from './ccip.js'
8
+ import { localBatchGatewayUrl } from './ens/localBatchGatewayRequest.js'
9
+
10
+ export type CcipReadTunnelParameters = {
11
+ batchGateways: string[]
12
+ ccipRequest?: typeof ccipRequest_
13
+ }
14
+
15
+ export function ccipReadTunnel({
16
+ batchGateways,
17
+ ccipRequest = ccipRequest_,
18
+ }: CcipReadTunnelParameters): { request: typeof ccipRequest_ } {
19
+ return {
20
+ async request({ data, sender, urls }) {
21
+ if (urls.includes(localBatchGatewayUrl)) {
22
+ return ccipRequest({
23
+ data,
24
+ sender,
25
+ urls: batchGateways,
26
+ })
27
+ } else {
28
+ const [failures, responses] = decodeFunctionResult({
29
+ abi: batchGatewayAbi,
30
+ functionName: 'query',
31
+ data: await ccipRequest({
32
+ data: encodeFunctionData({
33
+ abi: batchGatewayAbi,
34
+ functionName: 'query',
35
+ args: [[{ sender, data, urls }]],
36
+ }),
37
+ sender,
38
+ urls: batchGateways,
39
+ }),
40
+ })
41
+ if (failures[0]) {
42
+ let error: Error | undefined
43
+ try {
44
+ const res = decodeErrorResult({
45
+ abi: [...batchGatewayAbi, solidityError],
46
+ data: responses[0],
47
+ })
48
+ if (res.errorName === 'HttpError') {
49
+ error = new HttpRequestError({
50
+ body: { message: res.args[1] },
51
+ status: res.args[0],
52
+ url: urls.join(' | '),
53
+ })
54
+ } else {
55
+ const message = res.args[0]
56
+ if (message) {
57
+ error = new Error(message)
58
+ }
59
+ }
60
+ } catch {}
61
+ throw error ?? new Error('An unknown error occurred.')
62
+ }
63
+ return responses[0]
64
+ }
65
+ },
66
+ }
67
+ }
package/utils/index.ts CHANGED
@@ -155,6 +155,10 @@ export {
155
155
  offchainLookupAbiItem,
156
156
  offchainLookupSignature,
157
157
  } from './ccip.js'
158
+ export {
159
+ type CcipReadTunnelParameters,
160
+ ccipReadTunnel,
161
+ } from './ccipTunnel.js'
158
162
  export {
159
163
  type AssertCurrentChainErrorType,
160
164
  type AssertCurrentChainParameters,