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
@@ -0,0 +1,81 @@
1
+ import type { Address } from 'abitype'
2
+ import { VirtualAddress } from 'ox/tempo'
3
+ import { call } from '../../../actions/public/call.js'
4
+ import type { Client } from '../../../clients/createClient.js'
5
+ import { zeroAddress } from '../../../constants/address.js'
6
+ import { decodeAbiParameters } from '../../../utils/abi/decodeAbiParameters.js'
7
+ import { encodeAbiParameters } from '../../../utils/abi/encodeAbiParameters.js'
8
+ import { concat } from '../../../utils/data/concat.js'
9
+ import * as Addresses from '../../Addresses.js'
10
+
11
+ /** Reads fee preferences, balances, and virtual masters without dependent RPC requests. */
12
+ export async function read(
13
+ client: Client,
14
+ options: {
15
+ account?: Address | undefined
16
+ tokens?: readonly Address[] | undefined
17
+ targets?: readonly Address[] | undefined
18
+ },
19
+ ) {
20
+ const { account = zeroAddress, tokens = [], targets = [] } = options
21
+ const masterIds = [
22
+ ...new Set(targets.map((target) => VirtualAddress.parse(target).masterId)),
23
+ ]
24
+ const { data } = await call(client, {
25
+ batch: false,
26
+ data: concat([
27
+ bytecode,
28
+ encodeAbiParameters(
29
+ [
30
+ { type: 'address' },
31
+ { type: 'address' },
32
+ { type: 'address[]' },
33
+ { type: 'address' },
34
+ { type: 'bytes4[]' },
35
+ ],
36
+ [
37
+ account,
38
+ Addresses.feeManager,
39
+ tokens,
40
+ Addresses.addressRegistry,
41
+ masterIds,
42
+ ],
43
+ ),
44
+ ]),
45
+ })
46
+ const [preferredToken, preferredBalance, balances, resolved, masters] =
47
+ decodeAbiParameters(
48
+ [
49
+ { type: 'address' },
50
+ { type: 'uint256' },
51
+ { type: 'uint256[]' },
52
+ { type: 'bool' },
53
+ { type: 'address[]' },
54
+ ],
55
+ data ?? '0x',
56
+ )
57
+ return {
58
+ preferredToken,
59
+ preferredBalance,
60
+ balances: tokens.map((address, index) => ({
61
+ address,
62
+ balance: balances[index]!,
63
+ })),
64
+ virtualAddresses:
65
+ resolved && targets.length > 0
66
+ ? (Object.fromEntries(
67
+ targets.map((target) => {
68
+ const master =
69
+ masters[
70
+ masterIds.indexOf(VirtualAddress.parse(target).masterId)
71
+ ]!
72
+ return [target, master === zeroAddress ? null : master]
73
+ }),
74
+ ) as Record<Address, Address | null>)
75
+ : undefined,
76
+ }
77
+ }
78
+
79
+ // forge inspect contracts/src/deployless/RelayPreflight.sol:RelayPreflight bytecode --optimize --evm-version paris
80
+ const bytecode =
81
+ '0x608060405234801561001057600080fd5b5060405161067438038061067483398101604081905261002f916104a3565b6040516001600160a01b038616602482015260009061008090869060440160408051601f198184030181529190526020810180516001600160e01b03908116631da931f560e31b1790915261036b16565b9150600090506001600160a01b0382111561009c57600061009e565b815b9050600085516001600160401b038111156100bb576100bb6103b7565b6040519080825280602002602001820160405280156100e4578160200160208202803683370190505b506040516001600160a01b038a1660248201529091506000908190819060440160408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052905060005b89518110156101e0576101658a82815181106101515761015161059f565b60200260200101518361036b60201b60201c565b90508582815181106101795761017961059f565b602002602001018181525050856001600160a01b03168a82815181106101a1576101a161059f565b60200260200101516001600160a01b0316036101d857600192508481815181106101cd576101cd61059f565b602002602001015193505b600101610133565b50811580156101f757506001600160a01b03851615155b1561020a57610206858261036b565b9350505b600087516001600160401b03811115610225576102256103b7565b60405190808252806020026020018201604052801561024e578160200160208202803683370190505b509050600160005b8951811015610336576000806102d38d8d85815181106102785761027861059f565b60200260200101516040516024016102a091906001600160e01b031991909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03908116636c2558b360e11b1790915261036b16565b915091508115806102ea57506001600160a01b0381115b156102f8576000935061032c565b8085848151811061030b5761030b61059f565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050600101610256565b50600087868884866040516020016103529594939291906105fa565b6040516020818303038152906040529050805160208201f35b60008060405160208185516020870188620186a0fa60203d1015169250821561039357805191505b509250929050565b80516001600160a01b03811681146103b257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156103f5576103f56103b7565b604052919050565b60006001600160401b03821115610416576104166103b7565b5060051b60200190565b600082601f83011261043157600080fd5b815161044461043f826103fd565b6103cd565b8082825260208201915060208360051b86010192508583111561046657600080fd5b602085015b838110156104995780516001600160e01b03198116811461048b57600080fd5b83526020928301920161046b565b5095945050505050565b600080600080600060a086880312156104bb57600080fd5b6104c48661039b565b94506104d26020870161039b565b60408701519094506001600160401b038111156104ee57600080fd5b8601601f810188136104ff57600080fd5b805161050d61043f826103fd565b8082825260208201915060208360051b85010192508a83111561052f57600080fd5b6020840193505b82841015610558576105478461039b565b825260209384019390910190610536565b955061056a925050506060870161039b565b60808701519092506001600160401b0381111561058657600080fd5b61059288828901610420565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b600081518084526020840193506020830160005b828110156105f05781516001600160a01b03168652602095860195909101906001016105c9565b5093949350505050565b6001600160a01b0386168152602080820186905260a060408301819052855190830181905260009186019060c0840190835b8181101561064a57835183526020938401939092019160010161062c565b50508515156060850152838103608085015261066681866105b5565b999850505050505050505056fe'
@@ -0,0 +1,391 @@
1
+ import type { Address } from 'abitype'
2
+ import { RpcResponse } from 'ox'
3
+ import type { Transaction as core_Transaction } from 'ox/tempo'
4
+ import { tempo } from '../../../chains/index.js'
5
+ import { type Client, createClient } from '../../../clients/createClient.js'
6
+ import { custom } from '../../../clients/transports/custom.js'
7
+ import type * as Relay from '../../Relay.js'
8
+ import * as Transaction from '../../Transaction.js'
9
+ import * as Store from './cache.js'
10
+ import * as Deadline from './deadline.js'
11
+ import { formatError, isExecutionError } from './error.js'
12
+ import { getDefaultTokens } from './feeToken.js'
13
+ import * as Utils from './utils.js'
14
+ import {
15
+ extractCalls,
16
+ getVirtualAddressTargets,
17
+ resolveVirtualAddresses,
18
+ } from './virtualAddress.js'
19
+
20
+ export type Result = {
21
+ tx: Record<string, unknown>
22
+ capabilities?: Record<string, unknown> | undefined
23
+ sponsor?: unknown
24
+ }
25
+
26
+ /** Compose middleware and execute post-fill hooks once for the selected result. */
27
+ export function compose(
28
+ downstream: Relay.handleRequest.Handler,
29
+ options: Relay.handleRequest.Options = {},
30
+ resolveClient?: ((chainId: number) => { chain: { id: number } }) | undefined,
31
+ ): Relay.handleRequest.Handler {
32
+ const options_ = options
33
+ const plugins = options.plugins ?? []
34
+ if (plugins.length === 0) return downstream
35
+ if (plugins.filter((plugin) => plugin.signTransaction).length > 1)
36
+ throw new Error('Only one relay transaction signer may be configured.')
37
+
38
+ const handle: Relay.handleRequest.Handler = async (
39
+ request,
40
+ requestOptions = {},
41
+ ) => {
42
+ const stores = new Map<Store.Store, Store.Store>()
43
+ const tokens = new Map<number, Promise<readonly Address[]>>()
44
+ const scoped = (store: Store.Store | undefined) => {
45
+ if (!store) return undefined
46
+ let result = stores.get(store)
47
+ if (!result) {
48
+ result = Store.scoped(store)!
49
+ stores.set(store, result)
50
+ }
51
+ return result
52
+ }
53
+
54
+ const execute = async (
55
+ start: number,
56
+ request: Relay.handleRequest.Request,
57
+ options: Relay.handleRequest.RequestOptions,
58
+ ) => {
59
+ const state = {
60
+ request,
61
+ options: { ...options },
62
+ result: undefined as unknown,
63
+ }
64
+ const contexts = new Map<number, Relay.Plugin.Context>()
65
+ const contextAt = (index: number): Relay.Plugin.Context => {
66
+ const existing = contexts.get(index)
67
+ if (existing) return existing
68
+ const clients = new Map<number, Client>()
69
+ const chainId = (id = state.options.chainId) => {
70
+ if (id === undefined || !Number.isSafeInteger(id) || id <= 0)
71
+ throw new RpcResponse.InvalidParamsError({
72
+ message:
73
+ 'A chain ID is required to resolve the downstream client.',
74
+ })
75
+ return id
76
+ }
77
+ const context: Relay.Plugin.Context = {
78
+ get request() {
79
+ return state.request
80
+ },
81
+ set request(value) {
82
+ state.request = value
83
+ },
84
+ get result() {
85
+ return state.result
86
+ },
87
+ set result(value) {
88
+ state.result = value
89
+ },
90
+ get options() {
91
+ return state.options
92
+ },
93
+ set options(value) {
94
+ state.options = value
95
+ },
96
+ get client() {
97
+ return context.getClient()
98
+ },
99
+ getClient(id_) {
100
+ const id = chainId(id_)
101
+ let client = clients.get(id)
102
+ if (client) return client
103
+ const upstream = resolveClient?.(id)
104
+ if (upstream?.chain && upstream.chain.id !== id)
105
+ throw new RpcResponse.InvalidParamsError({
106
+ message: 'Conflicting chain ids.',
107
+ })
108
+ client = createClient({
109
+ chain: { ...tempo, ...upstream?.chain, id },
110
+ batch: { multicall: { deployless: true } },
111
+ transport: (config) => {
112
+ const transport = custom(
113
+ {
114
+ request: async (request, options) => {
115
+ const child = await execute(index + 1, request, {
116
+ ...state.options,
117
+ ...options,
118
+ chainId: id,
119
+ })
120
+ return child.state.result
121
+ },
122
+ },
123
+ { retryCount: 0 },
124
+ )(config)
125
+ // Forward request options without adding a retry loop around downstream I/O.
126
+ return { ...transport, request: transport.config.request }
127
+ },
128
+ })
129
+ clients.set(id, client)
130
+ return client
131
+ },
132
+ async resolveTokens(id_) {
133
+ const id = chainId(id_)
134
+ let result = tokens.get(id)
135
+ if (!result) {
136
+ result = Promise.resolve().then(() =>
137
+ (options_.resolveTokens ?? getDefaultTokens)(id),
138
+ )
139
+ tokens.set(id, result)
140
+ }
141
+ return result
142
+ },
143
+ getStore: scoped,
144
+ }
145
+ contexts.set(index, context)
146
+ return context
147
+ }
148
+ const dispatch = async (index: number): Promise<void> => {
149
+ if (index === plugins.length) {
150
+ const parameters = state.request.params?.[0] as
151
+ | Record<string, unknown>
152
+ | undefined
153
+ // The node must estimate unsigned sponsorship independently of the sender's fee-token balance.
154
+ const request =
155
+ state.request.method === 'eth_fillTransaction' &&
156
+ parameters?.feePayer === true &&
157
+ !parameters.feePayerSignature
158
+ ? {
159
+ ...state.request,
160
+ params: [{ ...parameters, feeToken: undefined }],
161
+ }
162
+ : state.request
163
+ requestOptions.signal?.throwIfAborted()
164
+ state.result = await downstream(request, {
165
+ ...state.options,
166
+ ...(isFill ? { signal: requestOptions.signal } : {}),
167
+ })
168
+ return
169
+ }
170
+ const plugin = plugins[index]!
171
+ const context = contextAt(index)
172
+ if (!plugin.handleRequest) return dispatch(index + 1)
173
+ let called = false
174
+ const result = await plugin.handleRequest(context, async () => {
175
+ if (called)
176
+ throw new Error(
177
+ 'next() may only be called once per middleware invocation.',
178
+ )
179
+ called = true
180
+ await dispatch(index + 1)
181
+ })
182
+ if (result !== undefined) state.result = result
183
+ }
184
+ await dispatch(start)
185
+ return { state, contextAt }
186
+ }
187
+
188
+ const isFill = request.method === 'eth_fillTransaction'
189
+ const isRaw = [
190
+ 'eth_signRawTransaction',
191
+ 'eth_sendRawTransaction',
192
+ 'eth_sendRawTransactionSync',
193
+ ].includes(request.method)
194
+ const parameters = request.params?.[0] as Record<string, unknown>
195
+ let root: Awaited<ReturnType<typeof execute>> | undefined
196
+ try {
197
+ requestOptions.signal?.throwIfAborted()
198
+ if (
199
+ isFill &&
200
+ (!parameters ||
201
+ typeof parameters !== 'object' ||
202
+ Array.isArray(parameters))
203
+ )
204
+ throw new RpcResponse.InvalidParamsError({
205
+ message: 'Expected a transaction object.',
206
+ })
207
+ if (isFill) Utils.normalizeFillTransactionRequest(parameters)
208
+ const bodyChainId = (() => {
209
+ if (isRaw && Utils.isSerializedTempoTransaction(request.params?.[0])) {
210
+ try {
211
+ return Transaction.deserialize(request.params[0]).chainId
212
+ } catch {
213
+ throw new RpcResponse.InvalidParamsError({
214
+ message: 'Invalid serialized Tempo transaction.',
215
+ })
216
+ }
217
+ }
218
+ if (!isFill || parameters.chainId === undefined) return undefined
219
+ const id = Utils.resolveChainId(parameters.chainId)
220
+ if (id === undefined || !Number.isSafeInteger(id) || id <= 0)
221
+ throw new RpcResponse.InvalidParamsError({
222
+ message: 'Invalid transaction chain ID.',
223
+ })
224
+ return id
225
+ })()
226
+ if (
227
+ bodyChainId !== undefined &&
228
+ requestOptions.chainId !== undefined &&
229
+ bodyChainId !== requestOptions.chainId
230
+ )
231
+ throw new RpcResponse.InvalidParamsError({
232
+ message: 'Conflicting chain ids.',
233
+ })
234
+ root = await execute(0, request, {
235
+ ...requestOptions,
236
+ ...((requestOptions.chainId ?? bodyChainId) !== undefined
237
+ ? { chainId: requestOptions.chainId ?? bodyChainId }
238
+ : {}),
239
+ })
240
+ if (!isFill) return root.state.result
241
+ const filled = root.state.result as Result
242
+ if (filled.capabilities?.error) return filled
243
+ const transaction = Utils.normalizeTempoTransaction(
244
+ Utils.mergeCallsFromRequest(
245
+ filled.tx,
246
+ Utils.normalizeFillTransactionRequest(parameters),
247
+ ),
248
+ )
249
+ const final: Result = {
250
+ ...filled,
251
+ tx: Utils.formatTempoTransaction(
252
+ transaction as core_Transaction.Transaction,
253
+ ),
254
+ }
255
+ const snapshot = freeze(structuredClone(final))
256
+ const targets = getVirtualAddressTargets(extractCalls(transaction))
257
+ const resolved = final.capabilities?.virtualAddresses as
258
+ | Record<Address, Address | null>
259
+ | undefined
260
+ const [patches, signatures, virtualAddresses] = await Promise.all([
261
+ Promise.all(
262
+ plugins.map((plugin, index) =>
263
+ plugin.afterFill?.(snapshot, root!.contextAt(index)),
264
+ ),
265
+ ),
266
+ Promise.all(
267
+ plugins.map((plugin, index) =>
268
+ plugin.signTransaction?.(snapshot, root!.contextAt(index)),
269
+ ),
270
+ ),
271
+ targets.length > 0 &&
272
+ !targets.every((target) => resolved && target in resolved)
273
+ ? resolveVirtualAddresses(root.contextAt(-1).client, {
274
+ calls: extractCalls(transaction),
275
+ }).catch(() => {
276
+ requestOptions.signal?.throwIfAborted()
277
+ return undefined
278
+ })
279
+ : undefined,
280
+ ])
281
+ requestOptions.signal?.throwIfAborted()
282
+ const capabilities = { ...final.capabilities }
283
+ const keys = new Set<string>()
284
+ for (const patch of patches) {
285
+ for (const [key, value] of Object.entries(patch?.capabilities ?? {})) {
286
+ if (keys.has(key))
287
+ throw new Error(`Conflicting relay capability: ${key}.`)
288
+ keys.add(key)
289
+ capabilities[key] = value
290
+ }
291
+ }
292
+ const signature = signatures.find((signature) => signature !== undefined)
293
+ if (signature) {
294
+ delete final.tx.signature
295
+ final.tx.feePayerSignature = signature
296
+ }
297
+ const sponsor = capabilities.sponsor ?? final.sponsor
298
+ return {
299
+ ...final,
300
+ capabilities: {
301
+ sponsored: !!sponsor,
302
+ ...capabilities,
303
+ ...(virtualAddresses ? { virtualAddresses } : {}),
304
+ },
305
+ }
306
+ } catch (error) {
307
+ requestOptions.signal?.throwIfAborted()
308
+ if (
309
+ isFill &&
310
+ isExecutionError(error) &&
311
+ (parameters.capabilities as Record<string, unknown> | undefined)
312
+ ?.errors === true
313
+ ) {
314
+ // Resolve errors through a downstream-only client; never restart the plugin pipeline.
315
+ const id =
316
+ requestOptions.chainId ?? Utils.resolveChainId(parameters.chainId)
317
+ const client = createClient({
318
+ chain: { ...tempo, id: id ?? tempo.id },
319
+ transport: custom(
320
+ {
321
+ request: (request, options) =>
322
+ downstream(request, {
323
+ ...requestOptions,
324
+ ...options,
325
+ chainId: id,
326
+ signal: requestOptions.signal,
327
+ }),
328
+ },
329
+ { retryCount: 0 },
330
+ ),
331
+ })
332
+ return formatError(error, parameters, client)
333
+ }
334
+ if (!isFill && !isRaw) throw error
335
+ throw Utils.toRpcError(error)
336
+ }
337
+ }
338
+ if (
339
+ options.timeout !== undefined &&
340
+ (!Number.isSafeInteger(options.timeout) || options.timeout <= 0)
341
+ )
342
+ throw new RpcResponse.InvalidParamsError({
343
+ message: 'Expected a positive integer for timeout.',
344
+ })
345
+ if (options.timeout !== undefined && options.timeout > 2_147_483_647)
346
+ throw new RpcResponse.InvalidParamsError({
347
+ message: 'The fill timeout cannot exceed 2147483647 milliseconds.',
348
+ })
349
+ return (request, requestOptions = {}) =>
350
+ request.method === 'eth_fillTransaction'
351
+ ? Deadline.run(handle, request, requestOptions, options)
352
+ : handle(request, requestOptions)
353
+ }
354
+
355
+ /** Prevent hooks from mutating the transaction another hook signs. */
356
+ function freeze<value>(value: value): value {
357
+ if (value && typeof value === 'object') {
358
+ for (const child of Object.values(value)) freeze(child)
359
+ Object.freeze(value)
360
+ }
361
+ return value
362
+ }
363
+
364
+ /** Normalize a downstream fill without discarding capabilities added by other plugins. */
365
+ export async function fill(
366
+ client: Client,
367
+ transaction: Record<string, unknown>,
368
+ options: Relay.handleRequest.RequestOptions = {},
369
+ ): Promise<Result> {
370
+ const formatted = Utils.formatFillTransactionRequest(client, transaction)
371
+ const result = (await client.request(
372
+ {
373
+ method: 'eth_fillTransaction',
374
+ params: [formatted as never],
375
+ },
376
+ options,
377
+ )) as unknown as Result
378
+
379
+ const error = result.capabilities?.error as
380
+ | { message?: string; errorName?: string; data?: `0x${string}` }
381
+ | undefined
382
+ if (error) {
383
+ const cause = new Error(
384
+ error.message ?? error.errorName ?? 'UpstreamRevert',
385
+ )
386
+ Object.assign(cause, { name: 'UpstreamRevertError', data: error.data })
387
+ throw cause
388
+ }
389
+
390
+ return { ...result, tx: Utils.mergeCallsFromRequest(result.tx, transaction) }
391
+ }