viem 2.56.8 → 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.
- package/CHANGELOG.md +78 -0
- package/README.md +0 -1
- package/_cjs/actions/index.js +5 -3
- package/_cjs/actions/index.js.map +1 -1
- package/_cjs/actions/public/getStorageValues.js +17 -0
- package/_cjs/actions/public/getStorageValues.js.map +1 -0
- package/_cjs/actions/public/simulateBlocks.js +2 -0
- package/_cjs/actions/public/simulateBlocks.js.map +1 -1
- package/_cjs/actions/public/waitForTransactionReceipt.js +12 -1
- package/_cjs/actions/public/waitForTransactionReceipt.js.map +1 -1
- package/_cjs/chains/definitions/blockdag.js +23 -0
- package/_cjs/chains/definitions/blockdag.js.map +1 -0
- package/_cjs/chains/definitions/candyChain.js +29 -0
- package/_cjs/chains/definitions/candyChain.js.map +1 -0
- package/_cjs/chains/definitions/creditCoin3Devnet.js +6 -0
- package/_cjs/chains/definitions/creditCoin3Devnet.js.map +1 -1
- package/_cjs/chains/definitions/creditCoin3Mainnet.js +6 -0
- package/_cjs/chains/definitions/creditCoin3Mainnet.js.map +1 -1
- package/_cjs/chains/definitions/creditCoin3Testnet.js +6 -0
- package/_cjs/chains/definitions/creditCoin3Testnet.js.map +1 -1
- package/_cjs/chains/definitions/kortana.js +23 -0
- package/_cjs/chains/definitions/kortana.js.map +1 -0
- package/_cjs/chains/definitions/rabbitChainTestnet.js +24 -0
- package/_cjs/chains/definitions/rabbitChainTestnet.js.map +1 -0
- package/_cjs/chains/index.js +22 -14
- package/_cjs/chains/index.js.map +1 -1
- package/_cjs/clients/createClientResolver.js +45 -0
- package/_cjs/clients/createClientResolver.js.map +1 -0
- package/_cjs/clients/decorators/public.js +2 -0
- package/_cjs/clients/decorators/public.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/index.js +13 -9
- package/_cjs/index.js.map +1 -1
- package/_cjs/op-stack/actions/getGame.js +1 -1
- package/_cjs/op-stack/actions/getGame.js.map +1 -1
- package/_cjs/op-stack/actions/getGames.js +1 -1
- package/_cjs/op-stack/actions/getGames.js.map +1 -1
- package/_cjs/op-stack/actions/getTimeToNextGame.js +1 -1
- package/_cjs/op-stack/actions/getTimeToNextGame.js.map +1 -1
- package/_cjs/op-stack/actions/getTimeToNextL2Output.js +1 -1
- package/_cjs/op-stack/actions/getTimeToNextL2Output.js.map +1 -1
- package/_cjs/tempo/Abis.js +1211 -32
- package/_cjs/tempo/Abis.js.map +1 -1
- package/_cjs/tempo/Addresses.js +2 -1
- package/_cjs/tempo/Addresses.js.map +1 -1
- package/_cjs/tempo/Client.js +2 -10
- package/_cjs/tempo/Client.js.map +1 -1
- package/_cjs/tempo/Decorator.js +12 -0
- package/_cjs/tempo/Decorator.js.map +1 -1
- package/_cjs/tempo/ExecutionError.js +290 -0
- package/_cjs/tempo/ExecutionError.js.map +1 -0
- package/_cjs/tempo/Relay.js +88 -0
- package/_cjs/tempo/Relay.js.map +1 -0
- package/_cjs/tempo/Selectors.js +7 -4
- package/_cjs/tempo/Selectors.js.map +1 -1
- package/_cjs/tempo/Transaction.js.map +1 -1
- package/_cjs/tempo/Transport.js +21 -12
- package/_cjs/tempo/Transport.js.map +1 -1
- package/_cjs/tempo/actions/index.js +2 -1
- package/_cjs/tempo/actions/index.js.map +1 -1
- package/_cjs/tempo/actions/propAmm.js +349 -0
- package/_cjs/tempo/actions/propAmm.js.map +1 -0
- package/_cjs/tempo/chainConfig.js +3 -0
- package/_cjs/tempo/chainConfig.js.map +1 -1
- package/_cjs/tempo/index.js +3 -3
- package/_cjs/tempo/index.js.map +1 -1
- package/_cjs/tempo/internal/relay/cache.js +74 -0
- package/_cjs/tempo/internal/relay/cache.js.map +1 -0
- package/_cjs/tempo/internal/relay/deadline.js +35 -0
- package/_cjs/tempo/internal/relay/deadline.js.map +1 -0
- package/_cjs/tempo/internal/relay/error.js +102 -0
- package/_cjs/tempo/internal/relay/error.js.map +1 -0
- package/_cjs/tempo/internal/relay/feePayer.js +426 -0
- package/_cjs/tempo/internal/relay/feePayer.js.map +1 -0
- package/_cjs/tempo/internal/relay/feeToken.js +143 -0
- package/_cjs/tempo/internal/relay/feeToken.js.map +1 -0
- package/_cjs/tempo/{Multisig.js → internal/relay/multisig.js} +132 -122
- package/_cjs/tempo/internal/relay/multisig.js.map +1 -0
- package/_cjs/tempo/internal/relay/plugin.js +13 -0
- package/_cjs/tempo/internal/relay/plugin.js.map +1 -0
- package/_cjs/tempo/internal/relay/preflight.js +58 -0
- package/_cjs/tempo/internal/relay/preflight.js.map +1 -0
- package/_cjs/tempo/internal/relay/request.js +319 -0
- package/_cjs/tempo/internal/relay/request.js.map +1 -0
- package/_cjs/tempo/internal/relay/simulate.js +267 -0
- package/_cjs/tempo/internal/relay/simulate.js.map +1 -0
- package/_cjs/tempo/internal/relay/utils.js +174 -0
- package/_cjs/tempo/internal/relay/utils.js.map +1 -0
- package/_cjs/tempo/internal/relay/virtualAddress.js +78 -0
- package/_cjs/tempo/internal/relay/virtualAddress.js.map +1 -0
- package/_cjs/tempo/internal/relay.js +139 -0
- package/_cjs/tempo/internal/relay.js.map +1 -0
- package/_cjs/tempo/multisig/Config.js +0 -2
- package/_cjs/tempo/multisig/Config.js.map +1 -1
- package/_cjs/tempo/multisig/Operation.js +1 -2
- package/_cjs/tempo/multisig/Operation.js.map +1 -1
- package/_cjs/tokens/definitions/eurc.js +1 -0
- package/_cjs/tokens/definitions/eurc.js.map +1 -1
- package/_cjs/tokens/definitions/usdc.js +1 -0
- package/_cjs/tokens/definitions/usdc.js.map +1 -1
- package/_cjs/utils/siwe/parseSiweMessage.js +3 -3
- package/_cjs/utils/siwe/parseSiweMessage.js.map +1 -1
- package/_esm/actions/index.js +1 -0
- package/_esm/actions/index.js.map +1 -1
- package/_esm/actions/public/getStorageValues.js +39 -0
- package/_esm/actions/public/getStorageValues.js.map +1 -0
- package/_esm/actions/public/simulateBlocks.js +4 -0
- package/_esm/actions/public/simulateBlocks.js.map +1 -1
- package/_esm/actions/public/waitForTransactionReceipt.js +15 -1
- package/_esm/actions/public/waitForTransactionReceipt.js.map +1 -1
- package/_esm/chains/definitions/blockdag.js +20 -0
- package/_esm/chains/definitions/blockdag.js.map +1 -0
- package/_esm/chains/definitions/candyChain.js +26 -0
- package/_esm/chains/definitions/candyChain.js.map +1 -0
- package/_esm/chains/definitions/creditCoin3Devnet.js +6 -0
- package/_esm/chains/definitions/creditCoin3Devnet.js.map +1 -1
- package/_esm/chains/definitions/creditCoin3Mainnet.js +6 -0
- package/_esm/chains/definitions/creditCoin3Mainnet.js.map +1 -1
- package/_esm/chains/definitions/creditCoin3Testnet.js +6 -0
- package/_esm/chains/definitions/creditCoin3Testnet.js.map +1 -1
- package/_esm/chains/definitions/kortana.js +20 -0
- package/_esm/chains/definitions/kortana.js.map +1 -0
- package/_esm/chains/definitions/rabbitChainTestnet.js +21 -0
- package/_esm/chains/definitions/rabbitChainTestnet.js.map +1 -0
- package/_esm/chains/index.js +4 -0
- package/_esm/chains/index.js.map +1 -1
- package/_esm/clients/createClientResolver.js +64 -0
- package/_esm/clients/createClientResolver.js.map +1 -0
- package/_esm/clients/decorators/public.js +2 -0
- package/_esm/clients/decorators/public.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/index.js +2 -0
- package/_esm/index.js.map +1 -1
- package/_esm/op-stack/actions/getGame.js +1 -1
- package/_esm/op-stack/actions/getGame.js.map +1 -1
- package/_esm/op-stack/actions/getGames.js +1 -1
- package/_esm/op-stack/actions/getGames.js.map +1 -1
- package/_esm/op-stack/actions/getTimeToNextGame.js +2 -2
- package/_esm/op-stack/actions/getTimeToNextGame.js.map +1 -1
- package/_esm/op-stack/actions/getTimeToNextL2Output.js +2 -2
- package/_esm/op-stack/actions/getTimeToNextL2Output.js.map +1 -1
- package/_esm/tempo/Abis.js +1214 -34
- package/_esm/tempo/Abis.js.map +1 -1
- package/_esm/tempo/Addresses.js +2 -0
- package/_esm/tempo/Addresses.js.map +1 -1
- package/_esm/tempo/Client.js +8 -14
- package/_esm/tempo/Client.js.map +1 -1
- package/_esm/tempo/Decorator.js +12 -0
- package/_esm/tempo/Decorator.js.map +1 -1
- package/_esm/tempo/ExecutionError.js +306 -0
- package/_esm/tempo/ExecutionError.js.map +1 -0
- package/_esm/tempo/Relay.js +170 -0
- package/_esm/tempo/Relay.js.map +1 -0
- package/_esm/tempo/Selectors.js +6 -3
- package/_esm/tempo/Selectors.js.map +1 -1
- package/_esm/tempo/Transaction.js.map +1 -1
- package/_esm/tempo/Transport.js +21 -46
- package/_esm/tempo/Transport.js.map +1 -1
- package/_esm/tempo/actions/index.js +1 -0
- package/_esm/tempo/actions/index.js.map +1 -1
- package/_esm/tempo/actions/propAmm.js +539 -0
- package/_esm/tempo/actions/propAmm.js.map +1 -0
- package/_esm/tempo/chainConfig.js +4 -0
- package/_esm/tempo/chainConfig.js.map +1 -1
- package/_esm/tempo/index.js +8 -3
- package/_esm/tempo/index.js.map +1 -1
- package/_esm/tempo/internal/relay/cache.js +72 -0
- package/_esm/tempo/internal/relay/cache.js.map +1 -0
- package/_esm/tempo/internal/relay/deadline.js +34 -0
- package/_esm/tempo/internal/relay/deadline.js.map +1 -0
- package/_esm/tempo/internal/relay/error.js +101 -0
- package/_esm/tempo/internal/relay/error.js.map +1 -0
- package/_esm/tempo/internal/relay/feePayer.js +442 -0
- package/_esm/tempo/internal/relay/feePayer.js.map +1 -0
- package/_esm/tempo/internal/relay/feeToken.js +143 -0
- package/_esm/tempo/internal/relay/feeToken.js.map +1 -0
- package/_esm/tempo/{Multisig.js → internal/relay/multisig.js} +133 -129
- package/_esm/tempo/internal/relay/multisig.js.map +1 -0
- package/_esm/tempo/internal/relay/plugin.js +10 -0
- package/_esm/tempo/internal/relay/plugin.js.map +1 -0
- package/_esm/tempo/internal/relay/preflight.js +57 -0
- package/_esm/tempo/internal/relay/preflight.js.map +1 -0
- package/_esm/tempo/internal/relay/request.js +321 -0
- package/_esm/tempo/internal/relay/request.js.map +1 -0
- package/_esm/tempo/internal/relay/simulate.js +277 -0
- package/_esm/tempo/internal/relay/simulate.js.map +1 -0
- package/_esm/tempo/internal/relay/utils.js +174 -0
- package/_esm/tempo/internal/relay/utils.js.map +1 -0
- package/_esm/tempo/internal/relay/virtualAddress.js +73 -0
- package/_esm/tempo/internal/relay/virtualAddress.js.map +1 -0
- package/_esm/tempo/internal/relay.js +138 -0
- package/_esm/tempo/internal/relay.js.map +1 -0
- package/_esm/tempo/multisig/Config.js +2 -1
- package/_esm/tempo/multisig/Config.js.map +1 -1
- package/_esm/tempo/multisig/Operation.js +1 -1
- package/_esm/tempo/multisig/Operation.js.map +1 -1
- package/_esm/tokens/definitions/eurc.js +1 -0
- package/_esm/tokens/definitions/eurc.js.map +1 -1
- package/_esm/tokens/definitions/usdc.js +1 -0
- package/_esm/tokens/definitions/usdc.js.map +1 -1
- package/_esm/utils/siwe/parseSiweMessage.js +3 -3
- package/_esm/utils/siwe/parseSiweMessage.js.map +1 -1
- package/_types/actions/index.d.ts +1 -0
- package/_types/actions/index.d.ts.map +1 -1
- package/_types/actions/public/getStorageValues.d.ts +59 -0
- package/_types/actions/public/getStorageValues.d.ts.map +1 -0
- package/_types/actions/public/simulateBlocks.d.ts +8 -0
- package/_types/actions/public/simulateBlocks.d.ts.map +1 -1
- package/_types/actions/public/waitForTransactionReceipt.d.ts.map +1 -1
- package/_types/chains/definitions/blockdag.d.ts +51 -0
- package/_types/chains/definitions/blockdag.d.ts.map +1 -0
- package/_types/chains/definitions/candyChain.d.ts +48 -0
- package/_types/chains/definitions/candyChain.d.ts.map +1 -0
- package/_types/chains/definitions/creditCoin3Devnet.d.ts +6 -9
- package/_types/chains/definitions/creditCoin3Devnet.d.ts.map +1 -1
- package/_types/chains/definitions/creditCoin3Mainnet.d.ts +6 -9
- package/_types/chains/definitions/creditCoin3Mainnet.d.ts.map +1 -1
- package/_types/chains/definitions/creditCoin3Testnet.d.ts +6 -9
- package/_types/chains/definitions/creditCoin3Testnet.d.ts.map +1 -1
- package/_types/chains/definitions/kortana.d.ts +51 -0
- package/_types/chains/definitions/kortana.d.ts.map +1 -0
- package/_types/chains/definitions/rabbitChainTestnet.d.ts +51 -0
- package/_types/chains/definitions/rabbitChainTestnet.d.ts.map +1 -0
- package/_types/chains/index.d.ts +4 -0
- package/_types/chains/index.d.ts.map +1 -1
- package/_types/clients/createClientResolver.d.ts +76 -0
- package/_types/clients/createClientResolver.d.ts.map +1 -0
- package/_types/clients/decorators/public.d.ts +11 -0
- package/_types/clients/decorators/public.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/index.d.ts +3 -0
- package/_types/index.d.ts.map +1 -1
- package/_types/op-stack/actions/getGame.d.ts.map +1 -1
- package/_types/tempo/Abis.d.ts +14686 -9568
- package/_types/tempo/Abis.d.ts.map +1 -1
- package/_types/tempo/Addresses.d.ts +2 -0
- package/_types/tempo/Addresses.d.ts.map +1 -1
- package/_types/tempo/Capabilities.d.ts +7 -28
- package/_types/tempo/Capabilities.d.ts.map +1 -1
- package/_types/tempo/Client.d.ts +6 -15
- package/_types/tempo/Client.d.ts.map +1 -1
- package/_types/tempo/Decorator.d.ts +205 -1
- package/_types/tempo/Decorator.d.ts.map +1 -1
- package/_types/tempo/ExecutionError.d.ts +79 -0
- package/_types/tempo/ExecutionError.d.ts.map +1 -0
- package/_types/tempo/Relay.d.ts +302 -0
- package/_types/tempo/Relay.d.ts.map +1 -0
- package/_types/tempo/Selectors.d.ts +6 -3
- package/_types/tempo/Selectors.d.ts.map +1 -1
- package/_types/tempo/Transaction.d.ts +2 -1
- package/_types/tempo/Transaction.d.ts.map +1 -1
- package/_types/tempo/Transport.d.ts +15 -29
- package/_types/tempo/Transport.d.ts.map +1 -1
- package/_types/tempo/actions/earn.d.ts +621 -1
- package/_types/tempo/actions/earn.d.ts.map +1 -1
- package/_types/tempo/actions/index.d.ts +1 -0
- package/_types/tempo/actions/index.d.ts.map +1 -1
- package/_types/tempo/actions/propAmm.d.ts +2228 -0
- package/_types/tempo/actions/propAmm.d.ts.map +1 -0
- package/_types/tempo/chainConfig.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +8 -3
- package/_types/tempo/index.d.ts.map +1 -1
- package/_types/tempo/internal/relay/cache.d.ts +9 -0
- package/_types/tempo/internal/relay/cache.d.ts.map +1 -0
- package/_types/tempo/internal/relay/deadline.d.ts +4 -0
- package/_types/tempo/internal/relay/deadline.d.ts.map +1 -0
- package/_types/tempo/internal/relay/error.d.ts +47 -0
- package/_types/tempo/internal/relay/error.d.ts.map +1 -0
- package/_types/tempo/internal/relay/feePayer.d.ts +70 -0
- package/_types/tempo/internal/relay/feePayer.d.ts.map +1 -0
- package/_types/tempo/internal/relay/feeToken.d.ts +38 -0
- package/_types/tempo/internal/relay/feeToken.d.ts.map +1 -0
- package/_types/tempo/internal/relay/multisig.d.ts +4 -0
- package/_types/tempo/internal/relay/multisig.d.ts.map +1 -0
- package/_types/tempo/internal/relay/plugin.d.ts +5 -0
- package/_types/tempo/internal/relay/plugin.d.ts.map +1 -0
- package/_types/tempo/internal/relay/preflight.d.ts +17 -0
- package/_types/tempo/internal/relay/preflight.d.ts.map +1 -0
- package/_types/tempo/internal/relay/request.d.ts +16 -0
- package/_types/tempo/internal/relay/request.d.ts.map +1 -0
- package/_types/tempo/internal/relay/simulate.d.ts +59 -0
- package/_types/tempo/internal/relay/simulate.d.ts.map +1 -0
- package/_types/tempo/internal/relay/utils.d.ts +294 -0
- package/_types/tempo/internal/relay/utils.d.ts.map +1 -0
- package/_types/tempo/internal/relay/virtualAddress.d.ts +9 -0
- package/_types/tempo/internal/relay/virtualAddress.d.ts.map +1 -0
- package/_types/tempo/internal/relay.d.ts +4 -0
- package/_types/tempo/internal/relay.d.ts.map +1 -0
- package/_types/tempo/multisig/Config.d.ts +0 -13
- package/_types/tempo/multisig/Config.d.ts.map +1 -1
- package/_types/tempo/multisig/Operation.d.ts +0 -5
- package/_types/tempo/multisig/Operation.d.ts.map +1 -1
- package/_types/tokens/definitions/eurc.d.ts +1 -0
- package/_types/tokens/definitions/eurc.d.ts.map +1 -1
- package/_types/tokens/definitions/usdc.d.ts +1 -0
- package/_types/tokens/definitions/usdc.d.ts.map +1 -1
- package/_types/tokens/sets.d.ts +3 -0
- package/_types/tokens/sets.d.ts.map +1 -1
- package/_types/types/eip1193.d.ts +20 -0
- package/_types/types/eip1193.d.ts.map +1 -1
- package/_types/utils/siwe/parseSiweMessage.d.ts.map +1 -1
- package/actions/index.ts +6 -0
- package/actions/public/getStorageValues.ts +93 -0
- package/actions/public/simulateBlocks.ts +13 -0
- package/actions/public/waitForTransactionReceipt.ts +16 -2
- package/chains/definitions/blockdag.ts +20 -0
- package/chains/definitions/candyChain.ts +26 -0
- package/chains/definitions/creditCoin3Devnet.ts +6 -0
- package/chains/definitions/creditCoin3Mainnet.ts +6 -0
- package/chains/definitions/creditCoin3Testnet.ts +6 -0
- package/chains/definitions/kortana.ts +20 -0
- package/chains/definitions/rabbitChainTestnet.ts +21 -0
- package/chains/index.ts +4 -0
- package/clients/createClientResolver.ts +191 -0
- package/clients/decorators/public.ts +18 -0
- package/errors/version.ts +1 -1
- package/index.ts +11 -0
- package/op-stack/actions/getGame.ts +3 -1
- package/op-stack/actions/getGames.ts +1 -1
- package/op-stack/actions/getTimeToNextGame.ts +2 -2
- package/op-stack/actions/getTimeToNextL2Output.ts +2 -2
- package/package.json +1 -1
- package/tempo/Abis.ts +1218 -34
- package/tempo/Addresses.ts +2 -0
- package/tempo/Capabilities.ts +7 -29
- package/tempo/Client.ts +8 -38
- package/tempo/Decorator.ts +239 -3
- package/tempo/ExecutionError.ts +418 -0
- package/tempo/Relay.ts +428 -0
- package/tempo/Selectors.ts +10 -4
- package/tempo/Transaction.ts +2 -1
- package/tempo/Transport.ts +69 -60
- package/tempo/actions/index.ts +1 -0
- package/tempo/actions/propAmm.ts +998 -0
- package/tempo/chainConfig.ts +4 -0
- package/tempo/index.ts +7 -3
- package/tempo/internal/relay/cache.ts +82 -0
- package/tempo/internal/relay/deadline.ts +45 -0
- package/tempo/internal/relay/error.ts +128 -0
- package/tempo/internal/relay/feePayer.ts +692 -0
- package/tempo/internal/relay/feeToken.ts +190 -0
- package/tempo/{Multisig.ts → internal/relay/multisig.ts} +162 -193
- package/tempo/internal/relay/plugin.ts +13 -0
- package/tempo/internal/relay/preflight.ts +81 -0
- package/tempo/internal/relay/request.ts +391 -0
- package/tempo/internal/relay/simulate.ts +367 -0
- package/tempo/internal/relay/utils.ts +202 -0
- package/tempo/internal/relay/virtualAddress.ts +95 -0
- package/tempo/internal/relay.ts +158 -0
- package/tempo/multisig/Config.ts +3 -2
- package/tempo/multisig/Operation.ts +1 -1
- package/tokens/definitions/eurc.ts +1 -0
- package/tokens/definitions/usdc.ts +1 -0
- package/types/eip1193.ts +20 -0
- package/utils/siwe/parseSiweMessage.ts +21 -13
- package/_cjs/tempo/Multisig.js.map +0 -1
- package/_esm/tempo/Multisig.js.map +0 -1
- package/_types/tempo/Multisig.d.ts +0 -37
- package/_types/tempo/Multisig.d.ts.map +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { withTimeout } from '../../../utils/promise/withTimeout.js';
|
|
2
|
+
// Scope in-flight work to one request so Workers never share request-owned I/O.
|
|
3
|
+
const flights = new WeakMap();
|
|
4
|
+
const prefix = 'viem:relay:cache:';
|
|
5
|
+
export function scoped(store) {
|
|
6
|
+
if (!store)
|
|
7
|
+
return undefined;
|
|
8
|
+
return {
|
|
9
|
+
getItem: (key) => store.getItem(key),
|
|
10
|
+
setItem: (key, value) => store.setItem(key, value),
|
|
11
|
+
removeItem: (key) => store.removeItem(key),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export async function memoize(fetch, options) {
|
|
15
|
+
const { store, ttl } = options;
|
|
16
|
+
const key = `${prefix}${options.key}`;
|
|
17
|
+
let active = true;
|
|
18
|
+
const timeoutError = new Error('Relay cache operation timed out.');
|
|
19
|
+
return withTimeout(async () => {
|
|
20
|
+
const raw = await store.getItem(key);
|
|
21
|
+
if (!active)
|
|
22
|
+
throw timeoutError;
|
|
23
|
+
if (raw) {
|
|
24
|
+
try {
|
|
25
|
+
const entry = JSON.parse(raw, (_key, item) => {
|
|
26
|
+
if (typeof item !== 'string' || !item.startsWith(prefix))
|
|
27
|
+
return item;
|
|
28
|
+
if (item.startsWith(`${prefix}string:`))
|
|
29
|
+
return item.slice(`${prefix}string:`.length);
|
|
30
|
+
if (item.startsWith(`${prefix}bigint:`))
|
|
31
|
+
return BigInt(item.slice(`${prefix}bigint:`.length));
|
|
32
|
+
throw new TypeError('Invalid relay cache value.');
|
|
33
|
+
});
|
|
34
|
+
if (entry.expiresAt > Date.now())
|
|
35
|
+
return entry.value;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Refresh malformed or older entries.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
let pending = flights.get(store);
|
|
42
|
+
if (!pending) {
|
|
43
|
+
pending = new Map();
|
|
44
|
+
flights.set(store, pending);
|
|
45
|
+
}
|
|
46
|
+
const existing = pending.get(key);
|
|
47
|
+
if (existing)
|
|
48
|
+
return existing;
|
|
49
|
+
const result = (async () => {
|
|
50
|
+
const value = await fetch();
|
|
51
|
+
if (!active)
|
|
52
|
+
throw timeoutError;
|
|
53
|
+
if (value !== undefined)
|
|
54
|
+
await store.setItem(key, JSON.stringify({ value, expiresAt: Date.now() + ttl }, (_key, item) => {
|
|
55
|
+
if (typeof item === 'bigint')
|
|
56
|
+
return `${prefix}bigint:${item}`;
|
|
57
|
+
if (typeof item === 'string' && item.startsWith(prefix))
|
|
58
|
+
return `${prefix}string:${item}`;
|
|
59
|
+
return item;
|
|
60
|
+
}));
|
|
61
|
+
return value;
|
|
62
|
+
})().finally(() => pending.delete(key));
|
|
63
|
+
pending.set(key, result);
|
|
64
|
+
return result;
|
|
65
|
+
}, {
|
|
66
|
+
timeout: 30_000,
|
|
67
|
+
errorInstance: timeoutError,
|
|
68
|
+
}).finally(() => {
|
|
69
|
+
active = false;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../tempo/internal/relay/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RpcResponse } from 'ox';
|
|
2
|
+
/** Bounds the complete fill, including callbacks that do not observe abort signals. */
|
|
3
|
+
export async function run(handler, request, options, config) {
|
|
4
|
+
const controller = new AbortController();
|
|
5
|
+
const abort = () => controller.abort(options.signal?.reason);
|
|
6
|
+
options.signal?.addEventListener('abort', abort, { once: true });
|
|
7
|
+
if (options.signal?.aborted)
|
|
8
|
+
abort();
|
|
9
|
+
const timeout = setTimeout(() => controller.abort(new RpcResponse.LimitExceededError({
|
|
10
|
+
message: 'Relay fill exceeded its deadline.',
|
|
11
|
+
})), config.timeout ?? 10_000);
|
|
12
|
+
const signal = controller.signal;
|
|
13
|
+
let rejectAbort;
|
|
14
|
+
const aborted = new Promise((_, reject) => {
|
|
15
|
+
rejectAbort = reject;
|
|
16
|
+
});
|
|
17
|
+
const onAbort = () => rejectAbort(signal.reason);
|
|
18
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
19
|
+
try {
|
|
20
|
+
signal.throwIfAborted();
|
|
21
|
+
return await Promise.race([
|
|
22
|
+
handler(request, { ...options, signal }),
|
|
23
|
+
aborted,
|
|
24
|
+
]);
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
clearTimeout(timeout);
|
|
28
|
+
options.signal?.removeEventListener('abort', abort);
|
|
29
|
+
signal.removeEventListener('abort', onAbort);
|
|
30
|
+
// Prevent timed-out hooks from dispatching additional I/O after the response completes.
|
|
31
|
+
controller.abort();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=deadline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deadline.js","sourceRoot":"","sources":["../../../../tempo/internal/relay/deadline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAGhC,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,OAAoC,EACpC,OAAoC,EACpC,OAA2C,EAC3C,MAAmC;IAEnC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5D,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAChE,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;QAAE,KAAK,EAAE,CAAA;IACpC,MAAM,OAAO,GAAG,UAAU,CACxB,GAAG,EAAE,CACH,UAAU,CAAC,KAAK,CACd,IAAI,WAAW,CAAC,kBAAkB,CAAC;QACjC,OAAO,EAAE,mCAAmC;KAC7C,CAAC,CACH,EACH,MAAM,CAAC,OAAO,IAAI,MAAM,CACzB,CAAA;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAA;IAEhC,IAAI,WAAuC,CAAA;IAC3C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,WAAW,GAAG,MAAM,CAAA;IACtB,CAAC,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAChD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,IAAI,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAA;QACvB,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACxB,OAAO,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC;YACxC,OAAO;SACR,CAAC,CAAA;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAA;QACrB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnD,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC5C,wFAAwF;QACxF,UAAU,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Hex } from 'ox';
|
|
2
|
+
import { zeroAddress } from '../../../constants/address.js';
|
|
3
|
+
import { formatUnits } from '../../../utils/unit/formatUnits.js';
|
|
4
|
+
import * as ExecutionError from '../../ExecutionError.js';
|
|
5
|
+
import { resolveTokenMetadata } from './feeToken.js';
|
|
6
|
+
import { simulateAndParseDiffs } from './simulate.js';
|
|
7
|
+
import * as Utils from './utils.js';
|
|
8
|
+
import { extractCalls, resolveVirtualAddresses } from './virtualAddress.js';
|
|
9
|
+
/** Distinguishes execution reverts from transport and plugin failures. */
|
|
10
|
+
export function isExecutionError(error) {
|
|
11
|
+
if (!(error instanceof Error))
|
|
12
|
+
return false;
|
|
13
|
+
const seen = new Set();
|
|
14
|
+
const pending = [error];
|
|
15
|
+
while (pending.length) {
|
|
16
|
+
const current = pending.pop();
|
|
17
|
+
if (!current || typeof current !== 'object' || seen.has(current))
|
|
18
|
+
continue;
|
|
19
|
+
seen.add(current);
|
|
20
|
+
const candidate = current;
|
|
21
|
+
if (candidate.code === 3 ||
|
|
22
|
+
candidate.name === 'UpstreamRevertError' ||
|
|
23
|
+
candidate.name === 'ExecutionRevertedError' ||
|
|
24
|
+
candidate.name === 'ContractFunctionRevertedError' ||
|
|
25
|
+
[candidate.message, candidate.details].some((message) => typeof message === 'string' && /^execution reverted\b/i.test(message)))
|
|
26
|
+
return true;
|
|
27
|
+
pending.push(candidate.cause, candidate.error);
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
export async function formatError(error, parameters, client, simulateStore) {
|
|
32
|
+
const revert = ExecutionError.from(error);
|
|
33
|
+
const stub = {
|
|
34
|
+
from: parameters.from,
|
|
35
|
+
to: parameters.to ?? null,
|
|
36
|
+
gas: '0x0',
|
|
37
|
+
nonce: '0x0',
|
|
38
|
+
value: '0x0',
|
|
39
|
+
maxFeePerGas: '0x0',
|
|
40
|
+
maxPriorityFeePerGas: '0x0',
|
|
41
|
+
};
|
|
42
|
+
if (revert.errorName === 'InsufficientBalance' && revert.args?.length === 3) {
|
|
43
|
+
const [available, required, token] = revert.args;
|
|
44
|
+
const normalized = Utils.normalizeFillTransactionRequest(parameters);
|
|
45
|
+
// Simulate from zero address for optimistic balance diffs.
|
|
46
|
+
const optimisticCalls = normalized ? extractCalls(normalized) : undefined;
|
|
47
|
+
const [{ balanceDiffs, tokenMetadata }, virtualAddresses] = optimisticCalls
|
|
48
|
+
? await Promise.all([
|
|
49
|
+
simulateAndParseDiffs(client, {
|
|
50
|
+
account: zeroAddress,
|
|
51
|
+
calls: optimisticCalls,
|
|
52
|
+
store: simulateStore,
|
|
53
|
+
}),
|
|
54
|
+
resolveVirtualAddresses(client, { calls: optimisticCalls }).catch(() => undefined),
|
|
55
|
+
])
|
|
56
|
+
: [{ balanceDiffs: undefined, tokenMetadata: undefined }, undefined];
|
|
57
|
+
// Re-key balance diffs from zero address to the real sender.
|
|
58
|
+
const senderDiffs = parameters.from && balanceDiffs
|
|
59
|
+
? { [parameters.from]: balanceDiffs[zeroAddress] ?? [] }
|
|
60
|
+
: balanceDiffs;
|
|
61
|
+
const metadata = await resolveTokenMetadata(client, {
|
|
62
|
+
token,
|
|
63
|
+
tokenMetadata,
|
|
64
|
+
store: simulateStore,
|
|
65
|
+
}).catch(() => undefined);
|
|
66
|
+
const deficit = required - available;
|
|
67
|
+
return {
|
|
68
|
+
tx: stub,
|
|
69
|
+
capabilities: {
|
|
70
|
+
balanceDiffs: senderDiffs,
|
|
71
|
+
error: ExecutionError.serialize(revert),
|
|
72
|
+
insufficientFunds: metadata
|
|
73
|
+
? {
|
|
74
|
+
amount: Hex.fromNumber(deficit),
|
|
75
|
+
decimals: metadata.decimals,
|
|
76
|
+
formatted: formatUnits(deficit, metadata.decimals),
|
|
77
|
+
token,
|
|
78
|
+
symbol: metadata.symbol,
|
|
79
|
+
}
|
|
80
|
+
: undefined,
|
|
81
|
+
sponsored: false,
|
|
82
|
+
...(virtualAddresses ? { virtualAddresses } : {}),
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const normalized = Utils.normalizeFillTransactionRequest(parameters);
|
|
87
|
+
const virtualAddresses = normalized
|
|
88
|
+
? await resolveVirtualAddresses(client, {
|
|
89
|
+
calls: extractCalls(normalized),
|
|
90
|
+
}).catch(() => undefined)
|
|
91
|
+
: undefined;
|
|
92
|
+
return {
|
|
93
|
+
tx: stub,
|
|
94
|
+
capabilities: {
|
|
95
|
+
error: ExecutionError.serialize(revert),
|
|
96
|
+
sponsored: false,
|
|
97
|
+
...(virtualAddresses ? { virtualAddresses } : {}),
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../../tempo/internal/relay/error.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import { Hash, RpcResponse, Signature } from 'ox';
|
|
2
|
+
import { TxEnvelopeTempo } from 'ox/tempo';
|
|
3
|
+
import { createClient } from '../../../clients/createClient.js';
|
|
4
|
+
import { http } from '../../../clients/transports/http.js';
|
|
5
|
+
import * as Transaction from '../../Transaction.js';
|
|
6
|
+
import * as Request from './request.js';
|
|
7
|
+
import * as Utils from './utils.js';
|
|
8
|
+
export function create(options) {
|
|
9
|
+
// Bind signing permission to the middleware invocation and its validated payload.
|
|
10
|
+
const authorized = new WeakMap();
|
|
11
|
+
const allowedFeePayers = new Set(options.allowedFeePayers?.map((url) => ExternalFeePayerUrl.normalize(url, {
|
|
12
|
+
allowUnsafe: options.internal_allowUnsafeUrls,
|
|
13
|
+
})));
|
|
14
|
+
return {
|
|
15
|
+
async handleRequest(context, next) {
|
|
16
|
+
const { request } = context;
|
|
17
|
+
if (![
|
|
18
|
+
'eth_fillTransaction',
|
|
19
|
+
'eth_signRawTransaction',
|
|
20
|
+
'eth_sendRawTransaction',
|
|
21
|
+
'eth_sendRawTransactionSync',
|
|
22
|
+
].includes(request.method))
|
|
23
|
+
return next();
|
|
24
|
+
const { client, getClient, options: requestOptions } = context;
|
|
25
|
+
const chainId = requestOptions.chainId;
|
|
26
|
+
const getTokens = (id) => context.resolveTokens(id);
|
|
27
|
+
const record = (details) => {
|
|
28
|
+
if (details && requestOptions.response)
|
|
29
|
+
requestOptions.response.sponsorship_details = details;
|
|
30
|
+
};
|
|
31
|
+
if (request.method !== 'eth_fillTransaction') {
|
|
32
|
+
if (!options.account) {
|
|
33
|
+
if (request.method === 'eth_signRawTransaction')
|
|
34
|
+
throw new RpcResponse.MethodNotFoundError({
|
|
35
|
+
message: 'eth_signRawTransaction requires a fee payer to be configured on the relay. Add `Relay.feePayer({ account })` to enable transaction sponsorship.',
|
|
36
|
+
});
|
|
37
|
+
return next();
|
|
38
|
+
}
|
|
39
|
+
const serialized = request.params?.[0];
|
|
40
|
+
if (typeof serialized !== 'string' ||
|
|
41
|
+
!requestsRawSponsorship(serialized))
|
|
42
|
+
return next();
|
|
43
|
+
const result = await handleRawTransaction({
|
|
44
|
+
...options,
|
|
45
|
+
account: options.account,
|
|
46
|
+
getClient,
|
|
47
|
+
getFeeToken: async (id) => (await getTokens(id))[0],
|
|
48
|
+
method: request.method,
|
|
49
|
+
request,
|
|
50
|
+
});
|
|
51
|
+
record(result.sponsorshipDetails);
|
|
52
|
+
return result.result;
|
|
53
|
+
}
|
|
54
|
+
const parameters = request.params[0];
|
|
55
|
+
const { feePayer: _, ...normalized } = Utils.normalizeFillTransactionRequest(parameters);
|
|
56
|
+
const external = typeof parameters.feePayer === 'string'
|
|
57
|
+
? ExternalFeePayerUrl.normalize(parameters.feePayer, {
|
|
58
|
+
allowUnsafe: options.internal_allowUnsafeUrls ?? false,
|
|
59
|
+
})
|
|
60
|
+
: undefined;
|
|
61
|
+
if (external && !allowedFeePayers.has(external))
|
|
62
|
+
throw new RpcResponse.InvalidParamsError({
|
|
63
|
+
message: 'External fee payer URL is not allowed.',
|
|
64
|
+
});
|
|
65
|
+
const wantsSponsorship = (!!options.account || !!external) && parameters.feePayer !== false;
|
|
66
|
+
if (options.account && !external)
|
|
67
|
+
delete normalized.feePayerSignature;
|
|
68
|
+
const base = { ...normalized, chainId };
|
|
69
|
+
if (!wantsSponsorship)
|
|
70
|
+
return Request.fill(client, base);
|
|
71
|
+
const token = options.feeToken ??
|
|
72
|
+
parameters.feeToken ??
|
|
73
|
+
(!options.validate || external
|
|
74
|
+
? (await getTokens(chainId))[0]
|
|
75
|
+
: undefined);
|
|
76
|
+
const transaction = {
|
|
77
|
+
...base,
|
|
78
|
+
feePayer: true,
|
|
79
|
+
...(token ? { feeToken: token } : {}),
|
|
80
|
+
};
|
|
81
|
+
const prepared = isPreparedTransaction(transaction);
|
|
82
|
+
const fillClient = external
|
|
83
|
+
? createClient({
|
|
84
|
+
chain: client.chain,
|
|
85
|
+
transport: http(external, {
|
|
86
|
+
fetchOptions: { redirect: 'error' },
|
|
87
|
+
retryCount: 0,
|
|
88
|
+
}),
|
|
89
|
+
})
|
|
90
|
+
: client;
|
|
91
|
+
const result = prepared && !external
|
|
92
|
+
? { tx: transaction }
|
|
93
|
+
: await Request.fill(fillClient, transaction, external ? { ...requestOptions, retryCount: 0 } : requestOptions);
|
|
94
|
+
const filled = Utils.normalizeTempoTransaction(result.tx);
|
|
95
|
+
// Reserve intrinsic gas for larger signatures before validating and signing the candidate.
|
|
96
|
+
if ((!prepared || parameters.feePayer !== true) &&
|
|
97
|
+
filled.gas &&
|
|
98
|
+
!filled.feePayerSignature)
|
|
99
|
+
filled.gas += 20000n;
|
|
100
|
+
if (token && (!external || filled.feeToken == null))
|
|
101
|
+
Object.assign(filled, { feeToken: token });
|
|
102
|
+
const sponsored = external ||
|
|
103
|
+
!options.validate ||
|
|
104
|
+
(await shouldSponsor({
|
|
105
|
+
sender: parameters.from,
|
|
106
|
+
transaction: filled,
|
|
107
|
+
validate: options.validate,
|
|
108
|
+
}));
|
|
109
|
+
if (!sponsored)
|
|
110
|
+
return Request.fill(client, { ...base, feePayer: false });
|
|
111
|
+
const defer = typeof normalized.multisigSimulation === 'object' &&
|
|
112
|
+
normalized.multisigSimulation !== null;
|
|
113
|
+
const sponsor = sponsored
|
|
114
|
+
? external
|
|
115
|
+
? (result.capabilities?.sponsor ?? result.sponsor)
|
|
116
|
+
: options.account
|
|
117
|
+
? getSponsor({ ...options, account: options.account })
|
|
118
|
+
: undefined
|
|
119
|
+
: undefined;
|
|
120
|
+
if (options.account && !external && !defer) {
|
|
121
|
+
delete filled.signature;
|
|
122
|
+
if (!filled.from)
|
|
123
|
+
filled.from = parameters.from;
|
|
124
|
+
authorized.set(context, TxEnvelopeTempo.getFeePayerSignPayload(TxEnvelopeTempo.from(filled), { sender: filled.from }));
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
...result,
|
|
128
|
+
...(sponsor ? { sponsor } : {}),
|
|
129
|
+
tx: Utils.formatTempoTransaction(filled),
|
|
130
|
+
capabilities: {
|
|
131
|
+
...result.capabilities,
|
|
132
|
+
sponsored: external
|
|
133
|
+
? (result.capabilities?.sponsored ?? !!sponsor)
|
|
134
|
+
: !!sponsor,
|
|
135
|
+
...(sponsor ? { sponsor } : {}),
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
async signTransaction(result, context) {
|
|
140
|
+
const approved = authorized.get(context);
|
|
141
|
+
authorized.delete(context);
|
|
142
|
+
const parameters = context.request.params[0];
|
|
143
|
+
if (!approved ||
|
|
144
|
+
!options.account ||
|
|
145
|
+
typeof parameters.feePayer === 'string' ||
|
|
146
|
+
parameters.feePayer === false ||
|
|
147
|
+
!result.capabilities?.sponsored ||
|
|
148
|
+
(typeof parameters.multisigSimulation === 'object' &&
|
|
149
|
+
parameters.multisigSimulation !== null))
|
|
150
|
+
return undefined;
|
|
151
|
+
const transaction = Utils.normalizeTempoTransaction(result.tx);
|
|
152
|
+
const payload = TxEnvelopeTempo.getFeePayerSignPayload(TxEnvelopeTempo.from(transaction), { sender: (transaction.from ?? parameters.from) });
|
|
153
|
+
if (payload !== approved)
|
|
154
|
+
throw new RpcResponse.InvalidParamsError({
|
|
155
|
+
message: 'Sponsored transaction changed after validation.',
|
|
156
|
+
});
|
|
157
|
+
const signed = await sign({
|
|
158
|
+
account: options.account,
|
|
159
|
+
onSponsored: options.onSponsored,
|
|
160
|
+
sender: parameters.from,
|
|
161
|
+
transaction,
|
|
162
|
+
signal: context.options.signal,
|
|
163
|
+
});
|
|
164
|
+
if (signed.sponsorshipDetails && context.options.response)
|
|
165
|
+
context.options.response.sponsorship_details = signed.sponsorshipDetails;
|
|
166
|
+
const tx = Utils.formatTempoTransaction(signed.transaction);
|
|
167
|
+
return tx.feePayerSignature;
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Refusal messages keyed by named validation reason. */
|
|
172
|
+
const refusalMessages = {
|
|
173
|
+
billing_past_due: 'Billing past due.',
|
|
174
|
+
billing_required: 'Billing required.',
|
|
175
|
+
fee_token_unsupported: 'Fee token unsupported.',
|
|
176
|
+
spend_limit_exceeded: 'Spend limit exceeded.',
|
|
177
|
+
tx_fee_limit_exceeded: 'Transaction fee limit exceeded.',
|
|
178
|
+
};
|
|
179
|
+
/** Returns sponsor metadata for `eth_fillTransaction` responses. */
|
|
180
|
+
// biome-ignore lint/correctness/noUnusedVariables: declaration merge
|
|
181
|
+
function getSponsor(options) {
|
|
182
|
+
const { account, name, url } = options;
|
|
183
|
+
return {
|
|
184
|
+
address: account.address,
|
|
185
|
+
...(name ? { name } : {}),
|
|
186
|
+
...(url ? { url } : {}),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/** Returns whether the fee payer approves a filled transaction. */
|
|
190
|
+
// biome-ignore lint/correctness/noUnusedVariables: declaration merge
|
|
191
|
+
async function shouldSponsor(options) {
|
|
192
|
+
const { sender, transaction, validate } = options;
|
|
193
|
+
if (!validate)
|
|
194
|
+
return true;
|
|
195
|
+
// Named refusal reasons collapse to false: fills fall back to an
|
|
196
|
+
// unsponsored fill instead of surfacing the reason.
|
|
197
|
+
const verdict = await validate({
|
|
198
|
+
...transaction,
|
|
199
|
+
from: sender,
|
|
200
|
+
});
|
|
201
|
+
return verdict === true;
|
|
202
|
+
}
|
|
203
|
+
/** Returns whether a raw Tempo transaction is explicitly requesting sponsorship. */
|
|
204
|
+
function requestsRawSponsorship(serialized) {
|
|
205
|
+
if (!Utils.isSerializedTempoTransaction(serialized))
|
|
206
|
+
return false;
|
|
207
|
+
const transaction = Transaction.deserialize(serialized);
|
|
208
|
+
return ('feePayerSignature' in transaction && transaction.feePayerSignature === null);
|
|
209
|
+
}
|
|
210
|
+
/** Returns `true` when a fill request already has the fields needed for sponsorship signing. */
|
|
211
|
+
function isPreparedTransaction(value) {
|
|
212
|
+
return (typeof value.from === 'string' &&
|
|
213
|
+
typeof Utils.resolveChainId(value.chainId) === 'number' &&
|
|
214
|
+
typeof value.gas !== 'undefined' &&
|
|
215
|
+
typeof value.nonce !== 'undefined' &&
|
|
216
|
+
(typeof value.maxFeePerGas !== 'undefined' ||
|
|
217
|
+
typeof value.gasPrice !== 'undefined'));
|
|
218
|
+
}
|
|
219
|
+
/** Signs a filled transaction as the fee payer. */
|
|
220
|
+
export async function sign(options) {
|
|
221
|
+
const { account, transaction, sender } = options;
|
|
222
|
+
const from = transaction.from ?? sender;
|
|
223
|
+
const { signature: _, ...withoutSenderSig } = transaction;
|
|
224
|
+
const prepared = { ...withoutSenderSig, from };
|
|
225
|
+
if (!prepared.from)
|
|
226
|
+
throw new RpcResponse.InvalidParamsError({
|
|
227
|
+
message: 'Transaction sender must be provided before fee payer signing.',
|
|
228
|
+
});
|
|
229
|
+
if (!account.sign)
|
|
230
|
+
throw new Error('Fee payer account cannot sign transactions.');
|
|
231
|
+
const chainId = Utils.resolveChainId(transaction.chainId);
|
|
232
|
+
if (chainId === undefined)
|
|
233
|
+
throw new RpcResponse.InvalidParamsError({
|
|
234
|
+
message: 'Transaction chainId must be provided before fee payer signing.',
|
|
235
|
+
});
|
|
236
|
+
const envelope = TxEnvelopeTempo.from(prepared);
|
|
237
|
+
const signPayload = TxEnvelopeTempo.getFeePayerSignPayload(envelope, {
|
|
238
|
+
sender: prepared.from,
|
|
239
|
+
});
|
|
240
|
+
options.signal?.throwIfAborted();
|
|
241
|
+
const feePayerSignature = Signature.from(await account.sign({ hash: signPayload }));
|
|
242
|
+
options.signal?.throwIfAborted();
|
|
243
|
+
// Record the commitment before releasing the signature, since the signed fill can be broadcast through another endpoint.
|
|
244
|
+
const feeToken = transaction.feeToken;
|
|
245
|
+
const sponsorshipDetails = await options.onSponsored?.({
|
|
246
|
+
chainId,
|
|
247
|
+
...(feeToken ? { feeToken } : {}),
|
|
248
|
+
method: 'eth_fillTransaction',
|
|
249
|
+
sender: prepared.from,
|
|
250
|
+
signPayload,
|
|
251
|
+
transaction: TxEnvelopeTempo.serialize(envelope, { feePayerSignature }),
|
|
252
|
+
});
|
|
253
|
+
return {
|
|
254
|
+
...(sponsorshipDetails ? { sponsorshipDetails } : {}),
|
|
255
|
+
transaction: { ...prepared, feePayerSignature },
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/** Handles `eth_signRawTransaction` and broadcast methods for sponsored Tempo transactions. */
|
|
259
|
+
// biome-ignore lint/correctness/noUnusedVariables: declaration merge
|
|
260
|
+
async function handleRawTransaction(options) {
|
|
261
|
+
const { account, feeToken: sponsorFeeToken, getClient, method, request, validate, } = options;
|
|
262
|
+
const serialized = request.params?.[0];
|
|
263
|
+
if (!Utils.isSerializedTempoTransaction(serialized))
|
|
264
|
+
throw new RpcResponse.InvalidParamsError({
|
|
265
|
+
message: 'Only Tempo (0x76/0x78) transactions are supported.',
|
|
266
|
+
});
|
|
267
|
+
const transaction = Transaction.deserialize(serialized);
|
|
268
|
+
// Prefer sender recovered from raw envelope; multisig finalize path supplies fallback sender.
|
|
269
|
+
const sender = transaction.from ?? options.sender;
|
|
270
|
+
// Sponsorship only applies after sender has signed original transaction.
|
|
271
|
+
if (!transaction.signature || !sender)
|
|
272
|
+
throw new RpcResponse.InvalidParamsError({
|
|
273
|
+
message: 'Transaction must be signed by the sender before fee payer signing.',
|
|
274
|
+
});
|
|
275
|
+
if (!account.sign)
|
|
276
|
+
throw new Error('Fee payer account cannot sign transactions.');
|
|
277
|
+
const client = getClient(transaction.chainId);
|
|
278
|
+
const feeToken_chain = client.chain?.feeToken;
|
|
279
|
+
const feeToken = transaction.feeToken ??
|
|
280
|
+
sponsorFeeToken ??
|
|
281
|
+
(await options.getFeeToken?.(transaction.chainId)) ??
|
|
282
|
+
feeToken_chain;
|
|
283
|
+
const transaction_sponsored = feeToken
|
|
284
|
+
? { ...transaction, feeToken }
|
|
285
|
+
: transaction;
|
|
286
|
+
if (validate) {
|
|
287
|
+
const verdict = await validate(transaction_sponsored);
|
|
288
|
+
if (verdict !== true)
|
|
289
|
+
throw new RpcResponse.InvalidParamsError(verdict === false
|
|
290
|
+
? { message: 'Sponsorship rejected.' }
|
|
291
|
+
: { data: { code: verdict }, message: refusalMessages[verdict] });
|
|
292
|
+
}
|
|
293
|
+
const envelope = TxEnvelopeTempo.from(transaction_sponsored);
|
|
294
|
+
const signPayload = TxEnvelopeTempo.getFeePayerSignPayload(envelope, {
|
|
295
|
+
sender,
|
|
296
|
+
});
|
|
297
|
+
const feePayerSignature = Signature.from(await account.sign({ hash: signPayload }));
|
|
298
|
+
const serializedTransaction = TxEnvelopeTempo.serialize(envelope, {
|
|
299
|
+
feePayerSignature,
|
|
300
|
+
signature: transaction.signature,
|
|
301
|
+
});
|
|
302
|
+
// Awaited before any broadcast so a recording failure refuses sponsorship;
|
|
303
|
+
// no sponsored transaction ever reaches the chain unrecorded.
|
|
304
|
+
const sponsorshipDetails = await options.onSponsored?.({
|
|
305
|
+
chainId: transaction.chainId,
|
|
306
|
+
...(feeToken ? { feeToken } : {}),
|
|
307
|
+
method,
|
|
308
|
+
sender,
|
|
309
|
+
signPayload,
|
|
310
|
+
transaction: serializedTransaction,
|
|
311
|
+
transactionHash: Hash.keccak256(serializedTransaction),
|
|
312
|
+
});
|
|
313
|
+
// Raw-sign requests stop after fee-payer signature is added; send methods broadcast it.
|
|
314
|
+
const result = method === 'eth_signRawTransaction'
|
|
315
|
+
? serializedTransaction
|
|
316
|
+
: await client.request({
|
|
317
|
+
method: method,
|
|
318
|
+
params: [
|
|
319
|
+
serializedTransaction,
|
|
320
|
+
...(request.params?.slice(1) ?? []),
|
|
321
|
+
],
|
|
322
|
+
});
|
|
323
|
+
return { result, ...(sponsorshipDetails ? { sponsorshipDetails } : {}) };
|
|
324
|
+
}
|
|
325
|
+
export var ExternalFeePayerUrl;
|
|
326
|
+
(function (ExternalFeePayerUrl) {
|
|
327
|
+
/** Normalizes external fee-payer relay URLs before forwarding fill payloads. */
|
|
328
|
+
function normalize(value, options = {}) {
|
|
329
|
+
let url;
|
|
330
|
+
try {
|
|
331
|
+
url = new URL(value);
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
throw new RpcResponse.InvalidParamsError({
|
|
335
|
+
message: 'Invalid fee payer URL.',
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
const allowUnsafe = options.allowUnsafe === true;
|
|
339
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:')
|
|
340
|
+
throw new RpcResponse.InvalidParamsError({
|
|
341
|
+
message: 'Invalid fee payer URL protocol.',
|
|
342
|
+
});
|
|
343
|
+
if (!allowUnsafe && url.protocol !== 'https:')
|
|
344
|
+
throw new RpcResponse.InvalidParamsError({
|
|
345
|
+
message: 'Invalid fee payer URL protocol.',
|
|
346
|
+
});
|
|
347
|
+
if (!allowUnsafe && isUnsafeHostname(url.hostname))
|
|
348
|
+
throw new RpcResponse.InvalidParamsError({
|
|
349
|
+
message: 'Invalid fee payer URL host.',
|
|
350
|
+
});
|
|
351
|
+
url.username = '';
|
|
352
|
+
url.password = '';
|
|
353
|
+
url.hash = '';
|
|
354
|
+
return url.href;
|
|
355
|
+
}
|
|
356
|
+
ExternalFeePayerUrl.normalize = normalize;
|
|
357
|
+
function isUnsafeHostname(hostname) {
|
|
358
|
+
const host = normalizeHostname(hostname);
|
|
359
|
+
if (host === 'localhost' || host.endsWith('.localhost'))
|
|
360
|
+
return true;
|
|
361
|
+
const ipv4 = parseIpv4(host);
|
|
362
|
+
if (ipv4)
|
|
363
|
+
return isUnsafeIpv4(ipv4);
|
|
364
|
+
if (!host.includes(':'))
|
|
365
|
+
return false;
|
|
366
|
+
const ipv6 = parseIpv6(host);
|
|
367
|
+
if (!ipv6)
|
|
368
|
+
return true;
|
|
369
|
+
return isUnsafeIpv6(ipv6);
|
|
370
|
+
}
|
|
371
|
+
function normalizeHostname(hostname) {
|
|
372
|
+
return hostname
|
|
373
|
+
.toLowerCase()
|
|
374
|
+
.replace(/^\[|\]$/g, '')
|
|
375
|
+
.split('%')[0];
|
|
376
|
+
}
|
|
377
|
+
function parseIpv4(value) {
|
|
378
|
+
const parts = value.split('.');
|
|
379
|
+
if (parts.length !== 4 || parts.some((part) => !/^\d+$/.test(part)))
|
|
380
|
+
return undefined;
|
|
381
|
+
const numbers = parts.map((part) => Number(part));
|
|
382
|
+
if (numbers.some((part) => !Number.isInteger(part) || part < 0 || part > 255))
|
|
383
|
+
return undefined;
|
|
384
|
+
return numbers;
|
|
385
|
+
}
|
|
386
|
+
function isUnsafeIpv4(parts) {
|
|
387
|
+
const [a, b] = parts;
|
|
388
|
+
if (a === 0 || a === 10 || a === 127)
|
|
389
|
+
return true;
|
|
390
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
391
|
+
return true;
|
|
392
|
+
if (a === 169 && b === 254)
|
|
393
|
+
return true;
|
|
394
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
395
|
+
return true;
|
|
396
|
+
if (a === 192 && b === 168)
|
|
397
|
+
return true;
|
|
398
|
+
return a >= 224;
|
|
399
|
+
}
|
|
400
|
+
function parseIpv6(value) {
|
|
401
|
+
const halves = value.split('::');
|
|
402
|
+
if (halves.length > 2)
|
|
403
|
+
return undefined;
|
|
404
|
+
const left = halves[0] ? halves[0].split(':') : [];
|
|
405
|
+
const right = halves[1] ? halves[1].split(':') : [];
|
|
406
|
+
const missing = halves.length === 2 ? 8 - left.length - right.length : 0;
|
|
407
|
+
if (missing < 0)
|
|
408
|
+
return undefined;
|
|
409
|
+
const parts = [...left, ...Array(missing).fill('0'), ...right];
|
|
410
|
+
if (parts.length !== 8)
|
|
411
|
+
return undefined;
|
|
412
|
+
const numbers = parts.map((part) => /^[\da-f]{1,4}$/i.test(part) ? Number.parseInt(part, 16) : NaN);
|
|
413
|
+
if (numbers.some((part) => !Number.isInteger(part) || part < 0 || part > 0xffff))
|
|
414
|
+
return undefined;
|
|
415
|
+
return numbers;
|
|
416
|
+
}
|
|
417
|
+
function isUnsafeIpv6(parts) {
|
|
418
|
+
const [a] = parts;
|
|
419
|
+
if (parts.every((part) => part === 0))
|
|
420
|
+
return true;
|
|
421
|
+
if (parts.slice(0, 7).every((part) => part === 0) && parts[7] === 1)
|
|
422
|
+
return true;
|
|
423
|
+
if ((a & 0xfe00) === 0xfc00)
|
|
424
|
+
return true;
|
|
425
|
+
if ((a & 0xffc0) === 0xfe80)
|
|
426
|
+
return true;
|
|
427
|
+
if ((a & 0xffc0) === 0xfec0)
|
|
428
|
+
return true;
|
|
429
|
+
if ((a & 0xff00) === 0xff00)
|
|
430
|
+
return true;
|
|
431
|
+
const ipv4 = ipv4FromIpv6(parts);
|
|
432
|
+
return ipv4 ? isUnsafeIpv4(ipv4) : false;
|
|
433
|
+
}
|
|
434
|
+
function ipv4FromIpv6(parts) {
|
|
435
|
+
const mapped = parts.slice(0, 5).every((part) => part === 0) && parts[5] === 0xffff;
|
|
436
|
+
const compatible = parts.slice(0, 6).every((part) => part === 0);
|
|
437
|
+
if (!mapped && !compatible)
|
|
438
|
+
return undefined;
|
|
439
|
+
return [parts[6] >> 8, parts[6] & 0xff, parts[7] >> 8, parts[7] & 0xff];
|
|
440
|
+
}
|
|
441
|
+
})(ExternalFeePayerUrl || (ExternalFeePayerUrl = {}));
|
|
442
|
+
//# sourceMappingURL=feePayer.js.map
|