viem 2.47.11 → 2.47.14

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 (68) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/_cjs/actions/public/fillTransaction.js +7 -4
  3. package/_cjs/actions/public/fillTransaction.js.map +1 -1
  4. package/_cjs/actions/wallet/prepareTransactionRequest.js +5 -0
  5. package/_cjs/actions/wallet/prepareTransactionRequest.js.map +1 -1
  6. package/_cjs/errors/version.js +1 -1
  7. package/_cjs/tempo/Decorator.js +5 -0
  8. package/_cjs/tempo/Decorator.js.map +1 -1
  9. package/_cjs/tempo/Expiry.js +31 -0
  10. package/_cjs/tempo/Expiry.js.map +1 -0
  11. package/_cjs/tempo/Formatters.js +2 -0
  12. package/_cjs/tempo/Formatters.js.map +1 -1
  13. package/_cjs/tempo/actions/index.js +2 -1
  14. package/_cjs/tempo/actions/index.js.map +1 -1
  15. package/_cjs/tempo/actions/simulate.js +157 -0
  16. package/_cjs/tempo/actions/simulate.js.map +1 -0
  17. package/_cjs/tempo/index.js +2 -1
  18. package/_cjs/tempo/index.js.map +1 -1
  19. package/_esm/actions/public/fillTransaction.js +7 -4
  20. package/_esm/actions/public/fillTransaction.js.map +1 -1
  21. package/_esm/actions/wallet/prepareTransactionRequest.js +5 -0
  22. package/_esm/actions/wallet/prepareTransactionRequest.js.map +1 -1
  23. package/_esm/errors/version.js +1 -1
  24. package/_esm/tempo/Decorator.js +5 -0
  25. package/_esm/tempo/Decorator.js.map +1 -1
  26. package/_esm/tempo/Expiry.js +29 -0
  27. package/_esm/tempo/Expiry.js.map +1 -0
  28. package/_esm/tempo/Formatters.js +2 -0
  29. package/_esm/tempo/Formatters.js.map +1 -1
  30. package/_esm/tempo/actions/index.js +1 -0
  31. package/_esm/tempo/actions/index.js.map +1 -1
  32. package/_esm/tempo/actions/simulate.js +233 -0
  33. package/_esm/tempo/actions/simulate.js.map +1 -0
  34. package/_esm/tempo/index.js +1 -0
  35. package/_esm/tempo/index.js.map +1 -1
  36. package/_types/actions/public/fillTransaction.d.ts +1 -0
  37. package/_types/actions/public/fillTransaction.d.ts.map +1 -1
  38. package/_types/actions/wallet/prepareTransactionRequest.d.ts.map +1 -1
  39. package/_types/chains/definitions/tempo.d.ts +10 -10
  40. package/_types/chains/definitions/tempoDevnet.d.ts +10 -10
  41. package/_types/chains/definitions/tempoLocalnet.d.ts +10 -10
  42. package/_types/chains/definitions/tempoModerato.d.ts +10 -10
  43. package/_types/errors/version.d.ts +1 -1
  44. package/_types/tempo/Decorator.d.ts +79 -0
  45. package/_types/tempo/Decorator.d.ts.map +1 -1
  46. package/_types/tempo/Expiry.d.ts +15 -0
  47. package/_types/tempo/Expiry.d.ts.map +1 -0
  48. package/_types/tempo/Formatters.d.ts.map +1 -1
  49. package/_types/tempo/actions/index.d.ts +1 -0
  50. package/_types/tempo/actions/index.d.ts.map +1 -1
  51. package/_types/tempo/actions/simulate.d.ts +193 -0
  52. package/_types/tempo/actions/simulate.d.ts.map +1 -0
  53. package/_types/tempo/chainConfig.d.ts +5 -5
  54. package/_types/tempo/index.d.ts +1 -0
  55. package/_types/tempo/index.d.ts.map +1 -1
  56. package/_types/types/eip1193.d.ts +2 -0
  57. package/_types/types/eip1193.d.ts.map +1 -1
  58. package/actions/public/fillTransaction.ts +8 -4
  59. package/actions/wallet/prepareTransactionRequest.ts +5 -0
  60. package/errors/version.ts +1 -1
  61. package/package.json +2 -2
  62. package/tempo/Decorator.ts +92 -0
  63. package/tempo/Expiry.ts +34 -0
  64. package/tempo/Formatters.ts +2 -0
  65. package/tempo/actions/index.ts +1 -0
  66. package/tempo/actions/simulate.ts +452 -0
  67. package/tempo/index.ts +1 -0
  68. package/types/eip1193.ts +2 -0
@@ -0,0 +1,34 @@
1
+ /** Returns a unix timestamp `n` days from now. */
2
+ export function days(n: number) {
3
+ return Math.floor(Date.now() / 1000) + n * 24 * 60 * 60
4
+ }
5
+
6
+ /** Returns a unix timestamp `n` hours from now. */
7
+ export function hours(n: number) {
8
+ return Math.floor(Date.now() / 1000) + n * 60 * 60
9
+ }
10
+
11
+ /** Returns a unix timestamp `n` minutes from now. */
12
+ export function minutes(n: number) {
13
+ return Math.floor(Date.now() / 1000) + n * 60
14
+ }
15
+
16
+ /** Returns a unix timestamp `n` months (30 days) from now. */
17
+ export function months(n: number) {
18
+ return Math.floor(Date.now() / 1000) + n * 30 * 24 * 60 * 60
19
+ }
20
+
21
+ /** Returns a unix timestamp `n` seconds from now. */
22
+ export function seconds(n: number) {
23
+ return Math.floor(Date.now() / 1000) + n
24
+ }
25
+
26
+ /** Returns a unix timestamp `n` weeks from now. */
27
+ export function weeks(n: number) {
28
+ return Math.floor(Date.now() / 1000) + n * 7 * 24 * 60 * 60
29
+ }
30
+
31
+ /** Returns a unix timestamp `n` years (365 days) from now. */
32
+ export function years(n: number) {
33
+ return Math.floor(Date.now() / 1000) + n * 365 * 24 * 60 * 60
34
+ }
@@ -126,6 +126,8 @@ export function formatTransactionRequest(
126
126
  ? account.accessKeyAddress
127
127
  : undefined
128
128
 
129
+ if (account) rpc.from = account.address
130
+
129
131
  return {
130
132
  ...rpc,
131
133
  ...(keyData ? { keyData } : {}),
@@ -7,5 +7,6 @@ export * as fee from './fee.js'
7
7
  export * as nonce from './nonce.js'
8
8
  export * as policy from './policy.js'
9
9
  export * as reward from './reward.js'
10
+ export * as simulate from './simulate.js'
10
11
  export * as token from './token.js'
11
12
  export * as validator from './validator.js'
@@ -0,0 +1,452 @@
1
+ import type { Abi, AbiStateMutability, Address, Narrow } from 'abitype'
2
+ import * as BlockOverrides from 'ox/BlockOverrides'
3
+ import type * as RpcSchema from 'ox/RpcSchema'
4
+ import type { RpcSchemaTempo } from 'ox/tempo'
5
+
6
+ import {
7
+ type ParseAccountErrorType,
8
+ parseAccount,
9
+ } from '../../accounts/utils/parseAccount.js'
10
+ import type { Client } from '../../clients/createClient.js'
11
+ import type { Transport } from '../../clients/transports/createTransport.js'
12
+ import { AbiDecodingZeroDataError } from '../../errors/abi.js'
13
+ import type { BaseError } from '../../errors/base.js'
14
+ import { RawContractError } from '../../errors/contract.js'
15
+ import { UnknownNodeError } from '../../errors/node.js'
16
+ import type { ErrorType as ErrorType_ } from '../../errors/utils.js'
17
+ import type { Account } from '../../types/account.js'
18
+ import type { Block, BlockTag } from '../../types/block.js'
19
+ import type { Call, Calls } from '../../types/calls.js'
20
+ import type { Chain } from '../../types/chain.js'
21
+ import type { Log } from '../../types/log.js'
22
+ import type { Hex } from '../../types/misc.js'
23
+ import type { MulticallResults } from '../../types/multicall.js'
24
+ import type { StateOverride } from '../../types/stateOverride.js'
25
+ import type { TransactionRequest } from '../../types/transaction.js'
26
+ import type { ExactPartial, UnionOmit } from '../../types/utils.js'
27
+ import {
28
+ type DecodeFunctionResultErrorType,
29
+ decodeFunctionResult,
30
+ } from '../../utils/abi/decodeFunctionResult.js'
31
+ import {
32
+ type EncodeFunctionDataErrorType,
33
+ encodeFunctionData,
34
+ } from '../../utils/abi/encodeFunctionData.js'
35
+ import { concat } from '../../utils/data/concat.js'
36
+ import {
37
+ type NumberToHexErrorType,
38
+ numberToHex,
39
+ } from '../../utils/encoding/toHex.js'
40
+ import { getContractError } from '../../utils/errors/getContractError.js'
41
+ import {
42
+ type GetNodeErrorReturnType,
43
+ getNodeError,
44
+ } from '../../utils/errors/getNodeError.js'
45
+ import {
46
+ type FormatBlockErrorType,
47
+ formatBlock,
48
+ } from '../../utils/formatters/block.js'
49
+ import { formatLog } from '../../utils/formatters/log.js'
50
+ import {
51
+ type FormatTransactionRequestErrorType,
52
+ formatTransactionRequest,
53
+ } from '../../utils/formatters/transactionRequest.js'
54
+ import {
55
+ type SerializeStateOverrideErrorType,
56
+ serializeStateOverride,
57
+ } from '../../utils/stateOverride.js'
58
+ import {
59
+ type AssertRequestErrorType,
60
+ assertRequest,
61
+ } from '../../utils/transaction/assertRequest.js'
62
+
63
+ export type TokenMetadata = {
64
+ [address: Hex]: {
65
+ name: string
66
+ symbol: string
67
+ currency: string
68
+ }
69
+ }
70
+
71
+ type CallExtraProperties = ExactPartial<
72
+ UnionOmit<
73
+ TransactionRequest,
74
+ 'blobs' | 'data' | 'kzg' | 'to' | 'sidecars' | 'value'
75
+ >
76
+ > & {
77
+ /** Account attached to the call (msg.sender). */
78
+ account?: Account | Address | undefined
79
+ /** Recipient. `null` if contract deployment. */
80
+ to?: Address | null | undefined
81
+ }
82
+
83
+ /**
84
+ * Simulates a set of calls on block(s) via `tempo_simulateV1`.
85
+ *
86
+ * Returns simulated block results and token metadata for any TIP-20
87
+ * tokens involved in the simulation.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * import { createClient, http, parseUnits } from 'viem'
92
+ * import { tempo } from 'viem/chains'
93
+ * import { Actions } from 'viem/tempo'
94
+ *
95
+ * const client = createClient({
96
+ * account: '0x...',
97
+ * chain: tempo,
98
+ * transport: http(),
99
+ * })
100
+ *
101
+ * const { blocks, tokenMetadata } = await Actions.simulate.simulateBlocks(client, {
102
+ * blocks: [{
103
+ * calls: [
104
+ * Actions.token.transfer.call({
105
+ * token: '0x20c0...01',
106
+ * to: '0x...',
107
+ * amount: parseUnits('100', 6),
108
+ * }),
109
+ * ],
110
+ * }],
111
+ * traceTransfers: true,
112
+ * })
113
+ * ```
114
+ *
115
+ * @param client - Client.
116
+ * @param parameters - {@link simulateBlocks.Parameters}
117
+ * @returns Simulated blocks and token metadata. {@link simulateBlocks.ReturnType}
118
+ */
119
+ export async function simulateBlocks<
120
+ chain extends Chain | undefined,
121
+ const calls extends readonly unknown[],
122
+ >(
123
+ client: Client<Transport, chain>,
124
+ parameters: simulateBlocks.Parameters<calls>,
125
+ ): Promise<simulateBlocks.ReturnType<calls>> {
126
+ const {
127
+ blockNumber,
128
+ blockTag = client.experimental_blockTag ?? 'latest',
129
+ blocks,
130
+ returnFullTransactions,
131
+ traceTransfers,
132
+ validation,
133
+ } = parameters
134
+
135
+ try {
136
+ const blockStateCalls = []
137
+ for (const block of blocks) {
138
+ const blockOverrides = block.blockOverrides
139
+ ? BlockOverrides.toRpc(block.blockOverrides)
140
+ : undefined
141
+ const calls = block.calls.map((call_) => {
142
+ const call = call_ as Call<unknown, CallExtraProperties>
143
+ const account = call.account
144
+ ? parseAccount(call.account)
145
+ : client.account
146
+ ? parseAccount(client.account)
147
+ : undefined
148
+ const data = call.abi ? encodeFunctionData(call) : call.data
149
+ const request = {
150
+ ...call,
151
+ account,
152
+ data: call.dataSuffix
153
+ ? concat([data || '0x', call.dataSuffix])
154
+ : data,
155
+ from: call.from ?? account?.address,
156
+ } as const
157
+ assertRequest(request)
158
+ return formatTransactionRequest(request)
159
+ })
160
+ const stateOverrides = block.stateOverrides
161
+ ? serializeStateOverride(block.stateOverrides)
162
+ : undefined
163
+
164
+ blockStateCalls.push({
165
+ blockOverrides,
166
+ calls,
167
+ stateOverrides,
168
+ })
169
+ }
170
+
171
+ const blockNumberHex =
172
+ typeof blockNumber === 'bigint' ? numberToHex(blockNumber) : undefined
173
+ const block = blockNumberHex || blockTag
174
+
175
+ type tempo_simulateV1 = RpcSchema.ToViem<RpcSchemaTempo.Tempo>[0]
176
+ const result = await client.request<tempo_simulateV1>({
177
+ method: 'tempo_simulateV1',
178
+ params: [
179
+ {
180
+ blockStateCalls,
181
+ returnFullTransactions,
182
+ traceTransfers,
183
+ validation,
184
+ } as tempo_simulateV1['Parameters'][0],
185
+ block,
186
+ ],
187
+ })
188
+
189
+ return {
190
+ blocks: result.blocks.map((block, i) => ({
191
+ ...formatBlock(block as never),
192
+ calls: block.calls?.map((call, j) => {
193
+ const { abi, args, functionName, to } = blocks[i].calls[j] as Call<
194
+ unknown,
195
+ CallExtraProperties
196
+ >
197
+
198
+ const data = call.error?.data ?? call.returnData
199
+ const gasUsed = BigInt(call.gasUsed)
200
+ const logs = call.logs?.map((log) => formatLog(log))
201
+ const status = call.status === '0x1' ? 'success' : 'failure'
202
+
203
+ const result =
204
+ abi && status === 'success' && data !== '0x'
205
+ ? decodeFunctionResult({
206
+ abi,
207
+ data,
208
+ functionName,
209
+ })
210
+ : null
211
+
212
+ const error = (() => {
213
+ if (status === 'success') return undefined
214
+
215
+ let error: Error | undefined
216
+ if (data === '0x') error = new AbiDecodingZeroDataError()
217
+ else if (data) error = new RawContractError({ data })
218
+
219
+ if (!error) return undefined
220
+ return getContractError(error, {
221
+ abi: (abi ?? []) as Abi,
222
+ address: to ?? '0x',
223
+ args,
224
+ functionName: functionName ?? '<unknown>',
225
+ })
226
+ })()
227
+
228
+ return {
229
+ data,
230
+ gasUsed,
231
+ logs,
232
+ status,
233
+ ...(status === 'success'
234
+ ? {
235
+ result,
236
+ }
237
+ : {
238
+ error,
239
+ }),
240
+ }
241
+ }),
242
+ })),
243
+ tokenMetadata: result.tokenMetadata ?? {},
244
+ } as unknown as simulateBlocks.ReturnType<calls>
245
+ } catch (e) {
246
+ const cause = e as BaseError
247
+ const error = getNodeError(cause, {})
248
+ if (error instanceof UnknownNodeError) throw cause
249
+ throw error
250
+ }
251
+ }
252
+
253
+ export declare namespace simulateBlocks {
254
+ export type Parameters<
255
+ calls extends readonly unknown[] = readonly unknown[],
256
+ > = {
257
+ /** Blocks to simulate. */
258
+ blocks: readonly {
259
+ /** Block overrides. */
260
+ blockOverrides?: BlockOverrides.BlockOverrides | undefined
261
+ /** Calls to execute. */
262
+ calls: Calls<Narrow<calls>, CallExtraProperties>
263
+ /** State overrides. */
264
+ stateOverrides?: StateOverride | undefined
265
+ }[]
266
+ /** Whether to return the full transactions. */
267
+ returnFullTransactions?: boolean | undefined
268
+ /** Whether to trace transfers. */
269
+ traceTransfers?: boolean | undefined
270
+ /** Whether to enable validation mode. */
271
+ validation?: boolean | undefined
272
+ } & (
273
+ | {
274
+ /** The balance of the account at a block number. */
275
+ blockNumber?: bigint | undefined
276
+ blockTag?: undefined
277
+ }
278
+ | {
279
+ blockNumber?: undefined
280
+ /**
281
+ * The balance of the account at a block tag.
282
+ * @default 'latest'
283
+ */
284
+ blockTag?: BlockTag | undefined
285
+ }
286
+ )
287
+
288
+ export type ReturnType<
289
+ calls extends readonly unknown[] = readonly unknown[],
290
+ > = {
291
+ blocks: readonly (Block & {
292
+ calls: MulticallResults<
293
+ Narrow<calls>,
294
+ true,
295
+ {
296
+ extraProperties: {
297
+ data: Hex
298
+ gasUsed: bigint
299
+ logs?: Log[] | undefined
300
+ }
301
+ error: Error
302
+ mutability: AbiStateMutability
303
+ }
304
+ >
305
+ })[]
306
+ tokenMetadata: TokenMetadata
307
+ }
308
+
309
+ export type ErrorType =
310
+ | AssertRequestErrorType
311
+ | DecodeFunctionResultErrorType
312
+ | EncodeFunctionDataErrorType
313
+ | FormatBlockErrorType
314
+ | FormatTransactionRequestErrorType
315
+ | GetNodeErrorReturnType
316
+ | ParseAccountErrorType
317
+ | SerializeStateOverrideErrorType
318
+ | NumberToHexErrorType
319
+ | ErrorType_
320
+ }
321
+
322
+ /**
323
+ * Simulates execution of a batch of calls via `tempo_simulateV1`.
324
+ *
325
+ * A convenience wrapper around {@link simulateBlocks} that runs all
326
+ * calls in a single block and returns flattened results.
327
+ *
328
+ * @example
329
+ * ```ts
330
+ * import { createClient, http, parseUnits } from 'viem'
331
+ * import { tempo } from 'viem/chains'
332
+ * import { Actions, Addresses } from 'viem/tempo'
333
+ *
334
+ * const client = createClient({
335
+ * account: '0x...',
336
+ * chain: tempo,
337
+ * transport: http(),
338
+ * })
339
+ *
340
+ * const { results, tokenMetadata } = await Actions.simulate.simulateCalls(client, {
341
+ * calls: [
342
+ * Actions.token.approve.call({
343
+ * token: '0x20c0...01',
344
+ * spender: Addresses.stablecoinDex,
345
+ * amount: parseUnits('100', 6),
346
+ * }),
347
+ * Actions.dex.buy.call({
348
+ * tokenIn: '0x20c0...01',
349
+ * tokenOut: '0x20c0...02',
350
+ * amountOut: parseUnits('10', 6),
351
+ * maxAmountIn: parseUnits('100', 6),
352
+ * }),
353
+ * Actions.token.transfer.call({
354
+ * token: '0x20c0...02',
355
+ * to: '0x...',
356
+ * amount: parseUnits('10', 6),
357
+ * }),
358
+ * ],
359
+ * })
360
+ * ```
361
+ *
362
+ * @param client - Client.
363
+ * @param parameters - {@link simulateCalls.Parameters}
364
+ * @returns Results, block, and token metadata. {@link simulateCalls.ReturnType}
365
+ */
366
+ export async function simulateCalls<
367
+ const calls extends readonly unknown[],
368
+ chain extends Chain | undefined,
369
+ account extends Account | Address | undefined = undefined,
370
+ >(
371
+ client: Client<Transport, chain>,
372
+ parameters: simulateCalls.Parameters<calls, account>,
373
+ ): Promise<simulateCalls.ReturnType<calls>> {
374
+ const {
375
+ blockNumber,
376
+ blockTag,
377
+ calls,
378
+ stateOverrides,
379
+ traceTransfers,
380
+ validation,
381
+ } = parameters
382
+
383
+ const account = parameters.account
384
+ ? parseAccount(parameters.account)
385
+ : undefined
386
+
387
+ const result = await simulateBlocks(client, {
388
+ blockNumber,
389
+ blockTag: blockTag as undefined,
390
+ blocks: [
391
+ {
392
+ calls: calls.map((call) => ({
393
+ ...(call as Call),
394
+ from: account?.address,
395
+ })) as any,
396
+ stateOverrides,
397
+ },
398
+ ],
399
+ traceTransfers,
400
+ validation,
401
+ })
402
+
403
+ const { calls: block_calls, ...block } = result.blocks[0]
404
+
405
+ return {
406
+ block,
407
+ results: block_calls,
408
+ tokenMetadata: result.tokenMetadata,
409
+ } as unknown as simulateCalls.ReturnType<calls>
410
+ }
411
+
412
+ export declare namespace simulateCalls {
413
+ export type Parameters<
414
+ calls extends readonly unknown[] = readonly unknown[],
415
+ account extends Account | Address | undefined =
416
+ | Account
417
+ | Address
418
+ | undefined,
419
+ > = Omit<simulateBlocks.Parameters, 'blocks' | 'returnFullTransactions'> & {
420
+ /** Account attached to the calls (msg.sender). */
421
+ account?: account | undefined
422
+ /** Calls to simulate. */
423
+ calls: Calls<Narrow<calls>>
424
+ /** State overrides. */
425
+ stateOverrides?: StateOverride | undefined
426
+ }
427
+
428
+ export type ReturnType<
429
+ calls extends readonly unknown[] = readonly unknown[],
430
+ > = {
431
+ /** Block results. */
432
+ block: Block
433
+ /** Call results. */
434
+ results: MulticallResults<
435
+ Narrow<calls>,
436
+ true,
437
+ {
438
+ extraProperties: {
439
+ data: Hex
440
+ gasUsed: bigint
441
+ logs?: Log[] | undefined
442
+ }
443
+ error: Error
444
+ mutability: AbiStateMutability
445
+ }
446
+ >
447
+ /** Token metadata resolved from the simulation. */
448
+ tokenMetadata: TokenMetadata
449
+ }
450
+
451
+ export type ErrorType = simulateBlocks.ErrorType | ErrorType_
452
+ }
package/tempo/index.ts CHANGED
@@ -20,6 +20,7 @@ export {
20
20
  type Decorator as TempoActions,
21
21
  decorator as tempoActions,
22
22
  } from './Decorator.js'
23
+ export * as Expiry from './Expiry.js'
23
24
  export * as Formatters from './Formatters.js'
24
25
  export * as Hardfork from './Hardfork.js'
25
26
  export * as P256 from './P256.js'
package/types/eip1193.ts CHANGED
@@ -764,6 +764,7 @@ export type PublicRpcSchema = [
764
764
  Method: 'eth_fillTransaction'
765
765
  Parameters: [transaction: TransactionRequest]
766
766
  ReturnType: {
767
+ meta?: Record<string, unknown> | undefined
767
768
  raw: Hex
768
769
  tx: Transaction
769
770
  }
@@ -1727,6 +1728,7 @@ export type WalletRpcSchema = [
1727
1728
  Method: 'eth_fillTransaction'
1728
1729
  Parameters: [transaction: TransactionRequest]
1729
1730
  ReturnType: {
1731
+ meta?: Record<string, unknown> | undefined
1730
1732
  raw: Hex
1731
1733
  tx: Transaction
1732
1734
  }