viem 2.49.0 → 2.49.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 (39) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/_cjs/chains/definitions/arc.js +19 -0
  3. package/_cjs/chains/definitions/arc.js.map +1 -0
  4. package/_cjs/chains/index.js +17 -15
  5. package/_cjs/chains/index.js.map +1 -1
  6. package/_cjs/errors/version.js +1 -1
  7. package/_cjs/tempo/Formatters.js +12 -4
  8. package/_cjs/tempo/Formatters.js.map +1 -1
  9. package/_cjs/tempo/Transaction.js +5 -2
  10. package/_cjs/tempo/Transaction.js.map +1 -1
  11. package/_cjs/tempo/actions/wallet.js +3 -3
  12. package/_cjs/tempo/actions/wallet.js.map +1 -1
  13. package/_esm/chains/definitions/arc.js +16 -0
  14. package/_esm/chains/definitions/arc.js.map +1 -0
  15. package/_esm/chains/index.js +1 -0
  16. package/_esm/chains/index.js.map +1 -1
  17. package/_esm/errors/version.js +1 -1
  18. package/_esm/tempo/Formatters.js +31 -8
  19. package/_esm/tempo/Formatters.js.map +1 -1
  20. package/_esm/tempo/Transaction.js +16 -6
  21. package/_esm/tempo/Transaction.js.map +1 -1
  22. package/_esm/tempo/actions/wallet.js +18 -5
  23. package/_esm/tempo/actions/wallet.js.map +1 -1
  24. package/_types/chains/definitions/arc.d.ts +54 -0
  25. package/_types/chains/definitions/arc.d.ts.map +1 -0
  26. package/_types/chains/index.d.ts +1 -0
  27. package/_types/chains/index.d.ts.map +1 -1
  28. package/_types/errors/version.d.ts +1 -1
  29. package/_types/tempo/Formatters.d.ts.map +1 -1
  30. package/_types/tempo/Transaction.d.ts.map +1 -1
  31. package/_types/tempo/actions/wallet.d.ts +67 -15
  32. package/_types/tempo/actions/wallet.d.ts.map +1 -1
  33. package/chains/definitions/arc.ts +16 -0
  34. package/chains/index.ts +1 -0
  35. package/errors/version.ts +1 -1
  36. package/package.json +1 -1
  37. package/tempo/Formatters.ts +35 -8
  38. package/tempo/Transaction.ts +16 -6
  39. package/tempo/actions/wallet.ts +75 -21
@@ -0,0 +1,16 @@
1
+ import { defineChain } from '../../utils/chain/defineChain.js'
2
+
3
+ export const arc = /*#__PURE__*/ defineChain({
4
+ id: 5042,
5
+ name: 'Arc',
6
+ nativeCurrency: {
7
+ name: 'USDC',
8
+ symbol: 'USDC',
9
+ decimals: 18,
10
+ },
11
+ rpcUrls: {
12
+ default: {
13
+ http: [],
14
+ },
15
+ },
16
+ })
package/chains/index.ts CHANGED
@@ -33,6 +33,7 @@ export { arbitrum } from './definitions/arbitrum.js'
33
33
  export { arbitrumGoerli } from './definitions/arbitrumGoerli.js'
34
34
  export { arbitrumNova } from './definitions/arbitrumNova.js'
35
35
  export { arbitrumSepolia } from './definitions/arbitrumSepolia.js'
36
+ export { arc } from './definitions/arc.js'
36
37
  export { arcTestnet } from './definitions/arcTestnet.js'
37
38
  export { arenaz } from './definitions/arenaz.js'
38
39
  export { areonNetwork } from './definitions/areonNetwork.js'
package/errors/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '2.49.0'
1
+ export const version = '2.49.3'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "viem",
3
3
  "description": "TypeScript Interface for Ethereum",
4
- "version": "2.49.0",
4
+ "version": "2.49.3",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
7
7
  "types": "./_types/index.d.ts",
@@ -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,
@@ -122,12 +133,15 @@ export function formatTransactionRequest(
122
133
  const [keyType, keyData] = (() => {
123
134
  const type =
124
135
  account && 'keyType' in account ? account.keyType : account?.source
125
- if (!type) return [request.keyType, request.keyData]
136
+ if (!type) return [request.keyType, shimKeyData(request.keyData)]
126
137
  if (type === 'webAuthn')
127
- // TODO: derive correct bytes size of key data based on webauthn create metadata.
128
- return ['webAuthn', `0x${'ff'.repeat(1400)}`]
138
+ // Send a 2-byte big-endian length hint (1400 = 0x0578) instead of a
139
+ // 1400-byte dummy blob. The node's gas estimator expects key_data to
140
+ // be 1, 2, or 4 bytes encoding the desired WebAuthn signature size;
141
+ // anything else falls back to the 800-byte default.
142
+ return ['webAuthn', '0x0578']
129
143
  if (['p256', 'secp256k1'].includes(type)) return [type, undefined]
130
- return [request.keyType, request.keyData]
144
+ return [request.keyType, shimKeyData(request.keyData)]
131
145
  })()
132
146
 
133
147
  const keyId =
@@ -157,3 +171,16 @@ export function formatTransactionRequest(
157
171
  : {}),
158
172
  } as never
159
173
  }
174
+
175
+ /**
176
+ * Auto-shim user-provided keyData that is longer than 4 bytes into a
177
+ * 2-byte big-endian length hint. The node gas estimator only accepts
178
+ * 1, 2, or 4-byte key_data as a size hint; anything else silently falls
179
+ * back to the 800-byte default.
180
+ */
181
+ function shimKeyData(data: Hex.Hex | undefined): Hex.Hex | undefined {
182
+ if (!data) return data
183
+ const byteLength = (data.length - 2) / 2 // subtract "0x" prefix
184
+ if (byteLength <= 4) return data
185
+ return Hex.fromNumber(byteLength, { size: 2 })
186
+ }
@@ -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,
@@ -3,11 +3,18 @@ import type { Client } from '../../clients/createClient.js'
3
3
  import type { Transport } from '../../clients/transports/createTransport.js'
4
4
  import type { ErrorType as CoreErrorType } from '../../errors/utils.js'
5
5
  import type { Chain } from '../../types/chain.js'
6
+ import type { OneOf } from '../../types/utils.js'
6
7
  import type { RequestErrorType } from '../../utils/buildRequest.js'
7
8
  import type { TransactionReceipt } from '../Transaction.js'
8
9
 
9
10
  /**
10
- * Opens the wallet send flow with optional pre-filled send fields.
11
+ * Transfers a TIP-20 token. Discriminated on `editable`:
12
+ *
13
+ * - omitted or `false` (default): read-only. Uses an access key when
14
+ * one matches (signs without showing the wallet UI), otherwise falls
15
+ * back to a confirm dialog the user has to approve.
16
+ * - `true`: editable. Opens the wallet send UI with the supplied fields
17
+ * pre-filled for the user to confirm or edit before signing.
11
18
  *
12
19
  * @example
13
20
  * ```ts
@@ -18,46 +25,83 @@ import type { TransactionReceipt } from '../Transaction.js'
18
25
  * transport: custom(window.ethereum),
19
26
  * })
20
27
  *
21
- * const { receipt } = await Actions.wallet.send(client, {
28
+ * // Read-only (no UI when an access key matches)
29
+ * const { receipt } = await Actions.wallet.transfer(client, {
22
30
  * amount: '1.5',
23
31
  * to: '0x...',
24
32
  * token: '0x...',
25
33
  * })
34
+ *
35
+ * // Editable (opens wallet UI)
36
+ * await Actions.wallet.transfer(client, {
37
+ * editable: true,
38
+ * token: 'pathUSD',
39
+ * })
26
40
  * ```
27
41
  *
28
42
  * @param client - Client.
29
43
  * @param parameters - Parameters.
30
- * @returns The submitted send receipt and chain ID.
44
+ * @returns The submitted transfer receipt and chain ID.
31
45
  */
32
- export async function send<chain extends Chain | undefined>(
46
+ export async function transfer<chain extends Chain | undefined>(
33
47
  client: Client<Transport, chain>,
34
- parameters: send.Parameters = {},
35
- ): Promise<send.ReturnValue> {
48
+ parameters: transfer.Parameters,
49
+ ): Promise<transfer.ReturnValue> {
36
50
  return client.request<{
37
- Method: 'wallet_send'
38
- Parameters: [send.Parameters]
39
- ReturnType: send.ReturnValue
51
+ Method: 'wallet_transfer'
52
+ Parameters: [transfer.Parameters]
53
+ ReturnType: transfer.ReturnValue
40
54
  }>(
41
55
  {
42
- method: 'wallet_send',
56
+ method: 'wallet_transfer',
43
57
  params: [parameters],
44
58
  },
45
59
  { retryCount: 0 },
46
60
  )
47
61
  }
48
62
 
49
- export declare namespace send {
50
- export type Parameters = {
51
- /** Human-readable amount to pre-fill (for example, "1.5"). */
52
- amount?: string | undefined
63
+ export declare namespace transfer {
64
+ /**
65
+ * Read-only variant uses an access key when one matches, otherwise
66
+ * shows a confirm dialog.
67
+ */
68
+ type ReadOnly = {
69
+ /** Human-readable amount to transfer (for example, `"1.5"`). */
70
+ amount: string
53
71
  /**
54
- * Fee payer override. `false` to disable the wallet's default fee payer,
55
- * a URL string to use a custom fee payer service.
72
+ * Skip the editable wallet UI. The wallet still shows a confirm
73
+ * dialog when no matching access key is available.
74
+ * @default false
56
75
  */
57
- feePayer?: boolean | string | undefined
76
+ editable?: false | undefined
77
+ /**
78
+ * Address to transfer tokens from. Defaults to the active account. When
79
+ * set to a different address, the call uses `transferFrom` and requires
80
+ * the active account to have an allowance from `from`.
81
+ */
82
+ from?: Address | undefined
83
+ /**
84
+ * UTF-8 memo (max 32 bytes) to attach to the transfer.
85
+ */
86
+ memo?: string | undefined
87
+ /** Recipient address. */
88
+ to: Address
58
89
  /**
59
- * UTF-8 memo (max 32 bytes) to attach to the transfer. Wallet rejects
60
- * the request if the selected token does not support memos (non-TIP-20).
90
+ * Token to transfer, accepted as either a contract address or a curated
91
+ * tokenlist symbol (case-insensitive, for example `"pathUsd"`). Symbols
92
+ * are resolved against the curated tokenlist on the active chain.
93
+ */
94
+ token: Address | string
95
+ }
96
+
97
+ /** Editable variant — opens the wallet send UI with optional pre-filled fields. */
98
+ type Editable = {
99
+ /** Human-readable amount to pre-fill (for example, `"1.5"`). */
100
+ amount?: string | undefined
101
+ /** Show the wallet UI for the user to confirm or edit. */
102
+ editable: true
103
+ /**
104
+ * UTF-8 memo (max 32 bytes) to attach to the transfer.
61
105
  */
62
106
  memo?: string | undefined
63
107
  /** Recipient address to pre-fill. */
@@ -71,10 +115,20 @@ export declare namespace send {
71
115
  token?: Address | string | undefined
72
116
  }
73
117
 
118
+ export type Parameters = {
119
+ /** Chain id. Defaults to the active chain. */
120
+ chainId?: number | undefined
121
+ /**
122
+ * Fee payer override. `false` to disable the wallet's default fee payer,
123
+ * a URL string to use a custom fee payer service.
124
+ */
125
+ feePayer?: boolean | string | undefined
126
+ } & OneOf<ReadOnly | Editable>
127
+
74
128
  export type ReturnValue = {
75
- /** Chain ID the send was submitted to. */
129
+ /** Chain ID the transfer was submitted to. */
76
130
  chainId: number
77
- /** Receipt of the submitted send. */
131
+ /** Receipt of the submitted transfer. */
78
132
  receipt: TransactionReceipt
79
133
  }
80
134