viem 2.56.9 → 2.57.0

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 +40 -0
  2. package/_cjs/actions/public/waitForTransactionReceipt.js +12 -1
  3. package/_cjs/actions/public/waitForTransactionReceipt.js.map +1 -1
  4. package/_cjs/chains/definitions/blockdag.js +23 -0
  5. package/_cjs/chains/definitions/blockdag.js.map +1 -0
  6. package/_cjs/chains/definitions/candyChain.js +29 -0
  7. package/_cjs/chains/definitions/candyChain.js.map +1 -0
  8. package/_cjs/chains/definitions/creditCoin3Devnet.js +6 -0
  9. package/_cjs/chains/definitions/creditCoin3Devnet.js.map +1 -1
  10. package/_cjs/chains/definitions/creditCoin3Mainnet.js +6 -0
  11. package/_cjs/chains/definitions/creditCoin3Mainnet.js.map +1 -1
  12. package/_cjs/chains/definitions/creditCoin3Testnet.js +6 -0
  13. package/_cjs/chains/definitions/creditCoin3Testnet.js.map +1 -1
  14. package/_cjs/chains/definitions/kortana.js +23 -0
  15. package/_cjs/chains/definitions/kortana.js.map +1 -0
  16. package/_cjs/chains/index.js +20 -14
  17. package/_cjs/chains/index.js.map +1 -1
  18. package/_cjs/clients/createClientResolver.js +45 -0
  19. package/_cjs/clients/createClientResolver.js.map +1 -0
  20. package/_cjs/errors/version.js +1 -1
  21. package/_cjs/index.js +13 -9
  22. package/_cjs/index.js.map +1 -1
  23. package/_cjs/op-stack/actions/getGame.js +1 -1
  24. package/_cjs/op-stack/actions/getGame.js.map +1 -1
  25. package/_cjs/op-stack/actions/getGames.js +1 -1
  26. package/_cjs/op-stack/actions/getGames.js.map +1 -1
  27. package/_cjs/op-stack/actions/getTimeToNextGame.js +1 -1
  28. package/_cjs/op-stack/actions/getTimeToNextGame.js.map +1 -1
  29. package/_cjs/op-stack/actions/getTimeToNextL2Output.js +1 -1
  30. package/_cjs/op-stack/actions/getTimeToNextL2Output.js.map +1 -1
  31. package/_cjs/tempo/Client.js +2 -10
  32. package/_cjs/tempo/Client.js.map +1 -1
  33. package/_cjs/tempo/ExecutionError.js +290 -0
  34. package/_cjs/tempo/ExecutionError.js.map +1 -0
  35. package/_cjs/tempo/Relay.js +88 -0
  36. package/_cjs/tempo/Relay.js.map +1 -0
  37. package/_cjs/tempo/Transaction.js.map +1 -1
  38. package/_cjs/tempo/Transport.js +21 -12
  39. package/_cjs/tempo/Transport.js.map +1 -1
  40. package/_cjs/tempo/chainConfig.js +3 -0
  41. package/_cjs/tempo/chainConfig.js.map +1 -1
  42. package/_cjs/tempo/index.js +3 -3
  43. package/_cjs/tempo/index.js.map +1 -1
  44. package/_cjs/tempo/internal/relay/cache.js +74 -0
  45. package/_cjs/tempo/internal/relay/cache.js.map +1 -0
  46. package/_cjs/tempo/internal/relay/deadline.js +35 -0
  47. package/_cjs/tempo/internal/relay/deadline.js.map +1 -0
  48. package/_cjs/tempo/internal/relay/error.js +102 -0
  49. package/_cjs/tempo/internal/relay/error.js.map +1 -0
  50. package/_cjs/tempo/internal/relay/feePayer.js +426 -0
  51. package/_cjs/tempo/internal/relay/feePayer.js.map +1 -0
  52. package/_cjs/tempo/internal/relay/feeToken.js +143 -0
  53. package/_cjs/tempo/internal/relay/feeToken.js.map +1 -0
  54. package/_cjs/tempo/{Multisig.js → internal/relay/multisig.js} +132 -122
  55. package/_cjs/tempo/internal/relay/multisig.js.map +1 -0
  56. package/_cjs/tempo/internal/relay/plugin.js +13 -0
  57. package/_cjs/tempo/internal/relay/plugin.js.map +1 -0
  58. package/_cjs/tempo/internal/relay/preflight.js +58 -0
  59. package/_cjs/tempo/internal/relay/preflight.js.map +1 -0
  60. package/_cjs/tempo/internal/relay/request.js +319 -0
  61. package/_cjs/tempo/internal/relay/request.js.map +1 -0
  62. package/_cjs/tempo/internal/relay/simulate.js +267 -0
  63. package/_cjs/tempo/internal/relay/simulate.js.map +1 -0
  64. package/_cjs/tempo/internal/relay/utils.js +174 -0
  65. package/_cjs/tempo/internal/relay/utils.js.map +1 -0
  66. package/_cjs/tempo/internal/relay/virtualAddress.js +78 -0
  67. package/_cjs/tempo/internal/relay/virtualAddress.js.map +1 -0
  68. package/_cjs/tempo/internal/relay.js +139 -0
  69. package/_cjs/tempo/internal/relay.js.map +1 -0
  70. package/_cjs/tempo/multisig/Config.js +0 -2
  71. package/_cjs/tempo/multisig/Config.js.map +1 -1
  72. package/_cjs/tempo/multisig/Operation.js +1 -2
  73. package/_cjs/tempo/multisig/Operation.js.map +1 -1
  74. package/_cjs/utils/siwe/parseSiweMessage.js +3 -3
  75. package/_cjs/utils/siwe/parseSiweMessage.js.map +1 -1
  76. package/_esm/actions/public/waitForTransactionReceipt.js +15 -1
  77. package/_esm/actions/public/waitForTransactionReceipt.js.map +1 -1
  78. package/_esm/chains/definitions/blockdag.js +20 -0
  79. package/_esm/chains/definitions/blockdag.js.map +1 -0
  80. package/_esm/chains/definitions/candyChain.js +26 -0
  81. package/_esm/chains/definitions/candyChain.js.map +1 -0
  82. package/_esm/chains/definitions/creditCoin3Devnet.js +6 -0
  83. package/_esm/chains/definitions/creditCoin3Devnet.js.map +1 -1
  84. package/_esm/chains/definitions/creditCoin3Mainnet.js +6 -0
  85. package/_esm/chains/definitions/creditCoin3Mainnet.js.map +1 -1
  86. package/_esm/chains/definitions/creditCoin3Testnet.js +6 -0
  87. package/_esm/chains/definitions/creditCoin3Testnet.js.map +1 -1
  88. package/_esm/chains/definitions/kortana.js +20 -0
  89. package/_esm/chains/definitions/kortana.js.map +1 -0
  90. package/_esm/chains/index.js +3 -0
  91. package/_esm/chains/index.js.map +1 -1
  92. package/_esm/clients/createClientResolver.js +64 -0
  93. package/_esm/clients/createClientResolver.js.map +1 -0
  94. package/_esm/errors/version.js +1 -1
  95. package/_esm/index.js +2 -0
  96. package/_esm/index.js.map +1 -1
  97. package/_esm/op-stack/actions/getGame.js +1 -1
  98. package/_esm/op-stack/actions/getGame.js.map +1 -1
  99. package/_esm/op-stack/actions/getGames.js +1 -1
  100. package/_esm/op-stack/actions/getGames.js.map +1 -1
  101. package/_esm/op-stack/actions/getTimeToNextGame.js +2 -2
  102. package/_esm/op-stack/actions/getTimeToNextGame.js.map +1 -1
  103. package/_esm/op-stack/actions/getTimeToNextL2Output.js +2 -2
  104. package/_esm/op-stack/actions/getTimeToNextL2Output.js.map +1 -1
  105. package/_esm/tempo/Client.js +8 -14
  106. package/_esm/tempo/Client.js.map +1 -1
  107. package/_esm/tempo/ExecutionError.js +306 -0
  108. package/_esm/tempo/ExecutionError.js.map +1 -0
  109. package/_esm/tempo/Relay.js +170 -0
  110. package/_esm/tempo/Relay.js.map +1 -0
  111. package/_esm/tempo/Transaction.js.map +1 -1
  112. package/_esm/tempo/Transport.js +21 -46
  113. package/_esm/tempo/Transport.js.map +1 -1
  114. package/_esm/tempo/chainConfig.js +4 -0
  115. package/_esm/tempo/chainConfig.js.map +1 -1
  116. package/_esm/tempo/index.js +8 -3
  117. package/_esm/tempo/index.js.map +1 -1
  118. package/_esm/tempo/internal/relay/cache.js +72 -0
  119. package/_esm/tempo/internal/relay/cache.js.map +1 -0
  120. package/_esm/tempo/internal/relay/deadline.js +34 -0
  121. package/_esm/tempo/internal/relay/deadline.js.map +1 -0
  122. package/_esm/tempo/internal/relay/error.js +101 -0
  123. package/_esm/tempo/internal/relay/error.js.map +1 -0
  124. package/_esm/tempo/internal/relay/feePayer.js +442 -0
  125. package/_esm/tempo/internal/relay/feePayer.js.map +1 -0
  126. package/_esm/tempo/internal/relay/feeToken.js +143 -0
  127. package/_esm/tempo/internal/relay/feeToken.js.map +1 -0
  128. package/_esm/tempo/{Multisig.js → internal/relay/multisig.js} +133 -129
  129. package/_esm/tempo/internal/relay/multisig.js.map +1 -0
  130. package/_esm/tempo/internal/relay/plugin.js +10 -0
  131. package/_esm/tempo/internal/relay/plugin.js.map +1 -0
  132. package/_esm/tempo/internal/relay/preflight.js +57 -0
  133. package/_esm/tempo/internal/relay/preflight.js.map +1 -0
  134. package/_esm/tempo/internal/relay/request.js +321 -0
  135. package/_esm/tempo/internal/relay/request.js.map +1 -0
  136. package/_esm/tempo/internal/relay/simulate.js +277 -0
  137. package/_esm/tempo/internal/relay/simulate.js.map +1 -0
  138. package/_esm/tempo/internal/relay/utils.js +174 -0
  139. package/_esm/tempo/internal/relay/utils.js.map +1 -0
  140. package/_esm/tempo/internal/relay/virtualAddress.js +73 -0
  141. package/_esm/tempo/internal/relay/virtualAddress.js.map +1 -0
  142. package/_esm/tempo/internal/relay.js +138 -0
  143. package/_esm/tempo/internal/relay.js.map +1 -0
  144. package/_esm/tempo/multisig/Config.js +2 -1
  145. package/_esm/tempo/multisig/Config.js.map +1 -1
  146. package/_esm/tempo/multisig/Operation.js +1 -1
  147. package/_esm/tempo/multisig/Operation.js.map +1 -1
  148. package/_esm/utils/siwe/parseSiweMessage.js +3 -3
  149. package/_esm/utils/siwe/parseSiweMessage.js.map +1 -1
  150. package/_types/actions/public/waitForTransactionReceipt.d.ts.map +1 -1
  151. package/_types/chains/definitions/blockdag.d.ts +51 -0
  152. package/_types/chains/definitions/blockdag.d.ts.map +1 -0
  153. package/_types/chains/definitions/candyChain.d.ts +48 -0
  154. package/_types/chains/definitions/candyChain.d.ts.map +1 -0
  155. package/_types/chains/definitions/creditCoin3Devnet.d.ts +6 -9
  156. package/_types/chains/definitions/creditCoin3Devnet.d.ts.map +1 -1
  157. package/_types/chains/definitions/creditCoin3Mainnet.d.ts +6 -9
  158. package/_types/chains/definitions/creditCoin3Mainnet.d.ts.map +1 -1
  159. package/_types/chains/definitions/creditCoin3Testnet.d.ts +6 -9
  160. package/_types/chains/definitions/creditCoin3Testnet.d.ts.map +1 -1
  161. package/_types/chains/definitions/kortana.d.ts +51 -0
  162. package/_types/chains/definitions/kortana.d.ts.map +1 -0
  163. package/_types/chains/index.d.ts +3 -0
  164. package/_types/chains/index.d.ts.map +1 -1
  165. package/_types/clients/createClientResolver.d.ts +76 -0
  166. package/_types/clients/createClientResolver.d.ts.map +1 -0
  167. package/_types/errors/version.d.ts +1 -1
  168. package/_types/index.d.ts +2 -0
  169. package/_types/index.d.ts.map +1 -1
  170. package/_types/op-stack/actions/getGame.d.ts.map +1 -1
  171. package/_types/tempo/Capabilities.d.ts +7 -28
  172. package/_types/tempo/Capabilities.d.ts.map +1 -1
  173. package/_types/tempo/Client.d.ts +6 -15
  174. package/_types/tempo/Client.d.ts.map +1 -1
  175. package/_types/tempo/ExecutionError.d.ts +79 -0
  176. package/_types/tempo/ExecutionError.d.ts.map +1 -0
  177. package/_types/tempo/Relay.d.ts +302 -0
  178. package/_types/tempo/Relay.d.ts.map +1 -0
  179. package/_types/tempo/Transaction.d.ts +2 -1
  180. package/_types/tempo/Transaction.d.ts.map +1 -1
  181. package/_types/tempo/Transport.d.ts +15 -29
  182. package/_types/tempo/Transport.d.ts.map +1 -1
  183. package/_types/tempo/chainConfig.d.ts.map +1 -1
  184. package/_types/tempo/index.d.ts +8 -3
  185. package/_types/tempo/index.d.ts.map +1 -1
  186. package/_types/tempo/internal/relay/cache.d.ts +9 -0
  187. package/_types/tempo/internal/relay/cache.d.ts.map +1 -0
  188. package/_types/tempo/internal/relay/deadline.d.ts +4 -0
  189. package/_types/tempo/internal/relay/deadline.d.ts.map +1 -0
  190. package/_types/tempo/internal/relay/error.d.ts +47 -0
  191. package/_types/tempo/internal/relay/error.d.ts.map +1 -0
  192. package/_types/tempo/internal/relay/feePayer.d.ts +70 -0
  193. package/_types/tempo/internal/relay/feePayer.d.ts.map +1 -0
  194. package/_types/tempo/internal/relay/feeToken.d.ts +38 -0
  195. package/_types/tempo/internal/relay/feeToken.d.ts.map +1 -0
  196. package/_types/tempo/internal/relay/multisig.d.ts +4 -0
  197. package/_types/tempo/internal/relay/multisig.d.ts.map +1 -0
  198. package/_types/tempo/internal/relay/plugin.d.ts +5 -0
  199. package/_types/tempo/internal/relay/plugin.d.ts.map +1 -0
  200. package/_types/tempo/internal/relay/preflight.d.ts +17 -0
  201. package/_types/tempo/internal/relay/preflight.d.ts.map +1 -0
  202. package/_types/tempo/internal/relay/request.d.ts +16 -0
  203. package/_types/tempo/internal/relay/request.d.ts.map +1 -0
  204. package/_types/tempo/internal/relay/simulate.d.ts +59 -0
  205. package/_types/tempo/internal/relay/simulate.d.ts.map +1 -0
  206. package/_types/tempo/internal/relay/utils.d.ts +294 -0
  207. package/_types/tempo/internal/relay/utils.d.ts.map +1 -0
  208. package/_types/tempo/internal/relay/virtualAddress.d.ts +9 -0
  209. package/_types/tempo/internal/relay/virtualAddress.d.ts.map +1 -0
  210. package/_types/tempo/internal/relay.d.ts +4 -0
  211. package/_types/tempo/internal/relay.d.ts.map +1 -0
  212. package/_types/tempo/multisig/Config.d.ts +0 -13
  213. package/_types/tempo/multisig/Config.d.ts.map +1 -1
  214. package/_types/tempo/multisig/Operation.d.ts +0 -5
  215. package/_types/tempo/multisig/Operation.d.ts.map +1 -1
  216. package/_types/utils/siwe/parseSiweMessage.d.ts.map +1 -1
  217. package/actions/public/waitForTransactionReceipt.ts +16 -2
  218. package/chains/definitions/blockdag.ts +20 -0
  219. package/chains/definitions/candyChain.ts +26 -0
  220. package/chains/definitions/creditCoin3Devnet.ts +6 -0
  221. package/chains/definitions/creditCoin3Mainnet.ts +6 -0
  222. package/chains/definitions/creditCoin3Testnet.ts +6 -0
  223. package/chains/definitions/kortana.ts +20 -0
  224. package/chains/index.ts +3 -0
  225. package/clients/createClientResolver.ts +191 -0
  226. package/errors/version.ts +1 -1
  227. package/index.ts +6 -0
  228. package/op-stack/actions/getGame.ts +3 -1
  229. package/op-stack/actions/getGames.ts +1 -1
  230. package/op-stack/actions/getTimeToNextGame.ts +2 -2
  231. package/op-stack/actions/getTimeToNextL2Output.ts +2 -2
  232. package/package.json +1 -1
  233. package/tempo/Capabilities.ts +7 -29
  234. package/tempo/Client.ts +8 -38
  235. package/tempo/ExecutionError.ts +418 -0
  236. package/tempo/Relay.ts +428 -0
  237. package/tempo/Transaction.ts +2 -1
  238. package/tempo/Transport.ts +69 -60
  239. package/tempo/chainConfig.ts +4 -0
  240. package/tempo/index.ts +7 -3
  241. package/tempo/internal/relay/cache.ts +82 -0
  242. package/tempo/internal/relay/deadline.ts +45 -0
  243. package/tempo/internal/relay/error.ts +128 -0
  244. package/tempo/internal/relay/feePayer.ts +692 -0
  245. package/tempo/internal/relay/feeToken.ts +190 -0
  246. package/tempo/{Multisig.ts → internal/relay/multisig.ts} +162 -193
  247. package/tempo/internal/relay/plugin.ts +13 -0
  248. package/tempo/internal/relay/preflight.ts +81 -0
  249. package/tempo/internal/relay/request.ts +391 -0
  250. package/tempo/internal/relay/simulate.ts +367 -0
  251. package/tempo/internal/relay/utils.ts +202 -0
  252. package/tempo/internal/relay/virtualAddress.ts +95 -0
  253. package/tempo/internal/relay.ts +158 -0
  254. package/tempo/multisig/Config.ts +3 -2
  255. package/tempo/multisig/Operation.ts +1 -1
  256. package/utils/siwe/parseSiweMessage.ts +21 -13
  257. package/_cjs/tempo/Multisig.js.map +0 -1
  258. package/_esm/tempo/Multisig.js.map +0 -1
  259. package/_types/tempo/Multisig.d.ts +0 -37
  260. package/_types/tempo/Multisig.d.ts.map +0 -1
package/tempo/Relay.ts ADDED
@@ -0,0 +1,428 @@
1
+ import type { Address } from 'abitype'
2
+ import * as RpcResponse from 'ox/RpcResponse'
3
+ import type { LocalAccount } from '../accounts/types.js'
4
+ import type { Client as Client_ } from '../clients/createClient.js'
5
+ import { ChainNotConfiguredError } from '../clients/createClientResolver.js'
6
+ import type { EIP1193RequestOptions } from '../types/eip1193.js'
7
+ import * as Sponsorship from './internal/relay/feePayer.js'
8
+ import * as FeeToken from './internal/relay/feeToken.js'
9
+ import * as Multisig from './internal/relay/multisig.js'
10
+ import * as Request_ from './internal/relay/request.js'
11
+ import * as Simulate from './internal/relay/simulate.js'
12
+ import * as internal from './internal/relay.js'
13
+ import type * as Store from './Store.js'
14
+
15
+ /**
16
+ * Creates a relay with RPC and Fetch handlers backed by a client or chain resolver.
17
+ *
18
+ * Pass a chain-configured `client` for a single chain, or `getClient` for multiple
19
+ * chains. Plugins may resolve the chain before forwarding to the selected client.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { createClient, http } from 'viem'
24
+ * import { tempo } from 'viem/chains'
25
+ * import { Relay } from 'viem/tempo'
26
+ *
27
+ * const relay = Relay.create({
28
+ * client: createClient({ chain: tempo, transport: http() }),
29
+ * })
30
+ * export default { fetch: relay.fetch }
31
+ * ```
32
+ *
33
+ * @param options - Client selection and relay plugins.
34
+ * @returns RPC and Fetch handlers sharing the same plugins.
35
+ */
36
+ export function create<const chainId extends number>(
37
+ options: handleRequest.Options & {
38
+ client: Client & { chain: { id: chainId } }
39
+ getClient?: never
40
+ },
41
+ ): create.ReturnType<chainId>
42
+ export function create<const chainId extends number = number>(
43
+ options: handleRequest.Options & {
44
+ client?: never
45
+ getClient: (options: { chainId: chainId }) => Client
46
+ },
47
+ ): create.ReturnType<chainId>
48
+ export function create<getClient extends (options: never) => Client>(
49
+ options: handleRequest.Options & { client?: never; getClient: getClient },
50
+ ): create.ReturnType<
51
+ Parameters<getClient>[0] extends { chainId: infer chainId extends number }
52
+ ? chainId
53
+ : number
54
+ >
55
+ export function create(
56
+ options: handleRequest.Options & {
57
+ client?: Client | undefined
58
+ getClient?: ((options: never) => Client) | undefined
59
+ },
60
+ ): create.ReturnType {
61
+ if (Boolean(options.client) === Boolean(options.getClient))
62
+ throw new RpcResponse.InvalidParamsError({
63
+ message: 'Expected exactly one of client or getClient.',
64
+ })
65
+ const clientChainId = options.client?.chain?.id
66
+ if (
67
+ options.client &&
68
+ (!Number.isSafeInteger(clientChainId) ||
69
+ !clientChainId ||
70
+ clientChainId <= 0)
71
+ )
72
+ throw new RpcResponse.InvalidParamsError({
73
+ message: 'Expected a client with a configured chain.',
74
+ })
75
+
76
+ const getClient = (chainId: number) => {
77
+ try {
78
+ const client = options.client ?? options.getClient!({ chainId } as never)
79
+ if (client.chain.id !== chainId)
80
+ throw new RpcResponse.InvalidParamsError({
81
+ message: 'Conflicting chain ids.',
82
+ })
83
+ return client
84
+ } catch (error) {
85
+ if (error instanceof ChainNotConfiguredError)
86
+ throw new RpcResponse.InvalidParamsError({
87
+ message: error.shortMessage,
88
+ })
89
+ throw error
90
+ }
91
+ }
92
+ const handle = Request_.compose(
93
+ async (request, requestOptions) => {
94
+ const { chainId, response: _, ...rest } = requestOptions ?? {}
95
+ if (chainId === undefined)
96
+ throw new RpcResponse.InvalidParamsError({
97
+ message: 'A chain ID is required to resolve the downstream client.',
98
+ })
99
+ return getClient(chainId).request(request as never, rest)
100
+ },
101
+ options,
102
+ getClient,
103
+ )
104
+
105
+ const request: handleRequest.Handler = (request, requestOptions) => {
106
+ const chainId = requestOptions?.chainId ?? clientChainId
107
+ if (
108
+ chainId !== undefined &&
109
+ (!Number.isSafeInteger(chainId) || chainId <= 0)
110
+ )
111
+ return Promise.reject(
112
+ new RpcResponse.InvalidParamsError({
113
+ message: 'Expected a valid chain ID.',
114
+ }),
115
+ )
116
+ if (clientChainId !== undefined && chainId !== clientChainId)
117
+ return Promise.reject(
118
+ new RpcResponse.InvalidParamsError({
119
+ message: 'Conflicting chain ids.',
120
+ }),
121
+ )
122
+ return handle(request, { ...requestOptions, chainId })
123
+ }
124
+ return {
125
+ request,
126
+ fetch: (request_, options: create.RequestOptions = {}) =>
127
+ internal.fetch(request_, request, options),
128
+ }
129
+ }
130
+
131
+ export declare namespace create {
132
+ /** Client selection and middleware for a relay. */
133
+ export type Options<chainId extends number = number> = handleRequest.Options &
134
+ (
135
+ | {
136
+ /** Chain-configured client used for every forwarded request. */
137
+ client: Client & { chain: { id: chainId } }
138
+ getClient?: never
139
+ }
140
+ | {
141
+ client?: never
142
+ /** Resolves the client after plugins have selected the request's chain. */
143
+ getClient: (options: {
144
+ chainId: chainId
145
+ }) => Client & { chain: { id: number } }
146
+ }
147
+ )
148
+
149
+ /** Optional chain selection and RPC request options. */
150
+ export type RequestOptions<chainId extends number = number> = Omit<
151
+ handleRequest.RequestOptions,
152
+ 'chainId'
153
+ > & { chainId?: chainId | undefined }
154
+
155
+ /** Handlers sharing one composed relay pipeline. */
156
+ export type ReturnType<chainId extends number = number> = {
157
+ /** Handles a POST JSON-RPC request, returning JSON or an empty 204 for notifications. */
158
+ fetch: {
159
+ (request: Request): Promise<Response>
160
+ (
161
+ request: Request,
162
+ options?: RequestOptions<chainId> | undefined,
163
+ ): Promise<Response>
164
+ }
165
+ /** Handles a parsed RPC call and returns its result. */
166
+ request: (
167
+ request: handleRequest.Request,
168
+ options?: RequestOptions<chainId> | undefined,
169
+ ) => Promise<unknown>
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Creates an RPC request handler by composing relay plugins around a downstream handler.
175
+ *
176
+ * Requests enter plugins in array order, and responses return in reverse order.
177
+ * Post-fill hooks run concurrently after middleware finishes. Middleware sees
178
+ * the downstream result before post-fill enrichment and signing.
179
+ * Without plugins, the downstream handler is returned unchanged. Plugins decide
180
+ * whether to forward, transform, or handle a request. Errors propagate unchanged
181
+ * unless a plugin handles them.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * import { http } from 'viem'
186
+ * import { Relay } from 'viem/tempo'
187
+ *
188
+ * const rpc = http('https://rpc.tempo.xyz')({})
189
+ * const handle = Relay.handleRequest(rpc.request, {
190
+ * plugins: [
191
+ * {
192
+ * async handleRequest(context, next) {
193
+ * context.options.retryCount = 0
194
+ * await next()
195
+ * },
196
+ * },
197
+ * ],
198
+ * })
199
+ * const chainId = await handle({ method: 'eth_chainId' })
200
+ * // @log: '0x1079'
201
+ * ```
202
+ *
203
+ * @param next - Downstream RPC request handler, typically forwarding to the Tempo (Execution) RPC.
204
+ * @param options - Relay options.
205
+ * @returns The composed RPC request handler.
206
+ */
207
+ export function handleRequest(
208
+ next: handleRequest.Handler,
209
+ options: handleRequest.Options = {},
210
+ ): handleRequest.Handler {
211
+ return Request_.compose(next, options)
212
+ }
213
+
214
+ export declare namespace handleRequest {
215
+ /** RPC request handler shared by relay plugins and the downstream execution RPC. */
216
+ export type Handler = (
217
+ request: Request,
218
+ options?: RequestOptions | undefined,
219
+ ) => Promise<unknown>
220
+
221
+ /** Options for {@link handleRequest}. */
222
+ export type Options = {
223
+ /** Plugins in request execution order. Defaults to an empty list. */
224
+ plugins?: readonly Plugin[] | undefined
225
+ /** Fee-token candidates shared by all plugins, memoized per request and chain. */
226
+ resolveTokens?:
227
+ | ((chainId: number) => readonly Address[] | Promise<readonly Address[]>)
228
+ | undefined
229
+ /** Deadline in milliseconds for a plugin-handled fill, including callbacks. Defaults to 10,000. */
230
+ timeout?: number | undefined
231
+ }
232
+
233
+ /** RPC request passed to a handler. */
234
+ export type Request = {
235
+ /** RPC method name. */
236
+ method: string
237
+ /** RPC method parameters. */
238
+ params?: readonly unknown[] | undefined
239
+ }
240
+
241
+ /** Options for one handled request. */
242
+ export type RequestOptions = EIP1193RequestOptions & {
243
+ /** Chain selected by the caller or resolved by a plugin. */
244
+ chainId?: number | undefined
245
+ /** Response metadata collected by the Fetch adapter. */
246
+ response?:
247
+ | { sponsorship_details?: Sponsorship.SponsorshipDetails | undefined }
248
+ | undefined
249
+ }
250
+ }
251
+
252
+ /** Hooks extending relay request processing and filled transaction responses. */
253
+ export type Plugin = {
254
+ /** Processes an RPC request. Await next(), then read or replace context.result. */
255
+ handleRequest?:
256
+ | ((context: Plugin.Context, next: () => Promise<void>) => Promise<unknown>)
257
+ | undefined
258
+ /** Runs concurrently after the final fill. Returns capability fields to merge. */
259
+ afterFill?:
260
+ | ((
261
+ filled: Plugin.FillResult,
262
+ context: Plugin.Context,
263
+ ) => Promise<Plugin.Enrichment | undefined>)
264
+ | undefined
265
+ /** Signs the final fill concurrently with enrichment. Only one signer may be registered. */
266
+ signTransaction?:
267
+ | ((
268
+ filled: Plugin.FillResult,
269
+ context: Plugin.Context,
270
+ ) => Promise<Plugin.Signature | undefined>)
271
+ | undefined
272
+ }
273
+
274
+ export declare namespace Plugin {
275
+ /** State and services isolated to one RPC invocation. */
276
+ export type Context = {
277
+ /** Current RPC request. Changes are passed to next(). */
278
+ request: handleRequest.Request
279
+ /** Downstream result, populated by next(). */
280
+ result: unknown
281
+ /** Transport options and selected chain. */
282
+ options: handleRequest.RequestOptions
283
+ /** Downstream client for the selected chain. */
284
+ readonly client: Client_
285
+ /** Gets a downstream client for the selected or specified chain. */
286
+ getClient: (chainId?: number) => Client_
287
+ /** Gets the shared token candidates for the selected or specified chain. */
288
+ resolveTokens: (chainId?: number) => Promise<readonly Address[]>
289
+ /** Scopes a configured store to this invocation. */
290
+ getStore: (store: Store.Store | undefined) => Store.Store | undefined
291
+ }
292
+ /** Immutable RPC fill supplied to post-fill hooks. */
293
+ export type FillResult = {
294
+ readonly tx: Readonly<Record<string, unknown>>
295
+ readonly capabilities?: Readonly<Record<string, unknown>> | undefined
296
+ readonly sponsor?: unknown
297
+ }
298
+ /** Additional response capabilities. Duplicate keys from hooks are rejected. */
299
+ export type Enrichment = {
300
+ capabilities?: Record<string, unknown> | undefined
301
+ }
302
+ /** Fee-payer signature in RPC format. */
303
+ export type Signature = {
304
+ r: `0x${string}`
305
+ s: `0x${string}`
306
+ yParity: `0x${string}`
307
+ }
308
+ }
309
+
310
+ declare const multisigBrand: unique symbol
311
+
312
+ /**
313
+ * Coordinates native multisig approvals using shared atomic storage.
314
+ *
315
+ * Memory storage is process-local. Independent clients and multiple server
316
+ * instances must use the same persistent store to share pending approvals.
317
+ *
318
+ * @example
319
+ * ```ts
320
+ * import { http } from 'viem'
321
+ * import { Relay, Store, withRelay } from 'viem/tempo'
322
+ *
323
+ * const transport = withRelay(http(), {
324
+ * plugins: [Relay.multisig({ store: Store.memory() })],
325
+ * })
326
+ * ```
327
+ *
328
+ * @param options - Shared atomic storage.
329
+ * @returns A plugin that coordinates multisig requests and forwards other calls.
330
+ */
331
+ export function multisig(options: multisig.Options): multisig.ReturnType {
332
+ return Multisig.create(options)
333
+ }
334
+
335
+ export declare namespace multisig {
336
+ /** Multisig coordination options. */
337
+ export type Options = {
338
+ /** Store shared by multisig coordinators, with atomic compare-and-set support. */
339
+ store: Store.Atomic
340
+ }
341
+ /** Middleware advertising native multisig coordination. */
342
+ export type ReturnType = Plugin & { readonly [multisigBrand]: true }
343
+ }
344
+
345
+ /**
346
+ * Sponsors transactions with a local account or an external fee-payer relay.
347
+ *
348
+ * Place multisig before this plugin and fee-token selection after it.
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * import { privateKeyToAccount } from 'viem/accounts'
353
+ * import { Relay } from 'viem/tempo'
354
+ * const plugin = Relay.feePayer({ account: privateKeyToAccount('0x...') })
355
+ * ```
356
+ * @param options - Sponsor account, policy, and display metadata.
357
+ * @returns A fee-payer relay plugin.
358
+ */
359
+ export function feePayer(options: feePayer.Options = {}): Plugin {
360
+ return Sponsorship.create(options)
361
+ }
362
+
363
+ export declare namespace feePayer {
364
+ /** Fee sponsorship configuration. */
365
+ export type Options = {
366
+ /** Local sponsor. Omit when requests use an external fee-payer URL. */
367
+ account?: LocalAccount | undefined
368
+ /** Trusted external fee-payer URLs. Matches the normalized full URL, including path and query. Defaults to none. */
369
+ allowedFeePayers?: readonly string[] | undefined
370
+ /** Sponsor's preferred fee token. Overrides the request token on sponsored fills. */
371
+ feeToken?: Address | undefined
372
+ /** Allow HTTP and private external relay hosts in trusted development environments. @default false */
373
+ internal_allowUnsafeUrls?: boolean | undefined
374
+ /** Display name returned in sponsor capabilities. */
375
+ name?: string | undefined
376
+ /** Called after signing and before returning or broadcasting. A thrown error aborts sponsorship. */
377
+ onSponsored?: Sponsorship.sign.Options['onSponsored'] | undefined
378
+ /** Sponsor display URL. */
379
+ url?: string | undefined
380
+ /** Only `true` authorizes sponsorship. Rejected fills fall back to sender-paid transactions. */
381
+ validate?: Sponsorship.Validate | undefined
382
+ }
383
+ /** Result of a sponsorship policy check. */
384
+ export type Validation = Sponsorship.Validation
385
+ /** Facts passed to the sponsorship callback. */
386
+ export type SponsoredEvent = Sponsorship.SponsoredEvent
387
+ }
388
+
389
+ /**
390
+ * Resolves fee tokens from user preferences and token balances.
391
+ *
392
+ * @example
393
+ * ```ts
394
+ * import { Relay } from 'viem/tempo'
395
+ * const plugin = Relay.feeToken()
396
+ * ```
397
+ * @returns A fee-token relay plugin.
398
+ */
399
+ export function feeToken(): Plugin {
400
+ return FeeToken.create()
401
+ }
402
+
403
+ /**
404
+ * Adds balance changes, estimated fees, and execution errors to fill capabilities.
405
+ *
406
+ * Runs after transaction middleware to simulate the final filled result.
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * import { Relay } from 'viem/tempo'
411
+ * const plugin = Relay.simulate()
412
+ * ```
413
+ * @param options - Optional metadata store.
414
+ * @returns A simulation relay plugin.
415
+ */
416
+ export function simulate(options: simulate.Options = {}): Plugin {
417
+ return Simulate.create(options)
418
+ }
419
+
420
+ export declare namespace simulate {
421
+ /** Simulation configuration. */
422
+ export type Options = {
423
+ /** Store for cached metadata. Omit to read metadata for each request. */
424
+ store?: Store.Store | undefined
425
+ }
426
+ }
427
+
428
+ type Client = Pick<Client_, 'request'> & { chain: { id: number } }
@@ -130,7 +130,8 @@ export type TransactionRequestTempo<
130
130
  accessList?: AccessList | undefined
131
131
  calls?: readonly TxTempo.Call<quantity, TempoAddress.Address>[] | undefined
132
132
  capabilities?: ExtractCapabilities<'fillTransaction', 'Request'> | undefined
133
- feePayer?: Account | true | undefined
133
+ /** Fee-payer account, external relay URL, or sponsorship preference. */
134
+ feePayer?: Account | boolean | string | undefined
134
135
  feeToken?: TempoAddress.Address | bigint | undefined
135
136
  hash?: Hex.Hex | undefined
136
137
  keyAuthorization?: KeyAuthorization.Signed<quantity, index> | undefined
@@ -23,7 +23,9 @@ import {
23
23
  } from '../errors/rpc.js'
24
24
  import type { Chain } from '../types/chain.js'
25
25
  import type { ChainConfig } from './chainConfig.js'
26
- import * as Multisig from './Multisig.js'
26
+ import * as Plugin_ from './internal/relay/plugin.js'
27
+ import * as Request_ from './internal/relay/request.js'
28
+ import type * as Relay_ from './Relay.js'
27
29
  import type { Store } from './Store.js'
28
30
  import * as Store_ from './Store.js'
29
31
  import * as Transaction from './Transaction.js'
@@ -86,63 +88,6 @@ type RelayProxyParameters = {
86
88
  export type FeePayer = Transport<typeof withFeePayer.type>
87
89
  export type Relay = Transport<typeof withRelay.type, { multisig: true }>
88
90
 
89
- /**
90
- * Wraps a transport with native multisig request handling.
91
- *
92
- * @example
93
- * ```ts
94
- * import { http, Store, withMultisig } from 'viem/tempo'
95
- *
96
- * const transport = withMultisig(http(), {
97
- * store: Store.memory(),
98
- * })
99
- * ```
100
- *
101
- * @param transport - Transport to wrap.
102
- * @param parameters - Multisig request handler parameters.
103
- * @returns The wrapped transport.
104
- * @experimental
105
- */
106
- export function withMultisig<transport extends Transport>(
107
- transport: transport,
108
- parameters: withMultisig.Parameters,
109
- ): withMultisig.ReturnValue<transport> {
110
- return ((options: Parameters<Transport>[0]) => {
111
- const value = transport(options)
112
- return {
113
- ...value,
114
- request: Multisig.handleRequest(
115
- (request, requestOptions) =>
116
- value.request(request as never, requestOptions),
117
- parameters,
118
- ) as typeof value.request,
119
- value: { ...value.value, multisig: true },
120
- }
121
- }) as withMultisig.ReturnValue<transport>
122
- }
123
-
124
- export declare namespace withMultisig {
125
- /** Multisig transport parameters. */
126
- export type Parameters = Multisig.handleRequest.Parameters
127
-
128
- /** Multisig transport return type. */
129
- export type ReturnValue<transport extends Transport = Transport> =
130
- transport extends Transport<
131
- infer type,
132
- infer rpcAttributes,
133
- infer eip1193RequestFn
134
- >
135
- ? Transport<
136
- type,
137
- rpcAttributes & {
138
- /** Whether the transport coordinates native multisig approvals. */
139
- multisig: true
140
- },
141
- eip1193RequestFn
142
- >
143
- : never
144
- }
145
-
146
91
  /**
147
92
  * Creates a relay transport that routes requests between
148
93
  * the default transport or the relay transport.
@@ -156,16 +101,57 @@ export declare namespace withMultisig {
156
101
  * - `'sign-only'`: Relay co-signs the transaction and returns it to the client transport, which then broadcasts it via the default transport
157
102
  * - `'sign-and-broadcast'`: Relay co-signs and broadcasts the transaction directly
158
103
  *
104
+ * Local plugin options wrap the default transport directly, preserving its attributes.
105
+ * Local mode enables fee sponsorship only when a `Relay.feePayer` plugin is configured.
106
+ *
159
107
  * @param defaultTransport - The default transport to use.
160
- * @param relayTransport - The relay transport to use.
108
+ * @param relayTransport - The remote relay transport or local plugin options.
161
109
  * @param parameters - Configuration parameters.
162
110
  * @returns A relay transport.
163
111
  */
112
+ export function withRelay<
113
+ transport extends Transport,
114
+ const plugins extends readonly Relay_.Plugin[] = readonly [],
115
+ >(
116
+ defaultTransport: transport,
117
+ options: withRelay.LocalOptions<plugins>,
118
+ ): withRelay.LocalReturnValue<transport, plugins>
164
119
  export function withRelay(
165
120
  defaultTransport: Transport,
166
121
  relayTransport: Transport,
167
122
  parameters?: withRelay.Parameters,
168
- ): withRelay.ReturnValue {
123
+ ): withRelay.ReturnValue
124
+ export function withRelay(
125
+ defaultTransport: Transport,
126
+ relayTransport: Transport | withRelay.LocalOptions,
127
+ parameters?: withRelay.Parameters,
128
+ ): Transport {
129
+ if (typeof relayTransport !== 'function')
130
+ return (config) => {
131
+ const transport = defaultTransport(config)
132
+ const next: Relay_.handleRequest.Handler = (request, options) =>
133
+ transport.request(request as never, options)
134
+ const request = Request_.compose(
135
+ next,
136
+ relayTransport,
137
+ config.chain ? () => ({ chain: config.chain! }) : undefined,
138
+ )
139
+ return {
140
+ ...transport,
141
+ request: ((request_, options) =>
142
+ request(request_ as Relay_.handleRequest.Request, {
143
+ chainId: config.chain?.id,
144
+ ...options,
145
+ })) as typeof transport.request,
146
+ value: {
147
+ ...transport.value,
148
+ ...(relayTransport.plugins?.some(Plugin_.isMultisig)
149
+ ? { multisig: true }
150
+ : {}),
151
+ },
152
+ }
153
+ }
154
+
169
155
  const { policy = 'sign-only' } = parameters ?? {}
170
156
 
171
157
  return (config) => {
@@ -282,6 +268,29 @@ export declare namespace withRelay {
282
268
 
283
269
  export type Parameters = RelayProxyParameters
284
270
 
271
+ /** Plugins applied directly to the default transport. */
272
+ export type LocalOptions<
273
+ plugins extends readonly Relay_.Plugin[] = readonly Relay_.Plugin[],
274
+ > = Pick<Relay_.handleRequest.Options, 'resolveTokens'> & {
275
+ /** Ordered relay plugins. Defaults to an empty list. */
276
+ plugins?: plugins | undefined
277
+ }
278
+
279
+ /** Wrapped transport preserving its attributes and RPC request schema. */
280
+ export type LocalReturnValue<
281
+ transport extends Transport,
282
+ plugins extends readonly Relay_.Plugin[] = readonly [],
283
+ > = transport extends Transport<infer type, infer attributes, infer request>
284
+ ? Transport<
285
+ type,
286
+ attributes &
287
+ (Extract<plugins[number], Relay_.multisig.ReturnType> extends never
288
+ ? {}
289
+ : { multisig: true }),
290
+ request
291
+ >
292
+ : never
293
+
285
294
  export type ReturnValue = Relay
286
295
  }
287
296
 
@@ -119,6 +119,10 @@ export const chainConfig = {
119
119
  throw new Error('Multisig operation hash does not match transaction.')
120
120
  return {
121
121
  ...storedTransaction,
122
+ // Serialized zero values must not trigger a new fill of an approved transaction.
123
+ gas: storedTransaction.gas ?? 0n,
124
+ maxFeePerGas: storedTransaction.maxFeePerGas ?? 0n,
125
+ maxPriorityFeePerGas: storedTransaction.maxPriorityFeePerGas ?? 0n,
122
126
  account: request.account,
123
127
  from: operation.account,
124
128
  multisigSimulation: getMultisigSimulation({
package/tempo/index.ts CHANGED
@@ -67,14 +67,19 @@ export {
67
67
  type Decorator as TempoActions,
68
68
  decorator as tempoActions,
69
69
  } from './Decorator.js'
70
+ /** Decodes Tempo precompile reverts into readable execution errors. */
71
+ export * as ExecutionError from './ExecutionError.js'
70
72
  export * as Expiry from './Expiry.js'
71
73
  export * from './errors.js'
72
74
  export * as Formatters from './Formatters.js'
73
75
  export * as Hardfork from './Hardfork.js'
74
76
  export * as KeyAuthorizationManager from './KeyAuthorizationManager.js'
75
- /** @experimental */
76
- export * as Multisig from './Multisig.js'
77
77
  export * as P256 from './P256.js'
78
+ /**
79
+ * Composable relay request handlers alongside the Tempo (Execution) RPC.
80
+ * @experimental
81
+ */
82
+ export * as Relay from './Relay.js'
78
83
  /** @experimental */
79
84
  export * as Scopes from './Scopes.js'
80
85
  /** @experimental */
@@ -117,7 +122,6 @@ export {
117
122
  http,
118
123
  walletNamespaceCompat,
119
124
  withFeePayer,
120
- withMultisig,
121
125
  withRelay,
122
126
  } from './Transport.js'
123
127
  export * as WebAuthnP256 from './WebAuthnP256.js'