crypto-aio 0.1.0 → 0.2.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 +151 -1
- package/README.md +32 -12
- package/dist/adapters/evm/builder.js +64 -4
- package/dist/adapters/evm/builder.js.map +1 -1
- package/dist/adapters/evm/decode.js +6 -1
- package/dist/adapters/evm/decode.js.map +1 -1
- package/dist/adapters/evm/ethers-client.js +4 -0
- package/dist/adapters/evm/ethers-client.js.map +1 -1
- package/dist/adapters/evm/fees.d.ts +24 -0
- package/dist/adapters/evm/fees.js +47 -4
- package/dist/adapters/evm/fees.js.map +1 -1
- package/dist/adapters/evm/index.d.ts +1 -1
- package/dist/adapters/evm/index.js +2 -1
- package/dist/adapters/evm/index.js.map +1 -1
- package/dist/adapters/evm/network.d.ts +5 -0
- package/dist/adapters/evm/network.js +21 -2
- package/dist/adapters/evm/network.js.map +1 -1
- package/dist/adapters/evm/plugin.d.ts +5 -6
- package/dist/adapters/evm/plugin.js +50 -2
- package/dist/adapters/evm/plugin.js.map +1 -1
- package/dist/adapters/evm/proofs.js +17 -5
- package/dist/adapters/evm/proofs.js.map +1 -1
- package/dist/adapters/evm/reader.d.ts +18 -0
- package/dist/adapters/evm/reader.js +34 -0
- package/dist/adapters/evm/reader.js.map +1 -1
- package/dist/adapters/evm/tokens.d.ts +3 -0
- package/dist/adapters/evm/tokens.js.map +1 -1
- package/dist/adapters/evm/types.d.ts +10 -0
- package/dist/adapters/evm/types.js.map +1 -1
- package/dist/adapters/evm/web3-client.d.ts +6 -3
- package/dist/adapters/evm/web3-client.js +19 -2
- package/dist/adapters/evm/web3-client.js.map +1 -1
- package/dist/adapters/solana/builder.js +29 -18
- package/dist/adapters/solana/builder.js.map +1 -1
- package/dist/adapters/solana/fees.d.ts +12 -3
- package/dist/adapters/solana/fees.js +13 -4
- package/dist/adapters/solana/fees.js.map +1 -1
- package/dist/adapters/solana/message.d.ts +15 -0
- package/dist/adapters/solana/message.js +120 -0
- package/dist/adapters/solana/message.js.map +1 -0
- package/dist/adapters/solana/plugin.js +4 -1
- package/dist/adapters/solana/plugin.js.map +1 -1
- package/dist/adapters/solana/types.d.ts +8 -5
- package/dist/adapters/solana/types.js.map +1 -1
- package/dist/adapters/solana/web3.js +10 -32
- package/dist/adapters/solana/web3.js.map +1 -1
- package/dist/adapters/ton/proofs.js +18 -76
- package/dist/adapters/ton/proofs.js.map +1 -1
- package/dist/adapters/ton/reader.d.ts +45 -4
- package/dist/adapters/ton/reader.js +200 -5
- package/dist/adapters/ton/reader.js.map +1 -1
- package/dist/adapters/ton/trace.d.ts +26 -0
- package/dist/adapters/ton/trace.js +35 -9
- package/dist/adapters/ton/trace.js.map +1 -1
- package/dist/adapters/tron/abi.d.ts +2 -0
- package/dist/adapters/tron/abi.js +2 -0
- package/dist/adapters/tron/abi.js.map +1 -1
- package/dist/adapters/tron/builder.js +20 -4
- package/dist/adapters/tron/builder.js.map +1 -1
- package/dist/adapters/tron/decode.d.ts +2 -0
- package/dist/adapters/tron/decode.js +1 -1
- package/dist/adapters/tron/decode.js.map +1 -1
- package/dist/adapters/tron/proofs.js +1 -0
- package/dist/adapters/tron/proofs.js.map +1 -1
- package/dist/adapters/tron/reader.d.ts +10 -0
- package/dist/adapters/tron/reader.js +17 -0
- package/dist/adapters/tron/reader.js.map +1 -1
- package/dist/adapters/tron/tokens.d.ts +2 -0
- package/dist/adapters/tron/tokens.js.map +1 -1
- package/dist/adapters/utxo/builder.js +1 -1
- package/dist/adapters/utxo/builder.js.map +1 -1
- package/dist/adapters/utxo/chains.js +2 -1
- package/dist/adapters/utxo/chains.js.map +1 -1
- package/dist/adapters/utxo/context.d.ts +6 -0
- package/dist/adapters/utxo/context.js +8 -1
- package/dist/adapters/utxo/context.js.map +1 -1
- package/dist/adapters/utxo/decode.d.ts +8 -0
- package/dist/adapters/utxo/decode.js +36 -0
- package/dist/adapters/utxo/decode.js.map +1 -1
- package/dist/adapters/utxo/driver.js +5 -0
- package/dist/adapters/utxo/driver.js.map +1 -1
- package/dist/adapters/utxo/esplora.d.ts +23 -2
- package/dist/adapters/utxo/esplora.js +49 -2
- package/dist/adapters/utxo/esplora.js.map +1 -1
- package/dist/adapters/utxo/proofs.d.ts +15 -6
- package/dist/adapters/utxo/proofs.js +185 -47
- package/dist/adapters/utxo/proofs.js.map +1 -1
- package/dist/adapters/utxo/rawblock.d.ts +46 -0
- package/dist/adapters/utxo/rawblock.js +159 -0
- package/dist/adapters/utxo/rawblock.js.map +1 -0
- package/dist/adapters/utxo/rawtx.d.ts +14 -0
- package/dist/adapters/utxo/rawtx.js +44 -14
- package/dist/adapters/utxo/rawtx.js.map +1 -1
- package/dist/core/blockchain/handle.d.ts +6 -27
- package/dist/core/blockchain/handle.js +112 -112
- package/dist/core/blockchain/handle.js.map +1 -1
- package/dist/core/config/types.d.ts +15 -0
- package/dist/core/config/types.js.map +1 -1
- package/dist/core/container/container.d.ts +1 -8
- package/dist/core/container/container.js +42 -8
- package/dist/core/container/container.js.map +1 -1
- package/dist/core/driver/types.d.ts +34 -1
- package/dist/core/driver/types.js.map +1 -1
- package/dist/core/errors/codes.d.ts +10 -0
- package/dist/core/errors/codes.js +4 -0
- package/dist/core/errors/codes.js.map +1 -1
- package/dist/core/lifecycle/engine-rules.d.ts +3 -4
- package/dist/core/lifecycle/engine-rules.js +16 -6
- package/dist/core/lifecycle/engine-rules.js.map +1 -1
- package/dist/core/lifecycle/engine.d.ts +2 -0
- package/dist/core/lifecycle/engine.js +19 -1
- package/dist/core/lifecycle/engine.js.map +1 -1
- package/dist/core/lifecycle/evaluate.js +9 -4
- package/dist/core/lifecycle/evaluate.js.map +1 -1
- package/dist/core/lifecycle/monitor.js +16 -6
- package/dist/core/lifecycle/monitor.js.map +1 -1
- package/dist/core/lifecycle/reconcile.d.ts +1 -1
- package/dist/core/lifecycle/reconcile.js +1 -1
- package/dist/core/lifecycle/reconcile.js.map +1 -1
- package/dist/core/lifecycle/workers.d.ts +9 -3
- package/dist/core/lifecycle/workers.js +32 -14
- package/dist/core/lifecycle/workers.js.map +1 -1
- package/dist/core/model/ids.d.ts +1 -0
- package/dist/core/model/ids.js +1 -0
- package/dist/core/model/ids.js.map +1 -1
- package/dist/core/model/ordering.d.ts +8 -0
- package/dist/core/model/ordering.js.map +1 -1
- package/dist/core/model/transaction.d.ts +7 -0
- package/dist/core/model/transaction.js.map +1 -1
- package/dist/core/observe/scanner.js +3 -0
- package/dist/core/observe/scanner.js.map +1 -1
- package/dist/core/signing/wallet.js +8 -0
- package/dist/core/signing/wallet.js.map +1 -1
- package/dist/core/store/format.d.ts +20 -0
- package/dist/core/store/format.js +86 -0
- package/dist/core/store/format.js.map +1 -0
- package/dist/core/store/memory.js +2 -2
- package/dist/core/store/memory.js.map +1 -1
- package/dist/core/store/types.d.ts +15 -3
- package/dist/core/store/types.js +2 -0
- package/dist/core/store/types.js.map +1 -1
- package/dist/core/transport/http-transport.js +21 -13
- package/dist/core/transport/http-transport.js.map +1 -1
- package/dist/core/transport/types.d.ts +16 -1
- package/dist/core/transport/types.js.map +1 -1
- package/dist/core/util/json.d.ts +7 -1
- package/dist/core/util/json.js +13 -4
- package/dist/core/util/json.js.map +1 -1
- package/dist/core/util/names.d.ts +6 -0
- package/dist/core/util/names.js +10 -0
- package/dist/core/util/names.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/testing/contracts/operations.js +20 -1
- package/dist/testing/contracts/operations.js.map +1 -1
- package/dist/testing/env.d.ts +5 -0
- package/dist/testing/env.js +1 -1
- package/dist/testing/env.js.map +1 -1
- package/dist/testing/faulty-store.d.ts +2 -0
- package/dist/testing/faulty-store.js +5 -0
- package/dist/testing/faulty-store.js.map +1 -1
- package/package.json +17 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../../../src/adapters/evm/decode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Transactions and receipts into the driver model: native value and ERC-20 `Transfer`\n * logs as transfers, fees in the native asset, and `decoding: 'partial'` whenever\n * contract code ran, since internal transfers need traces, which the driver does not\n * read.\n */\nimport type {\n DriverTransaction,\n DriverTransfer,\n DriverTxObservation,\n} from '../../core/driver/types';\nimport { ABI_WORD, ADDRESS_WORD } from './client';\nimport { TRANSFER_GAS } from './fees';\nimport { POLYGON_FEE_LOG, POLYGON_TRANSFER_LOG, type EvmNetworkConfig } from './network';\nimport type { EvmAbi, EvmLog, EvmReceipt, EvmTx } from './types';\n\nconst TRANSFER_SELECTOR = '0xa9059cbb';\n\n/**\n * The recipient (lower-cased) and amount of an ERC-20 `transfer(address,uint256)`\n * call: the selector, then two ABI words. `null` for any other calldata.\n */\nfunction transferCall(\n input: string,\n): { readonly to: string; readonly amount: bigint } | null {\n const to = `0x${input.slice(10, 74)}`;\n const amount = `0x${input.slice(74)}`;\n if (\n !input.startsWith(TRANSFER_SELECTOR) ||\n !ADDRESS_WORD.test(to) ||\n !ABI_WORD.test(amount)\n ) {\n return null;\n }\n return { to: `0x${to.slice(26)}`.toLowerCase(), amount: BigInt(amount) };\n}\n\n/**\n * No phantom success: a token `transfer` call worked only if the token logged a\n * `Transfer` from the sender to the call's recipient, of a positive amount whenever the\n * call asked for one. ERC-20 requires the event, and some tokens return `false` instead\n * of reverting, so a successful receipt alone would report a transfer that moved nothing;\n * a log to anyone else, or of nothing, pays the recipient nothing either. A\n * fee-on-transfer token logs less than asked, and still counts; a non-compliant token\n * that moves value without the event is reported failed. The call's arguments come from\n * its signed calldata. Only verdicts on our own transactions apply it (`evmObservation`,\n * `includedFinal`), never the decoder.\n */\nexport function tokenTransferLanded(\n abi: EvmAbi,\n tx: EvmTx,\n receipt: EvmReceipt,\n): boolean {\n if (tx.to === null || !tx.input.startsWith(TRANSFER_SELECTOR)) return true;\n const call = transferCall(tx.input);\n if (!call) return false;\n return receipt.logs.some((log) => {\n const transfer = log.address === tx.to ? abi.decodeTransfer(log) : null;\n return (\n transfer !== null &&\n transfer.from === tx.from &&\n transfer.to.toLowerCase() === call.to &&\n (call.amount === 0n || transfer.amount > 0n)\n );\n });\n}\n\n/** What the chain reports: where the transaction is, and its receipt's status. */\nexport function chainObservation(\n tx: EvmTx,\n receipt: EvmReceipt | null,\n): DriverTxObservation {\n if (receipt) {\n return {\n seen: 'block',\n txHash: tx.hash,\n blockHeight: receipt.blockNumber,\n blockHash: receipt.blockHash,\n success: receipt.status === 1,\n ...(receipt.status === 0 ? { reason: 'reverted' } : {}),\n };\n }\n if (tx.blockHash !== null && tx.blockNumber !== null) {\n return {\n seen: 'block',\n txHash: tx.hash,\n blockHeight: tx.blockNumber,\n blockHash: tx.blockHash,\n };\n }\n return { seen: 'mempool', txHash: tx.hash };\n}\n\n/**\n * The verdict on one of our own transactions: the chain's status, and a successful token\n * `transfer` that logged no transfer to its recipient is `success: false`.\n */\nexport function evmObservation(\n abi: EvmAbi,\n tx: EvmTx,\n receipt: EvmReceipt | null,\n): DriverTxObservation {\n const observation = chainObservation(tx, receipt);\n if (!receipt || receipt.status === 0 || tokenTransferLanded(abi, tx, receipt)) {\n return observation;\n }\n return { ...observation, success: false, reason: 'token transfer failed' };\n}\n\n/** bor's fee log or native transfer log, from the MRC20 predeploy. */\nconst isPolygonSystemLog = (log: EvmLog): boolean =>\n log.address.toLowerCase() === POLYGON_FEE_LOG.address &&\n (log.topics[0] === POLYGON_FEE_LOG.topic ||\n log.topics[0] === POLYGON_TRANSFER_LOG.topic);\n\n/**\n * Whether contract code ran: calldata, logs, or more execution gas than a plain transfer.\n * On Polygon PoS, a plain transfer (no calldata, exactly 21,000 execution gas) also\n * carries bor's system logs, which are no sign of code: its value is `tx.value`.\n */\nfunction ranCode(tx: EvmTx, receipt: EvmReceipt, polygonSystemLogs: boolean): boolean {\n const executionGas = receipt.gasUsed - (receipt.gasUsedForL1 ?? 0n);\n if (tx.input !== '0x' || executionGas !== TRANSFER_GAS) return true;\n const logs = polygonSystemLogs\n ? receipt.logs.filter((log) => !isPolygonSystemLog(log))\n : receipt.logs;\n return logs.length > 0;\n}\n\n/**\n * Any transaction as the chain reports it: the receipt's status, never the token\n * verdict, so a third party's call that shares the `transfer` selector is not misreported.\n * Pass the network's config so bor's system logs do not make a plain Polygon transfer\n * `partial`.\n */\nexport function decodeTransaction(\n abi: EvmAbi,\n tx: EvmTx,\n receipt: EvmReceipt | null,\n timestamp?: number,\n network: Pick<EvmNetworkConfig, 'polygonSystemLogs'> = { polygonSystemLogs: false },\n): DriverTransaction {\n const transfers: DriverTransfer[] = [];\n const executed = receipt === null || receipt.status === 1;\n const to = tx.to ?? receipt?.contractAddress ?? null;\n if (executed && tx.value > 0n && to !== null) {\n transfers.push({\n locator: 'native',\n from: [tx.from],\n to,\n asset: 'native',\n amount: tx.value,\n source: 'native',\n });\n }\n for (const log of receipt?.status === 1 ? receipt.logs : []) {\n const decoded = abi.decodeTransfer(log);\n if (!decoded) continue;\n transfers.push({\n locator: `log:${log.logIndex}`,\n from: [decoded.from],\n to: decoded.to,\n asset: { standard: 'erc20', contract: log.address },\n amount: decoded.amount,\n source: 'token-event',\n });\n }\n const decoding =\n receipt === null\n ? 'partial'\n : receipt.status === 0 || !ranCode(tx, receipt, network.polygonSystemLogs)\n ? 'complete'\n : 'partial';\n return {\n id: tx.hash,\n observation: chainObservation(tx, receipt),\n ...(receipt\n ? {\n fee: [\n {\n asset: 'native' as const,\n amount: receipt.gasUsed * receipt.effectiveGasPrice + (receipt.l1Fee ?? 0n),\n },\n ],\n }\n : {}),\n transfers,\n decoding,\n ...(timestamp !== undefined ? { timestamp } : {}),\n details: {\n nonce: tx.nonce,\n type: tx.type,\n gasLimit: tx.gasLimit,\n ...(receipt\n ? {\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.effectiveGasPrice,\n status: receipt.status,\n }\n : {}),\n ...(receipt?.l1Fee !== undefined ? { l1Fee: receipt.l1Fee } : {}),\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../../../src/adapters/evm/decode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Transactions and receipts into the driver model: native value and ERC-20 `Transfer`\n * logs as transfers, fees in the native asset, and `decoding: 'partial'` whenever\n * contract code ran, since internal transfers need traces, which the driver does not\n * read.\n */\nimport type {\n DriverTransaction,\n DriverTransfer,\n DriverTxObservation,\n} from '../../core/driver/types';\nimport { ABI_WORD, ADDRESS_WORD } from './client';\nimport { TRANSFER_GAS } from './fees';\nimport { POLYGON_FEE_LOG, POLYGON_TRANSFER_LOG, type EvmNetworkConfig } from './network';\nimport type { EvmAbi, EvmLog, EvmReceipt, EvmTx } from './types';\n\nconst TRANSFER_SELECTOR = '0xa9059cbb';\n\n/**\n * The recipient (lower-cased) and amount of an ERC-20 `transfer(address,uint256)`\n * call: the selector, then two ABI words. `null` for any other calldata.\n */\nfunction transferCall(\n input: string,\n): { readonly to: string; readonly amount: bigint } | null {\n const to = `0x${input.slice(10, 74)}`;\n const amount = `0x${input.slice(74)}`;\n if (\n !input.startsWith(TRANSFER_SELECTOR) ||\n !ADDRESS_WORD.test(to) ||\n !ABI_WORD.test(amount)\n ) {\n return null;\n }\n return { to: `0x${to.slice(26)}`.toLowerCase(), amount: BigInt(amount) };\n}\n\n/**\n * No phantom success: a token `transfer` call worked only if the token logged a\n * `Transfer` from the sender to the call's recipient, of a positive amount whenever the\n * call asked for one. ERC-20 requires the event, and some tokens return `false` instead\n * of reverting, so a successful receipt alone would report a transfer that moved nothing;\n * a log to anyone else, or of nothing, pays the recipient nothing either. A\n * fee-on-transfer token logs less than asked, and still counts; a non-compliant token\n * that moves value without the event is reported failed. The call's arguments come from\n * its signed calldata. Only verdicts on our own transactions apply it (`evmObservation`,\n * `includedFinal`), never the decoder.\n */\nexport function tokenTransferLanded(\n abi: EvmAbi,\n tx: EvmTx,\n receipt: EvmReceipt,\n): boolean {\n if (tx.to === null || !tx.input.startsWith(TRANSFER_SELECTOR)) return true;\n const call = transferCall(tx.input);\n if (!call) return false;\n return receipt.logs.some((log) => {\n const transfer = log.address === tx.to ? abi.decodeTransfer(log) : null;\n return (\n transfer !== null &&\n transfer.from === tx.from &&\n transfer.to.toLowerCase() === call.to &&\n (call.amount === 0n || transfer.amount > 0n)\n );\n });\n}\n\n/** What the chain reports: where the transaction is, and its receipt's status. */\nexport function chainObservation(\n tx: EvmTx,\n receipt: EvmReceipt | null,\n): DriverTxObservation {\n if (receipt) {\n return {\n seen: 'block',\n txHash: tx.hash,\n blockHeight: receipt.blockNumber,\n blockHash: receipt.blockHash,\n success: receipt.status === 1,\n ...(receipt.status === 0 ? { reason: 'reverted' } : {}),\n };\n }\n if (tx.blockHash !== null && tx.blockNumber !== null) {\n return {\n seen: 'block',\n txHash: tx.hash,\n blockHeight: tx.blockNumber,\n blockHash: tx.blockHash,\n };\n }\n return { seen: 'mempool', txHash: tx.hash };\n}\n\n/**\n * The verdict on one of our own transactions: the chain's status, and a successful token\n * `transfer` that logged no transfer to its recipient is `success: false`.\n */\nexport function evmObservation(\n abi: EvmAbi,\n tx: EvmTx,\n receipt: EvmReceipt | null,\n): DriverTxObservation {\n const observation = chainObservation(tx, receipt);\n if (!receipt || receipt.status === 0 || tokenTransferLanded(abi, tx, receipt)) {\n return observation;\n }\n return {\n ...observation,\n success: false,\n reason: 'token transfer failed',\n failure: 'unevidenced',\n };\n}\n\n/** bor's fee log or native transfer log, from the MRC20 predeploy. */\nconst isPolygonSystemLog = (log: EvmLog): boolean =>\n log.address.toLowerCase() === POLYGON_FEE_LOG.address &&\n (log.topics[0] === POLYGON_FEE_LOG.topic ||\n log.topics[0] === POLYGON_TRANSFER_LOG.topic);\n\n/**\n * Whether contract code ran: calldata, logs, or more execution gas than a plain transfer.\n * On Polygon PoS, a plain transfer (no calldata, exactly 21,000 execution gas) also\n * carries bor's system logs, which are no sign of code: its value is `tx.value`.\n */\nfunction ranCode(tx: EvmTx, receipt: EvmReceipt, polygonSystemLogs: boolean): boolean {\n const executionGas = receipt.gasUsed - (receipt.gasUsedForL1 ?? 0n);\n if (tx.input !== '0x' || executionGas !== TRANSFER_GAS) return true;\n const logs = polygonSystemLogs\n ? receipt.logs.filter((log) => !isPolygonSystemLog(log))\n : receipt.logs;\n return logs.length > 0;\n}\n\n/**\n * Any transaction as the chain reports it: the receipt's status, never the token\n * verdict, so a third party's call that shares the `transfer` selector is not misreported.\n * Pass the network's config so bor's system logs do not make a plain Polygon transfer\n * `partial`.\n */\nexport function decodeTransaction(\n abi: EvmAbi,\n tx: EvmTx,\n receipt: EvmReceipt | null,\n timestamp?: number,\n network: Pick<EvmNetworkConfig, 'polygonSystemLogs'> = { polygonSystemLogs: false },\n): DriverTransaction {\n const transfers: DriverTransfer[] = [];\n const executed = receipt === null || receipt.status === 1;\n const to = tx.to ?? receipt?.contractAddress ?? null;\n if (executed && tx.value > 0n && to !== null) {\n transfers.push({\n locator: 'native',\n from: [tx.from],\n to,\n asset: 'native',\n amount: tx.value,\n source: 'native',\n });\n }\n for (const log of receipt?.status === 1 ? receipt.logs : []) {\n const decoded = abi.decodeTransfer(log);\n if (!decoded) continue;\n transfers.push({\n locator: `log:${log.logIndex}`,\n from: [decoded.from],\n to: decoded.to,\n asset: { standard: 'erc20', contract: log.address },\n amount: decoded.amount,\n source: 'token-event',\n });\n }\n const decoding =\n receipt === null\n ? 'partial'\n : receipt.status === 0 || !ranCode(tx, receipt, network.polygonSystemLogs)\n ? 'complete'\n : 'partial';\n return {\n id: tx.hash,\n observation: chainObservation(tx, receipt),\n ...(receipt\n ? {\n fee: [\n {\n asset: 'native' as const,\n amount: receipt.gasUsed * receipt.effectiveGasPrice + (receipt.l1Fee ?? 0n),\n },\n ],\n }\n : {}),\n transfers,\n decoding,\n ...(timestamp !== undefined ? { timestamp } : {}),\n details: {\n nonce: tx.nonce,\n type: tx.type,\n gasLimit: tx.gasLimit,\n ...(receipt\n ? {\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.effectiveGasPrice,\n status: receipt.status,\n }\n : {}),\n ...(receipt?.l1Fee !== undefined ? { l1Fee: receipt.l1Fee } : {}),\n },\n };\n}\n"]}
|
|
@@ -39,10 +39,12 @@ const erc20 = new ethers_1.Interface([
|
|
|
39
39
|
'function balanceOf(address owner) view returns (uint256)',
|
|
40
40
|
'function decimals() view returns (uint8)',
|
|
41
41
|
'function symbol() view returns (string)',
|
|
42
|
+
'function deprecated() view returns (bool)',
|
|
42
43
|
'event Transfer(address indexed from, address indexed to, uint256 amount)',
|
|
43
44
|
]);
|
|
44
45
|
const gasPriceOracle = new ethers_1.Interface([
|
|
45
46
|
'function getL1Fee(bytes data) view returns (uint256)',
|
|
47
|
+
'function getOperatorFee(uint256 gasUsed) view returns (uint256)',
|
|
46
48
|
]);
|
|
47
49
|
const TRANSFER_TOPIC = erc20.getEvent('Transfer')?.topicHash;
|
|
48
50
|
const ethersAbi = {
|
|
@@ -51,7 +53,9 @@ const ethersAbi = {
|
|
|
51
53
|
encodeBalanceOf: (owner) => erc20.encodeFunctionData('balanceOf', [owner]),
|
|
52
54
|
encodeDecimals: () => erc20.encodeFunctionData('decimals', []),
|
|
53
55
|
encodeSymbol: () => erc20.encodeFunctionData('symbol', []),
|
|
56
|
+
encodeDeprecated: () => erc20.encodeFunctionData('deprecated', []),
|
|
54
57
|
encodeGetL1Fee: (unsignedTx) => gasPriceOracle.encodeFunctionData('getL1Fee', [unsignedTx]),
|
|
58
|
+
encodeGetOperatorFee: (gasUsed) => gasPriceOracle.encodeFunctionData('getOperatorFee', [gasUsed]),
|
|
55
59
|
decodeUint256: (data) => {
|
|
56
60
|
if (!client_1.ABI_WORD.test(data))
|
|
57
61
|
throw new Error('not one ABI word');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ethers-client.js","sourceRoot":"","sources":["../../../src/adapters/evm/ethers-client.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,mCAagB;AAGhB,qCAMkB;AAClB,qCAA4C;AAC5C,+BAAkD;AAKlD;;;GAGG;AACH,MAAa,wBAAyB,SAAQ,2BAAkB;IACrD,KAAK,CAAO;IAErB,YAAY,OAAgB,EAAE,IAAU;QACtC,KAAK,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/E,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEQ,KAAK,CAAC,KAAK,CAClB,OAA0C;QAE1C,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAlBD,4DAkBC;AAED,MAAM,KAAK,GAAG,iBAAQ,CAAC,eAAe,EAAE,CAAC;AACzC,MAAM,KAAK,GAAG,IAAI,kBAAS,CAAC;IAC1B,+CAA+C;IAC/C,0DAA0D;IAC1D,0CAA0C;IAC1C,yCAAyC;IACzC,0EAA0E;CAC3E,CAAC,CAAC;AACH,MAAM,cAAc,GAAG,IAAI,kBAAS,CAAC;IACnC,sDAAsD;CACvD,CAAC,CAAC;AACH,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAmB,CAAC;AAEvE,MAAM,SAAS,GAAW;IACxB,aAAa,EAAE,cAAc;IAC7B,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAClF,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1E,cAAc,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,EAAE,CAAC;IAC9D,YAAY,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC1D,cAAc,EAAE,CAAC,UAAU,EAAE,EAAE,CAC7B,cAAc,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAC;IAC7D,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE;QACtB,IAAI,CAAC,iBAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAW,CAAC;IACtD,CAAC;IACD,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAW;IACnE,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE;QACtB,MAAM,KAAK,GAAG,IAAA,yBAAgB,EAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,IAAA,mBAAU,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAW,CAAC;YACpE,EAAE,EAAE,IAAA,mBAAU,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAW,CAAC;YAChE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAW;SAC3D,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,SAAS,QAAQ,CAAC,EAAe,EAAE,SAAwB;IACzD,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,EAAE,CAAC,OAAO;QACnB,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC;QACvB,EAAE,EAAE,EAAE,CAAC,EAAE;QACT,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,QAAQ,EAAE,EAAE,CAAC,QAAQ;KACtB,CAAC;IACF,MAAM,KAAK,GAAG,oBAAW,CAAC,IAAI,CAC5B,EAAE,CAAC,IAAI,KAAK,SAAS;QACnB,CAAC,CAAC;YACE,GAAG,MAAM;YACT,IAAI,EAAE,CAAC;YACP,YAAY,EAAE,EAAE,CAAC,YAAY;YAC7B,oBAAoB,EAAE,EAAE,CAAC,oBAAoB;SAC9C;QACH,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAClD,CAAC;IACF,IAAI,SAAS;QAAE,KAAK,CAAC,SAAS,GAAG,kBAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAa,YAAa,SAAQ,sBAAa;IACpC,OAAO,GAAG,QAAQ,CAAC;IACnB,GAAG,GAAG,SAAS,CAAC;IAChB,UAAU,CAAY;IACtB,QAAQ,CAAU;IAE3B,YAAY,SAAoB,EAAE,OAAe;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,0FAA0F;QAC1F,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAES,IAAI,CACZ,MAAc,EACd,MAA0B,EAC1B,IAAiB;QAEjB,+EAA+E;QAC/E,OAAO,IAAA,mBAAa,EAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,OAAO,gBAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAA,kBAAS,EAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,QAAQ,CAAC,OAAe;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAU,CAAC,CAAC;IAC3C,CAAC;IAED,oBAAoB,CAAC,SAAqB;QACxC,OAAO,IAAA,uBAAc,EAAC,IAAA,gBAAO,EAAC,IAAA,8BAAqB,EAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;IAES,cAAc,CAAC,EAAe;QACtC,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC;IACzC,CAAC;IAES,YAAY,CAAC,EAAe;QACpC,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC;IACnC,CAAC;IAES,YAAY,CACpB,EAAe,EACf,SAAuB;QAEvB,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACvC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,IAAc,EAAE,CAAC;IACjE,CAAC;IAED,YAAY;QACV,MAAM,MAAM,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAC5E,IAAA,mBAAa,EAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,IAAA,gBAAU,EAAC,MAAM,CAAC,CAAC,CACnE,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;IACnD,CAAC;CACF;AAxDD,oCAwDC;AAED,iFAAiF;AACpE,QAAA,mBAAmB,GAAG,IAAA,yBAAgB,EACjD,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAC7D,CAAC","sourcesContent":["/**\n * `EthersClient`: the ethers v6 strategy (the EVM default). Driver I/O goes straight to the\n * core transport under each call's tags, never through ethers' provider: ethers' request\n * queue drains on a real 0 ms timer that fake-clock tests cannot step deterministically,\n * and the driver needs none of it (one request per call). ethers does the codec work, and\n * `TransportJsonRpcProvider` (static network, no batching, no cache, no polling, `_send` →\n * transport) is the `crypto-aio/native` client.\n */\nimport {\n AbiCoder,\n Interface,\n JsonRpcApiProvider,\n Network,\n Signature,\n Transaction,\n computeAddress,\n getAddress,\n hexlify,\n isAddress,\n type JsonRpcPayload,\n type JsonRpcResult,\n} from 'ethers';\nimport type { DisposableNativeClient } from '../../core/driver/types';\nimport type { Transport } from '../../core/transport/types';\nimport {\n ABI_WORD,\n ADDRESS,\n EvmClientBase,\n transferLogWords,\n uncompressedPublicKey,\n} from './client';\nimport { evmDriverFactory } from './driver';\nimport { nativeTags, transportCall } from './rpc';\nimport type { EvmAbi, EvmCallTags, EvmSignature, EvmTxFields } from './types';\n\ntype Call = (method: string, params: unknown) => Promise<unknown>;\n\n/**\n * The ethers provider bridged onto the core transport through `call`: the native client\n * only.\n */\nexport class TransportJsonRpcProvider extends JsonRpcApiProvider {\n readonly #call: Call;\n\n constructor(network: Network, call: Call) {\n super(network, { staticNetwork: network, batchMaxCount: 1, cacheTimeout: -1 });\n this.#call = call;\n this._start();\n }\n\n override async _send(\n payload: JsonRpcPayload | JsonRpcPayload[],\n ): Promise<JsonRpcResult[]> {\n const results: JsonRpcResult[] = [];\n for (const item of Array.isArray(payload) ? payload : [payload]) {\n results.push({ id: item.id, result: await this.#call(item.method, item.params) });\n }\n return results;\n }\n}\n\nconst coder = AbiCoder.defaultAbiCoder();\nconst erc20 = new Interface([\n 'function transfer(address to, uint256 amount)',\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'event Transfer(address indexed from, address indexed to, uint256 amount)',\n]);\nconst gasPriceOracle = new Interface([\n 'function getL1Fee(bytes data) view returns (uint256)',\n]);\nconst TRANSFER_TOPIC = erc20.getEvent('Transfer')?.topicHash as string;\n\nconst ethersAbi: EvmAbi = {\n transferTopic: TRANSFER_TOPIC,\n encodeTransfer: (to, amount) => erc20.encodeFunctionData('transfer', [to, amount]),\n encodeBalanceOf: (owner) => erc20.encodeFunctionData('balanceOf', [owner]),\n encodeDecimals: () => erc20.encodeFunctionData('decimals', []),\n encodeSymbol: () => erc20.encodeFunctionData('symbol', []),\n encodeGetL1Fee: (unsignedTx) =>\n gasPriceOracle.encodeFunctionData('getL1Fee', [unsignedTx]),\n decodeUint256: (data) => {\n if (!ABI_WORD.test(data)) throw new Error('not one ABI word');\n return coder.decode(['uint256'], data)[0] as bigint;\n },\n decodeString: (data) => coder.decode(['string'], data)[0] as string,\n decodeTransfer: (log) => {\n const words = transferLogWords(log, TRANSFER_TOPIC);\n if (!words) return null;\n return {\n from: getAddress(coder.decode(['address'], words.from)[0] as string),\n to: getAddress(coder.decode(['address'], words.to)[0] as string),\n amount: coder.decode(['uint256'], words.data)[0] as bigint,\n };\n },\n};\n\nfunction toEthers(tx: EvmTxFields, signature?: EvmSignature): Transaction {\n const common = {\n chainId: tx.chainId,\n nonce: Number(tx.nonce),\n to: tx.to,\n value: tx.value,\n data: tx.data,\n gasLimit: tx.gasLimit,\n };\n const built = Transaction.from(\n tx.type === 'eip1559'\n ? {\n ...common,\n type: 2,\n maxFeePerGas: tx.maxFeePerGas,\n maxPriorityFeePerGas: tx.maxPriorityFeePerGas,\n }\n : { ...common, type: 0, gasPrice: tx.gasPrice },\n );\n if (signature) built.signature = Signature.from(signature);\n return built;\n}\n\nexport class EthersClient extends EvmClientBase {\n readonly library = 'ethers';\n readonly abi = ethersAbi;\n readonly #transport: Transport;\n readonly #network: Network;\n\n constructor(transport: Transport, chainId: bigint) {\n super(chainId);\n this.#transport = transport;\n // A plain network: ethers' known networks carry plugins (ENS, gas stations) we never use.\n this.#network = new Network('crypto-aio', chainId);\n }\n\n protected send(\n method: string,\n params: readonly unknown[],\n tags: EvmCallTags,\n ): Promise<unknown> {\n // No SDK queue, and so no real timer, between a driver call and the transport.\n return transportCall(this.#transport, method, [...params], tags);\n }\n\n isAddress(value: string): boolean {\n return ADDRESS.test(value) && isAddress(value);\n }\n\n checksum(address: string): string {\n return this.checked(address, getAddress);\n }\n\n addressFromPublicKey(publicKey: Uint8Array): string {\n return computeAddress(hexlify(uncompressedPublicKey(publicKey)));\n }\n\n protected encodeUnsigned(tx: EvmTxFields): string {\n return toEthers(tx).unsignedSerialized;\n }\n\n protected hashUnsigned(tx: EvmTxFields): string {\n return toEthers(tx).unsignedHash;\n }\n\n protected encodeSigned(\n tx: EvmTxFields,\n signature: EvmSignature,\n ): { raw: string; hash: string } {\n const signed = toEthers(tx, signature);\n return { raw: signed.serialized, hash: signed.hash as string };\n }\n\n createNative(): DisposableNativeClient {\n const client = new TransportJsonRpcProvider(this.#network, (method, params) =>\n transportCall(this.#transport, method, params, nativeTags(method)),\n );\n return { client, close: () => client.destroy() };\n }\n}\n\n/** The `ethers` adapter's driver factory; the manifest's `load()` returns it. */\nexport const ethersDriverFactory = evmDriverFactory(\n (transport, chainId) => new EthersClient(transport, chainId),\n);\n"]}
|
|
1
|
+
{"version":3,"file":"ethers-client.js","sourceRoot":"","sources":["../../../src/adapters/evm/ethers-client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `EthersClient`: the ethers v6 strategy (the EVM default). Driver I/O goes straight to the\n * core transport under each call's tags, never through ethers' provider: ethers' request\n * queue drains on a real 0 ms timer that fake-clock tests cannot step deterministically,\n * and the driver needs none of it (one request per call). ethers does the codec work, and\n * `TransportJsonRpcProvider` (static network, no batching, no cache, no polling, `_send` →\n * transport) is the `crypto-aio/native` client.\n */\nimport {\n AbiCoder,\n Interface,\n JsonRpcApiProvider,\n Network,\n Signature,\n Transaction,\n computeAddress,\n getAddress,\n hexlify,\n isAddress,\n type JsonRpcPayload,\n type JsonRpcResult,\n} from 'ethers';\nimport type { DisposableNativeClient } from '../../core/driver/types';\nimport type { Transport } from '../../core/transport/types';\nimport {\n ABI_WORD,\n ADDRESS,\n EvmClientBase,\n transferLogWords,\n uncompressedPublicKey,\n} from './client';\nimport { evmDriverFactory } from './driver';\nimport { nativeTags, transportCall } from './rpc';\nimport type { EvmAbi, EvmCallTags, EvmSignature, EvmTxFields } from './types';\n\ntype Call = (method: string, params: unknown) => Promise<unknown>;\n\n/**\n * The ethers provider bridged onto the core transport through `call`: the native client\n * only.\n */\nexport class TransportJsonRpcProvider extends JsonRpcApiProvider {\n readonly #call: Call;\n\n constructor(network: Network, call: Call) {\n super(network, { staticNetwork: network, batchMaxCount: 1, cacheTimeout: -1 });\n this.#call = call;\n this._start();\n }\n\n override async _send(\n payload: JsonRpcPayload | JsonRpcPayload[],\n ): Promise<JsonRpcResult[]> {\n const results: JsonRpcResult[] = [];\n for (const item of Array.isArray(payload) ? payload : [payload]) {\n results.push({ id: item.id, result: await this.#call(item.method, item.params) });\n }\n return results;\n }\n}\n\nconst coder = AbiCoder.defaultAbiCoder();\nconst erc20 = new Interface([\n 'function transfer(address to, uint256 amount)',\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function deprecated() view returns (bool)',\n 'event Transfer(address indexed from, address indexed to, uint256 amount)',\n]);\nconst gasPriceOracle = new Interface([\n 'function getL1Fee(bytes data) view returns (uint256)',\n 'function getOperatorFee(uint256 gasUsed) view returns (uint256)',\n]);\nconst TRANSFER_TOPIC = erc20.getEvent('Transfer')?.topicHash as string;\n\nconst ethersAbi: EvmAbi = {\n transferTopic: TRANSFER_TOPIC,\n encodeTransfer: (to, amount) => erc20.encodeFunctionData('transfer', [to, amount]),\n encodeBalanceOf: (owner) => erc20.encodeFunctionData('balanceOf', [owner]),\n encodeDecimals: () => erc20.encodeFunctionData('decimals', []),\n encodeSymbol: () => erc20.encodeFunctionData('symbol', []),\n encodeDeprecated: () => erc20.encodeFunctionData('deprecated', []),\n encodeGetL1Fee: (unsignedTx) =>\n gasPriceOracle.encodeFunctionData('getL1Fee', [unsignedTx]),\n encodeGetOperatorFee: (gasUsed) =>\n gasPriceOracle.encodeFunctionData('getOperatorFee', [gasUsed]),\n decodeUint256: (data) => {\n if (!ABI_WORD.test(data)) throw new Error('not one ABI word');\n return coder.decode(['uint256'], data)[0] as bigint;\n },\n decodeString: (data) => coder.decode(['string'], data)[0] as string,\n decodeTransfer: (log) => {\n const words = transferLogWords(log, TRANSFER_TOPIC);\n if (!words) return null;\n return {\n from: getAddress(coder.decode(['address'], words.from)[0] as string),\n to: getAddress(coder.decode(['address'], words.to)[0] as string),\n amount: coder.decode(['uint256'], words.data)[0] as bigint,\n };\n },\n};\n\nfunction toEthers(tx: EvmTxFields, signature?: EvmSignature): Transaction {\n const common = {\n chainId: tx.chainId,\n nonce: Number(tx.nonce),\n to: tx.to,\n value: tx.value,\n data: tx.data,\n gasLimit: tx.gasLimit,\n };\n const built = Transaction.from(\n tx.type === 'eip1559'\n ? {\n ...common,\n type: 2,\n maxFeePerGas: tx.maxFeePerGas,\n maxPriorityFeePerGas: tx.maxPriorityFeePerGas,\n }\n : { ...common, type: 0, gasPrice: tx.gasPrice },\n );\n if (signature) built.signature = Signature.from(signature);\n return built;\n}\n\nexport class EthersClient extends EvmClientBase {\n readonly library = 'ethers';\n readonly abi = ethersAbi;\n readonly #transport: Transport;\n readonly #network: Network;\n\n constructor(transport: Transport, chainId: bigint) {\n super(chainId);\n this.#transport = transport;\n // A plain network: ethers' known networks carry plugins (ENS, gas stations) we never use.\n this.#network = new Network('crypto-aio', chainId);\n }\n\n protected send(\n method: string,\n params: readonly unknown[],\n tags: EvmCallTags,\n ): Promise<unknown> {\n // No SDK queue, and so no real timer, between a driver call and the transport.\n return transportCall(this.#transport, method, [...params], tags);\n }\n\n isAddress(value: string): boolean {\n return ADDRESS.test(value) && isAddress(value);\n }\n\n checksum(address: string): string {\n return this.checked(address, getAddress);\n }\n\n addressFromPublicKey(publicKey: Uint8Array): string {\n return computeAddress(hexlify(uncompressedPublicKey(publicKey)));\n }\n\n protected encodeUnsigned(tx: EvmTxFields): string {\n return toEthers(tx).unsignedSerialized;\n }\n\n protected hashUnsigned(tx: EvmTxFields): string {\n return toEthers(tx).unsignedHash;\n }\n\n protected encodeSigned(\n tx: EvmTxFields,\n signature: EvmSignature,\n ): { raw: string; hash: string } {\n const signed = toEthers(tx, signature);\n return { raw: signed.serialized, hash: signed.hash as string };\n }\n\n createNative(): DisposableNativeClient {\n const client = new TransportJsonRpcProvider(this.#network, (method, params) =>\n transportCall(this.#transport, method, params, nativeTags(method)),\n );\n return { client, close: () => client.destroy() };\n }\n}\n\n/** The `ethers` adapter's driver factory; the manifest's `load()` returns it. */\nexport const ethersDriverFactory = evmDriverFactory(\n (transport, chainId) => new EthersClient(transport, chainId),\n);\n"]}
|
|
@@ -55,6 +55,24 @@ export declare function capPrice(params: EvmFeeParams, ceiling: bigint): EvmFeeP
|
|
|
55
55
|
* cancel's least bump. The details carry the price and the bound as decimal strings.
|
|
56
56
|
*/
|
|
57
57
|
export declare function assertWithinCeiling(params: EvmFeeParams, ceiling: bigint): void;
|
|
58
|
+
/**
|
|
59
|
+
* The default `maxGasLimit`, the highest gas limit an EVM transaction signs: 16,777,216
|
|
60
|
+
* (2^24), the per-transaction cap Ethereum enforces since Fusaka (EIP-7825), so no
|
|
61
|
+
* transaction above it is included there. A transfer this driver builds needs a small
|
|
62
|
+
* fraction of it (21,000 gas for a plain transfer, tens of thousands for a token's); an
|
|
63
|
+
* Arbitrum estimate also counts the L1 data fee in L2 gas, so it grows with L1 prices.
|
|
64
|
+
* Like `DEFAULT_MAX_FEE_PER_GAS`, it stops an absurd gas limit, from an endpoint's
|
|
65
|
+
* estimate or an override, not an expensive one: set the option to your own policy.
|
|
66
|
+
*/
|
|
67
|
+
export declare const DEFAULT_MAX_GAS_LIMIT = 16777216n;
|
|
68
|
+
/**
|
|
69
|
+
* Refuses, before anything is signed, a gas limit above `bound` (the handle's
|
|
70
|
+
* `maxGasLimit`), whatever produced it: the node's estimate with its headroom, an
|
|
71
|
+
* override's `gasLimit`, a stored fee, or a replacement that keeps its original's. It is
|
|
72
|
+
* never clamped: a lower limit than the call needs runs out of gas and still pays. The
|
|
73
|
+
* details carry the gas limit and the bound as decimal strings.
|
|
74
|
+
*/
|
|
75
|
+
export declare function assertWithinGasLimit(gasLimit: bigint, bound: bigint): void;
|
|
58
76
|
/** Validates an `EvmFeeOverride` against the network's fee model. */
|
|
59
77
|
export declare function parseFeeOverride(override: FeeOverride, model: EvmFeeModel): {
|
|
60
78
|
readonly params: EvmFeeParams;
|
|
@@ -64,12 +82,18 @@ export declare function parseFeeOverride(override: FeeOverride, model: EvmFeeMod
|
|
|
64
82
|
export declare function feeDraft(speed: FeeSpeed | 'custom', gasLimit: bigint, params: EvmFeeParams, extra?: {
|
|
65
83
|
readonly baseFeePerGas?: bigint;
|
|
66
84
|
readonly l1Fee?: bigint;
|
|
85
|
+
readonly operatorFee?: bigint;
|
|
67
86
|
}): FeeEstimateDraft;
|
|
68
87
|
/** The gas limit and prices a fee draft's details hold. */
|
|
69
88
|
export declare function feeOf(details: Readonly<Record<string, unknown>>): {
|
|
70
89
|
readonly gasLimit: bigint;
|
|
71
90
|
readonly params: EvmFeeParams;
|
|
72
91
|
};
|
|
92
|
+
/**
|
|
93
|
+
* Orders two fee settings by what a txpool compares on replacement: the fee cap (or gas
|
|
94
|
+
* price), then the tip. A legacy gas price is compared as a fee cap and tip alike.
|
|
95
|
+
*/
|
|
96
|
+
export declare function comparePrices(a: EvmFeeParams, b: EvmFeeParams): number;
|
|
73
97
|
/**
|
|
74
98
|
* Whether `next` may replace `previous` under a txpool's `percent` price bump: each price
|
|
75
99
|
* strictly higher, and at least `percent` higher (geth), so a zero tip must still rise.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_MAX_FEE_PER_GAS = exports.TRANSFER_GAS = exports.FEE_PERCENTILES = exports.FEE_HISTORY_BLOCKS = void 0;
|
|
3
|
+
exports.DEFAULT_MAX_GAS_LIMIT = exports.DEFAULT_MAX_FEE_PER_GAS = exports.TRANSFER_GAS = exports.FEE_PERCENTILES = exports.FEE_HISTORY_BLOCKS = void 0;
|
|
4
4
|
exports.median = median;
|
|
5
5
|
exports.feesFromHistory = feesFromHistory;
|
|
6
6
|
exports.legacyPrice = legacyPrice;
|
|
@@ -8,9 +8,11 @@ exports.gasLimitFrom = gasLimitFrom;
|
|
|
8
8
|
exports.priceCap = priceCap;
|
|
9
9
|
exports.capPrice = capPrice;
|
|
10
10
|
exports.assertWithinCeiling = assertWithinCeiling;
|
|
11
|
+
exports.assertWithinGasLimit = assertWithinGasLimit;
|
|
11
12
|
exports.parseFeeOverride = parseFeeOverride;
|
|
12
13
|
exports.feeDraft = feeDraft;
|
|
13
14
|
exports.feeOf = feeOf;
|
|
15
|
+
exports.comparePrices = comparePrices;
|
|
14
16
|
exports.meetsBump = meetsBump;
|
|
15
17
|
exports.minimumBump = minimumBump;
|
|
16
18
|
/**
|
|
@@ -123,6 +125,28 @@ function assertWithinCeiling(params, ceiling) {
|
|
|
123
125
|
return;
|
|
124
126
|
throw new error_1.ValidationError('INVALID_INTENT', 'the fee is above maxFeePerGas, the EVM handle option that bounds it (wei per gas)', { details: { required: price.toString(), maxFeePerGas: ceiling.toString() } });
|
|
125
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* The default `maxGasLimit`, the highest gas limit an EVM transaction signs: 16,777,216
|
|
130
|
+
* (2^24), the per-transaction cap Ethereum enforces since Fusaka (EIP-7825), so no
|
|
131
|
+
* transaction above it is included there. A transfer this driver builds needs a small
|
|
132
|
+
* fraction of it (21,000 gas for a plain transfer, tens of thousands for a token's); an
|
|
133
|
+
* Arbitrum estimate also counts the L1 data fee in L2 gas, so it grows with L1 prices.
|
|
134
|
+
* Like `DEFAULT_MAX_FEE_PER_GAS`, it stops an absurd gas limit, from an endpoint's
|
|
135
|
+
* estimate or an override, not an expensive one: set the option to your own policy.
|
|
136
|
+
*/
|
|
137
|
+
exports.DEFAULT_MAX_GAS_LIMIT = 16777216n;
|
|
138
|
+
/**
|
|
139
|
+
* Refuses, before anything is signed, a gas limit above `bound` (the handle's
|
|
140
|
+
* `maxGasLimit`), whatever produced it: the node's estimate with its headroom, an
|
|
141
|
+
* override's `gasLimit`, a stored fee, or a replacement that keeps its original's. It is
|
|
142
|
+
* never clamped: a lower limit than the call needs runs out of gas and still pays. The
|
|
143
|
+
* details carry the gas limit and the bound as decimal strings.
|
|
144
|
+
*/
|
|
145
|
+
function assertWithinGasLimit(gasLimit, bound) {
|
|
146
|
+
if (gasLimit <= bound)
|
|
147
|
+
return;
|
|
148
|
+
throw new error_1.ValidationError('INVALID_INTENT', 'the gas limit is above maxGasLimit, the EVM handle option that bounds it (gas)', { details: { required: gasLimit.toString(), maxGasLimit: bound.toString() } });
|
|
149
|
+
}
|
|
126
150
|
/** Validates an `EvmFeeOverride` against the network's fee model. */
|
|
127
151
|
function parseFeeOverride(override, model) {
|
|
128
152
|
const allowed = model === 'evm-1559'
|
|
@@ -173,7 +197,8 @@ function feeDraft(speed, gasLimit, params, extra = {}) {
|
|
|
173
197
|
}
|
|
174
198
|
: { gasPrice: params.gasPrice }),
|
|
175
199
|
...(extra.l1Fee !== undefined ? { l1Fee: extra.l1Fee } : {}),
|
|
176
|
-
|
|
200
|
+
...(extra.operatorFee !== undefined ? { operatorFee: extra.operatorFee } : {}),
|
|
201
|
+
expected: gasLimit * expectedPrice + (extra.l1Fee ?? 0n) + (extra.operatorFee ?? 0n),
|
|
177
202
|
};
|
|
178
203
|
return {
|
|
179
204
|
kind: params.type === 'eip1559' ? 'evm-1559' : 'evm-legacy',
|
|
@@ -183,9 +208,13 @@ function feeDraft(speed, gasLimit, params, extra = {}) {
|
|
|
183
208
|
...(extra.l1Fee !== undefined
|
|
184
209
|
? [{ asset: 'native', amount: extra.l1Fee, label: 'l1-data' }]
|
|
185
210
|
: []),
|
|
211
|
+
...(extra.operatorFee !== undefined
|
|
212
|
+
? [{ asset: 'native', amount: extra.operatorFee, label: 'operator' }]
|
|
213
|
+
: []),
|
|
186
214
|
],
|
|
187
|
-
// The L1 data fee moves with L1 prices until inclusion,
|
|
188
|
-
|
|
215
|
+
// The L1 data fee moves with L1 prices until inclusion, and the operator fee with the
|
|
216
|
+
// chain's operator settings, so either is only expected.
|
|
217
|
+
bound: extra.l1Fee !== undefined || extra.operatorFee !== undefined ? 'expected' : 'upper',
|
|
189
218
|
details,
|
|
190
219
|
};
|
|
191
220
|
}
|
|
@@ -201,6 +230,20 @@ function feeOf(details) {
|
|
|
201
230
|
return { gasLimit, params: { type: 'legacy', gasPrice } };
|
|
202
231
|
throw invalid('the fee holds no EVM gas prices');
|
|
203
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Orders two fee settings by what a txpool compares on replacement: the fee cap (or gas
|
|
235
|
+
* price), then the tip. A legacy gas price is compared as a fee cap and tip alike.
|
|
236
|
+
*/
|
|
237
|
+
function comparePrices(a, b) {
|
|
238
|
+
const pair = (p) => p.type === 'eip1559'
|
|
239
|
+
? [p.maxFeePerGas, p.maxPriorityFeePerGas]
|
|
240
|
+
: [p.gasPrice, p.gasPrice];
|
|
241
|
+
const [capA, tipA] = pair(a);
|
|
242
|
+
const [capB, tipB] = pair(b);
|
|
243
|
+
if (capA !== capB)
|
|
244
|
+
return capA < capB ? -1 : 1;
|
|
245
|
+
return tipA === tipB ? 0 : tipA < tipB ? -1 : 1;
|
|
246
|
+
}
|
|
204
247
|
/**
|
|
205
248
|
* Whether `next` may replace `previous` under a txpool's `percent` price bump: each price
|
|
206
249
|
* strictly higher, and at least `percent` higher (geth), so a zero tip must still rise.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fees.js","sourceRoot":"","sources":["../../../src/adapters/evm/fees.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The EVM fee policy: `evm-1559` or `evm-legacy` per network, an `upper`\n * bound with the `expected` cost in the details, overrides, and replacement bumps. Pure\n * functions over plain data; the driver does the I/O.\n */\nimport { ProviderError, ValidationError } from '../../core/errors/error';\nimport type { FeeEstimateDraft, FeeOverride, FeeSpeed } from '../../core/model/fee';\nimport type { EvmFeeDetails, EvmFeeHistory } from './types';\n\nexport type EvmFeeModel = 'evm-1559' | 'evm-legacy';\n\n/** The per-gas prices of one transaction. */\nexport type EvmFeeParams =\n | {\n readonly type: 'eip1559';\n readonly maxFeePerGas: bigint;\n readonly maxPriorityFeePerGas: bigint;\n }\n | { readonly type: 'legacy'; readonly gasPrice: bigint };\n\n/**\n * `eth_feeHistory` window and priority-fee percentiles for slow, normal and fast: the\n * method the Polygon Gas Station documents (10th, 25th and 50th over the last 15 blocks).\n */\nexport const FEE_HISTORY_BLOCKS = 15;\nexport const FEE_PERCENTILES: readonly number[] = [10, 25, 50];\nconst SPEED_INDEX: Readonly<Record<FeeSpeed, number>> = { slow: 0, normal: 1, fast: 2 };\n/** Legacy networks: `eth_gasPrice` scaled per speed, in percent. */\nconst LEGACY_PERCENT: Readonly<Record<FeeSpeed, bigint>> = {\n slow: 100n,\n normal: 110n,\n fast: 125n,\n};\n/** A plain transfer to an account without code costs exactly this much gas. */\nexport const TRANSFER_GAS = 21_000n;\n/** Headroom over the node's estimate for anything but a plain transfer, in percent. */\nconst GAS_HEADROOM_PERCENT = 120n;\n\nconst ceilDiv = (a: bigint, b: bigint): bigint => (a + b - 1n) / b;\nconst max = (a: bigint, b: bigint): bigint => (a > b ? a : b);\nconst min = (a: bigint, b: bigint): bigint => (a < b ? a : b);\n\n/** The lower median; `0n` for no values. */\nexport function median(values: readonly bigint[]): bigint {\n if (values.length === 0) return 0n;\n const sorted = [...values].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n return sorted[Math.floor((sorted.length - 1) / 2)] as bigint;\n}\n\nconst malformedHistory = () =>\n new ProviderError('PROVIDER_UNAVAILABLE', 'malformed fee history');\n\n/**\n * EIP-1559 prices for `speed`: the tip is the median, over the window, of the speed's\n * percentile (at least `minTip`); the cap allows the next base fee to double. The history\n * must answer a request for `FEE_PERCENTILES`: one without the next base fee, without\n * reward rows, or with a reward row shorter than `FEE_PERCENTILES` is a retryable\n * `PROVIDER_UNAVAILABLE`, never a tip of `minTip`.\n */\nexport function feesFromHistory(\n history: EvmFeeHistory,\n speed: FeeSpeed,\n minTip: bigint,\n): { readonly params: EvmFeeParams; readonly baseFeePerGas: bigint } {\n const baseFeePerGas = history.baseFeePerGas[history.baseFeePerGas.length - 1];\n if (baseFeePerGas === undefined || history.reward.length === 0) {\n throw malformedHistory();\n }\n const index = SPEED_INDEX[speed];\n const tips = history.reward.map((row) => {\n const tip = row[index];\n if (row.length < FEE_PERCENTILES.length || tip === undefined)\n throw malformedHistory();\n return tip;\n });\n const tip = max(median(tips), minTip);\n return {\n params: {\n type: 'eip1559',\n maxFeePerGas: 2n * baseFeePerGas + tip,\n maxPriorityFeePerGas: tip,\n },\n baseFeePerGas,\n };\n}\n\nexport function legacyPrice(gasPrice: bigint, speed: FeeSpeed): EvmFeeParams {\n return { type: 'legacy', gasPrice: ceilDiv(gasPrice * LEGACY_PERCENT[speed], 100n) };\n}\n\n/** The node's estimate, with headroom unless it is a plain transfer. */\nexport function gasLimitFrom(estimate: bigint): bigint {\n return estimate === TRANSFER_GAS\n ? TRANSFER_GAS\n : ceilDiv(estimate * GAS_HEADROOM_PERCENT, 100n);\n}\n\nconst invalid = (reason: string) => new ValidationError('INVALID_INTENT', reason);\n\n/**\n * The default `maxFeePerGas`, the highest price per gas an EVM transaction signs, 1,000\n * gwei. It bounds a plain transfer at 0.021 and a 65,000-gas token transfer at 0.065 of\n * the native coin, however an endpoint prices the fee. A network whose base fee rises\n * above the ceiling stalls its transfers as `FEE_TOO_LOW` until the fee falls or the\n * option is raised.\n */\nexport const DEFAULT_MAX_FEE_PER_GAS = 1_000_000_000_000n;\n\n/** The highest price per gas `params` may pay: the fee cap, or the legacy gas price. */\nexport function priceCap(params: EvmFeeParams): bigint {\n return params.type === 'eip1559' ? params.maxFeePerGas : params.gasPrice;\n}\n\n/**\n * A node's suggestion within the ceiling: the fee cap or gas price at most `ceiling`,\n * and the tip at most the fee cap. No endpoint can raise what a transfer signs.\n */\nexport function capPrice(params: EvmFeeParams, ceiling: bigint): EvmFeeParams {\n if (params.type === 'legacy')\n return { type: 'legacy', gasPrice: min(params.gasPrice, ceiling) };\n const maxFeePerGas = min(params.maxFeePerGas, ceiling);\n return {\n type: 'eip1559',\n maxFeePerGas,\n maxPriorityFeePerGas: min(params.maxPriorityFeePerGas, maxFeePerGas),\n };\n}\n\n/**\n * Refuses, before anything is signed, a fee whose price per gas is above `ceiling` (the\n * handle's `maxFeePerGas`), whatever produced it: an explicit override, a stored fee, or a\n * cancel's least bump. The details carry the price and the bound as decimal strings.\n */\nexport function assertWithinCeiling(params: EvmFeeParams, ceiling: bigint): void {\n const price = priceCap(params);\n if (price <= ceiling) return;\n throw new ValidationError(\n 'INVALID_INTENT',\n 'the fee is above maxFeePerGas, the EVM handle option that bounds it (wei per gas)',\n { details: { required: price.toString(), maxFeePerGas: ceiling.toString() } },\n );\n}\n\n/** Validates an `EvmFeeOverride` against the network's fee model. */\nexport function parseFeeOverride(\n override: FeeOverride,\n model: EvmFeeModel,\n): { readonly params: EvmFeeParams; readonly gasLimit?: bigint } {\n const allowed =\n model === 'evm-1559'\n ? ['maxFeePerGas', 'maxPriorityFeePerGas', 'gasLimit']\n : ['gasPrice', 'gasLimit'];\n const shape =\n model === 'evm-1559'\n ? '{ maxFeePerGas, maxPriorityFeePerGas, gasLimit? }'\n : '{ gasPrice, gasLimit? }';\n const keys = Object.keys(override);\n if (keys.some((key) => !allowed.includes(key))) {\n throw invalid(`${model} fee overrides look like ${shape}`);\n }\n const amount = (key: string, min: bigint): bigint => {\n const value = override[key];\n if (typeof value !== 'bigint' || value < min) {\n throw invalid(`fee override '${key}' must be a bigint of at least ${min}`);\n }\n return value;\n };\n const gasLimit =\n override.gasLimit === undefined ? undefined : amount('gasLimit', TRANSFER_GAS);\n const limit = gasLimit !== undefined ? { gasLimit } : {};\n if (model === 'evm-legacy') {\n return { params: { type: 'legacy', gasPrice: amount('gasPrice', 1n) }, ...limit };\n }\n const maxFeePerGas = amount('maxFeePerGas', 1n);\n const maxPriorityFeePerGas = amount('maxPriorityFeePerGas', 0n);\n if (maxPriorityFeePerGas > maxFeePerGas) {\n throw invalid('maxPriorityFeePerGas must not exceed maxFeePerGas');\n }\n return { params: { type: 'eip1559', maxFeePerGas, maxPriorityFeePerGas }, ...limit };\n}\n\n/** The fee draft for a transaction of `gasLimit` at `params`. */\nexport function feeDraft(\n speed: FeeSpeed | 'custom',\n gasLimit: bigint,\n params: EvmFeeParams,\n extra: { readonly baseFeePerGas?: bigint; readonly l1Fee?: bigint } = {},\n): FeeEstimateDraft {\n const cap = params.type === 'eip1559' ? params.maxFeePerGas : params.gasPrice;\n const expectedPrice =\n params.type === 'eip1559' && extra.baseFeePerGas !== undefined\n ? min(params.maxFeePerGas, extra.baseFeePerGas + params.maxPriorityFeePerGas)\n : cap;\n // `satisfies` checks the shape and keeps a literal type the draft's record accepts.\n const details = {\n gasLimit,\n ...(params.type === 'eip1559'\n ? {\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n ...(extra.baseFeePerGas !== undefined\n ? { baseFeePerGas: extra.baseFeePerGas }\n : {}),\n }\n : { gasPrice: params.gasPrice }),\n ...(extra.l1Fee !== undefined ? { l1Fee: extra.l1Fee } : {}),\n expected: gasLimit * expectedPrice + (extra.l1Fee ?? 0n),\n } satisfies EvmFeeDetails;\n return {\n kind: params.type === 'eip1559' ? 'evm-1559' : 'evm-legacy',\n speed,\n charges: [\n { asset: 'native', amount: gasLimit * cap, label: 'network' },\n ...(extra.l1Fee !== undefined\n ? [{ asset: 'native' as const, amount: extra.l1Fee, label: 'l1-data' }]\n : []),\n ],\n // The L1 data fee moves with L1 prices until inclusion, so it is only expected.\n bound: extra.l1Fee !== undefined ? 'expected' : 'upper',\n details,\n };\n}\n\n/** The gas limit and prices a fee draft's details hold. */\nexport function feeOf(details: Readonly<Record<string, unknown>>): {\n readonly gasLimit: bigint;\n readonly params: EvmFeeParams;\n} {\n const { gasLimit, maxFeePerGas, maxPriorityFeePerGas, gasPrice } = details;\n if (typeof gasLimit !== 'bigint') throw invalid('the fee holds no EVM gas limit');\n if (typeof maxFeePerGas === 'bigint' && typeof maxPriorityFeePerGas === 'bigint') {\n return { gasLimit, params: { type: 'eip1559', maxFeePerGas, maxPriorityFeePerGas } };\n }\n if (typeof gasPrice === 'bigint')\n return { gasLimit, params: { type: 'legacy', gasPrice } };\n throw invalid('the fee holds no EVM gas prices');\n}\n\n/**\n * Whether `next` may replace `previous` under a txpool's `percent` price bump: each price\n * strictly higher, and at least `percent` higher (geth), so a zero tip must still rise.\n */\nexport function meetsBump(\n previous: EvmFeeParams,\n next: EvmFeeParams,\n percent: number,\n): boolean {\n const factor = BigInt(100 + percent);\n const bumped = (before: bigint, after: bigint) =>\n after > before && after * 100n >= before * factor;\n if (previous.type === 'eip1559' && next.type === 'eip1559') {\n return (\n bumped(previous.maxFeePerGas, next.maxFeePerGas) &&\n bumped(previous.maxPriorityFeePerGas, next.maxPriorityFeePerGas)\n );\n }\n if (previous.type === 'legacy' && next.type === 'legacy') {\n return bumped(previous.gasPrice, next.gasPrice);\n }\n return false;\n}\n\n/** The smallest prices that meet the bump over `previous`: each strictly higher (geth). */\nexport function minimumBump(previous: EvmFeeParams, percent: number): EvmFeeParams {\n const up = (value: bigint) => {\n const bumped = ceilDiv(value * BigInt(100 + percent), 100n);\n return bumped > value ? bumped : value + 1n;\n };\n return previous.type === 'eip1559'\n ? {\n type: 'eip1559',\n maxFeePerGas: up(previous.maxFeePerGas),\n maxPriorityFeePerGas: up(previous.maxPriorityFeePerGas),\n }\n : { type: 'legacy', gasPrice: up(previous.gasPrice) };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fees.js","sourceRoot":"","sources":["../../../src/adapters/evm/fees.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The EVM fee policy: `evm-1559` or `evm-legacy` per network, an `upper`\n * bound with the `expected` cost in the details, overrides, and replacement bumps. Pure\n * functions over plain data; the driver does the I/O.\n */\nimport { ProviderError, ValidationError } from '../../core/errors/error';\nimport type { FeeEstimateDraft, FeeOverride, FeeSpeed } from '../../core/model/fee';\nimport type { EvmFeeDetails, EvmFeeHistory } from './types';\n\nexport type EvmFeeModel = 'evm-1559' | 'evm-legacy';\n\n/** The per-gas prices of one transaction. */\nexport type EvmFeeParams =\n | {\n readonly type: 'eip1559';\n readonly maxFeePerGas: bigint;\n readonly maxPriorityFeePerGas: bigint;\n }\n | { readonly type: 'legacy'; readonly gasPrice: bigint };\n\n/**\n * `eth_feeHistory` window and priority-fee percentiles for slow, normal and fast: the\n * method the Polygon Gas Station documents (10th, 25th and 50th over the last 15 blocks).\n */\nexport const FEE_HISTORY_BLOCKS = 15;\nexport const FEE_PERCENTILES: readonly number[] = [10, 25, 50];\nconst SPEED_INDEX: Readonly<Record<FeeSpeed, number>> = { slow: 0, normal: 1, fast: 2 };\n/** Legacy networks: `eth_gasPrice` scaled per speed, in percent. */\nconst LEGACY_PERCENT: Readonly<Record<FeeSpeed, bigint>> = {\n slow: 100n,\n normal: 110n,\n fast: 125n,\n};\n/** A plain transfer to an account without code costs exactly this much gas. */\nexport const TRANSFER_GAS = 21_000n;\n/** Headroom over the node's estimate for anything but a plain transfer, in percent. */\nconst GAS_HEADROOM_PERCENT = 120n;\n\nconst ceilDiv = (a: bigint, b: bigint): bigint => (a + b - 1n) / b;\nconst max = (a: bigint, b: bigint): bigint => (a > b ? a : b);\nconst min = (a: bigint, b: bigint): bigint => (a < b ? a : b);\n\n/** The lower median; `0n` for no values. */\nexport function median(values: readonly bigint[]): bigint {\n if (values.length === 0) return 0n;\n const sorted = [...values].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n return sorted[Math.floor((sorted.length - 1) / 2)] as bigint;\n}\n\nconst malformedHistory = () =>\n new ProviderError('PROVIDER_UNAVAILABLE', 'malformed fee history');\n\n/**\n * EIP-1559 prices for `speed`: the tip is the median, over the window, of the speed's\n * percentile (at least `minTip`); the cap allows the next base fee to double. The history\n * must answer a request for `FEE_PERCENTILES`: one without the next base fee, without\n * reward rows, or with a reward row shorter than `FEE_PERCENTILES` is a retryable\n * `PROVIDER_UNAVAILABLE`, never a tip of `minTip`.\n */\nexport function feesFromHistory(\n history: EvmFeeHistory,\n speed: FeeSpeed,\n minTip: bigint,\n): { readonly params: EvmFeeParams; readonly baseFeePerGas: bigint } {\n const baseFeePerGas = history.baseFeePerGas[history.baseFeePerGas.length - 1];\n if (baseFeePerGas === undefined || history.reward.length === 0) {\n throw malformedHistory();\n }\n const index = SPEED_INDEX[speed];\n const tips = history.reward.map((row) => {\n const tip = row[index];\n if (row.length < FEE_PERCENTILES.length || tip === undefined)\n throw malformedHistory();\n return tip;\n });\n const tip = max(median(tips), minTip);\n return {\n params: {\n type: 'eip1559',\n maxFeePerGas: 2n * baseFeePerGas + tip,\n maxPriorityFeePerGas: tip,\n },\n baseFeePerGas,\n };\n}\n\nexport function legacyPrice(gasPrice: bigint, speed: FeeSpeed): EvmFeeParams {\n return { type: 'legacy', gasPrice: ceilDiv(gasPrice * LEGACY_PERCENT[speed], 100n) };\n}\n\n/** The node's estimate, with headroom unless it is a plain transfer. */\nexport function gasLimitFrom(estimate: bigint): bigint {\n return estimate === TRANSFER_GAS\n ? TRANSFER_GAS\n : ceilDiv(estimate * GAS_HEADROOM_PERCENT, 100n);\n}\n\nconst invalid = (reason: string) => new ValidationError('INVALID_INTENT', reason);\n\n/**\n * The default `maxFeePerGas`, the highest price per gas an EVM transaction signs, 1,000\n * gwei. It bounds a plain transfer at 0.021 and a 65,000-gas token transfer at 0.065 of\n * the native coin, however an endpoint prices the fee. A network whose base fee rises\n * above the ceiling stalls its transfers as `FEE_TOO_LOW` until the fee falls or the\n * option is raised.\n */\nexport const DEFAULT_MAX_FEE_PER_GAS = 1_000_000_000_000n;\n\n/** The highest price per gas `params` may pay: the fee cap, or the legacy gas price. */\nexport function priceCap(params: EvmFeeParams): bigint {\n return params.type === 'eip1559' ? params.maxFeePerGas : params.gasPrice;\n}\n\n/**\n * A node's suggestion within the ceiling: the fee cap or gas price at most `ceiling`,\n * and the tip at most the fee cap. No endpoint can raise what a transfer signs.\n */\nexport function capPrice(params: EvmFeeParams, ceiling: bigint): EvmFeeParams {\n if (params.type === 'legacy')\n return { type: 'legacy', gasPrice: min(params.gasPrice, ceiling) };\n const maxFeePerGas = min(params.maxFeePerGas, ceiling);\n return {\n type: 'eip1559',\n maxFeePerGas,\n maxPriorityFeePerGas: min(params.maxPriorityFeePerGas, maxFeePerGas),\n };\n}\n\n/**\n * Refuses, before anything is signed, a fee whose price per gas is above `ceiling` (the\n * handle's `maxFeePerGas`), whatever produced it: an explicit override, a stored fee, or a\n * cancel's least bump. The details carry the price and the bound as decimal strings.\n */\nexport function assertWithinCeiling(params: EvmFeeParams, ceiling: bigint): void {\n const price = priceCap(params);\n if (price <= ceiling) return;\n throw new ValidationError(\n 'INVALID_INTENT',\n 'the fee is above maxFeePerGas, the EVM handle option that bounds it (wei per gas)',\n { details: { required: price.toString(), maxFeePerGas: ceiling.toString() } },\n );\n}\n\n/**\n * The default `maxGasLimit`, the highest gas limit an EVM transaction signs: 16,777,216\n * (2^24), the per-transaction cap Ethereum enforces since Fusaka (EIP-7825), so no\n * transaction above it is included there. A transfer this driver builds needs a small\n * fraction of it (21,000 gas for a plain transfer, tens of thousands for a token's); an\n * Arbitrum estimate also counts the L1 data fee in L2 gas, so it grows with L1 prices.\n * Like `DEFAULT_MAX_FEE_PER_GAS`, it stops an absurd gas limit, from an endpoint's\n * estimate or an override, not an expensive one: set the option to your own policy.\n */\nexport const DEFAULT_MAX_GAS_LIMIT = 16_777_216n;\n\n/**\n * Refuses, before anything is signed, a gas limit above `bound` (the handle's\n * `maxGasLimit`), whatever produced it: the node's estimate with its headroom, an\n * override's `gasLimit`, a stored fee, or a replacement that keeps its original's. It is\n * never clamped: a lower limit than the call needs runs out of gas and still pays. The\n * details carry the gas limit and the bound as decimal strings.\n */\nexport function assertWithinGasLimit(gasLimit: bigint, bound: bigint): void {\n if (gasLimit <= bound) return;\n throw new ValidationError(\n 'INVALID_INTENT',\n 'the gas limit is above maxGasLimit, the EVM handle option that bounds it (gas)',\n { details: { required: gasLimit.toString(), maxGasLimit: bound.toString() } },\n );\n}\n\n/** Validates an `EvmFeeOverride` against the network's fee model. */\nexport function parseFeeOverride(\n override: FeeOverride,\n model: EvmFeeModel,\n): { readonly params: EvmFeeParams; readonly gasLimit?: bigint } {\n const allowed =\n model === 'evm-1559'\n ? ['maxFeePerGas', 'maxPriorityFeePerGas', 'gasLimit']\n : ['gasPrice', 'gasLimit'];\n const shape =\n model === 'evm-1559'\n ? '{ maxFeePerGas, maxPriorityFeePerGas, gasLimit? }'\n : '{ gasPrice, gasLimit? }';\n const keys = Object.keys(override);\n if (keys.some((key) => !allowed.includes(key))) {\n throw invalid(`${model} fee overrides look like ${shape}`);\n }\n const amount = (key: string, min: bigint): bigint => {\n const value = override[key];\n if (typeof value !== 'bigint' || value < min) {\n throw invalid(`fee override '${key}' must be a bigint of at least ${min}`);\n }\n return value;\n };\n const gasLimit =\n override.gasLimit === undefined ? undefined : amount('gasLimit', TRANSFER_GAS);\n const limit = gasLimit !== undefined ? { gasLimit } : {};\n if (model === 'evm-legacy') {\n return { params: { type: 'legacy', gasPrice: amount('gasPrice', 1n) }, ...limit };\n }\n const maxFeePerGas = amount('maxFeePerGas', 1n);\n const maxPriorityFeePerGas = amount('maxPriorityFeePerGas', 0n);\n if (maxPriorityFeePerGas > maxFeePerGas) {\n throw invalid('maxPriorityFeePerGas must not exceed maxFeePerGas');\n }\n return { params: { type: 'eip1559', maxFeePerGas, maxPriorityFeePerGas }, ...limit };\n}\n\n/** The fee draft for a transaction of `gasLimit` at `params`. */\nexport function feeDraft(\n speed: FeeSpeed | 'custom',\n gasLimit: bigint,\n params: EvmFeeParams,\n extra: {\n readonly baseFeePerGas?: bigint;\n readonly l1Fee?: bigint;\n readonly operatorFee?: bigint;\n } = {},\n): FeeEstimateDraft {\n const cap = params.type === 'eip1559' ? params.maxFeePerGas : params.gasPrice;\n const expectedPrice =\n params.type === 'eip1559' && extra.baseFeePerGas !== undefined\n ? min(params.maxFeePerGas, extra.baseFeePerGas + params.maxPriorityFeePerGas)\n : cap;\n // `satisfies` checks the shape and keeps a literal type the draft's record accepts.\n const details = {\n gasLimit,\n ...(params.type === 'eip1559'\n ? {\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n ...(extra.baseFeePerGas !== undefined\n ? { baseFeePerGas: extra.baseFeePerGas }\n : {}),\n }\n : { gasPrice: params.gasPrice }),\n ...(extra.l1Fee !== undefined ? { l1Fee: extra.l1Fee } : {}),\n ...(extra.operatorFee !== undefined ? { operatorFee: extra.operatorFee } : {}),\n expected: gasLimit * expectedPrice + (extra.l1Fee ?? 0n) + (extra.operatorFee ?? 0n),\n } satisfies EvmFeeDetails;\n return {\n kind: params.type === 'eip1559' ? 'evm-1559' : 'evm-legacy',\n speed,\n charges: [\n { asset: 'native', amount: gasLimit * cap, label: 'network' },\n ...(extra.l1Fee !== undefined\n ? [{ asset: 'native' as const, amount: extra.l1Fee, label: 'l1-data' }]\n : []),\n ...(extra.operatorFee !== undefined\n ? [{ asset: 'native' as const, amount: extra.operatorFee, label: 'operator' }]\n : []),\n ],\n // The L1 data fee moves with L1 prices until inclusion, and the operator fee with the\n // chain's operator settings, so either is only expected.\n bound:\n extra.l1Fee !== undefined || extra.operatorFee !== undefined ? 'expected' : 'upper',\n details,\n };\n}\n\n/** The gas limit and prices a fee draft's details hold. */\nexport function feeOf(details: Readonly<Record<string, unknown>>): {\n readonly gasLimit: bigint;\n readonly params: EvmFeeParams;\n} {\n const { gasLimit, maxFeePerGas, maxPriorityFeePerGas, gasPrice } = details;\n if (typeof gasLimit !== 'bigint') throw invalid('the fee holds no EVM gas limit');\n if (typeof maxFeePerGas === 'bigint' && typeof maxPriorityFeePerGas === 'bigint') {\n return { gasLimit, params: { type: 'eip1559', maxFeePerGas, maxPriorityFeePerGas } };\n }\n if (typeof gasPrice === 'bigint')\n return { gasLimit, params: { type: 'legacy', gasPrice } };\n throw invalid('the fee holds no EVM gas prices');\n}\n\n/**\n * Orders two fee settings by what a txpool compares on replacement: the fee cap (or gas\n * price), then the tip. A legacy gas price is compared as a fee cap and tip alike.\n */\nexport function comparePrices(a: EvmFeeParams, b: EvmFeeParams): number {\n const pair = (p: EvmFeeParams): readonly [bigint, bigint] =>\n p.type === 'eip1559'\n ? [p.maxFeePerGas, p.maxPriorityFeePerGas]\n : [p.gasPrice, p.gasPrice];\n const [capA, tipA] = pair(a);\n const [capB, tipB] = pair(b);\n if (capA !== capB) return capA < capB ? -1 : 1;\n return tipA === tipB ? 0 : tipA < tipB ? -1 : 1;\n}\n\n/**\n * Whether `next` may replace `previous` under a txpool's `percent` price bump: each price\n * strictly higher, and at least `percent` higher (geth), so a zero tip must still rise.\n */\nexport function meetsBump(\n previous: EvmFeeParams,\n next: EvmFeeParams,\n percent: number,\n): boolean {\n const factor = BigInt(100 + percent);\n const bumped = (before: bigint, after: bigint) =>\n after > before && after * 100n >= before * factor;\n if (previous.type === 'eip1559' && next.type === 'eip1559') {\n return (\n bumped(previous.maxFeePerGas, next.maxFeePerGas) &&\n bumped(previous.maxPriorityFeePerGas, next.maxPriorityFeePerGas)\n );\n }\n if (previous.type === 'legacy' && next.type === 'legacy') {\n return bumped(previous.gasPrice, next.gasPrice);\n }\n return false;\n}\n\n/** The smallest prices that meet the bump over `previous`: each strictly higher (geth). */\nexport function minimumBump(previous: EvmFeeParams, percent: number): EvmFeeParams {\n const up = (value: bigint) => {\n const bumped = ceilDiv(value * BigInt(100 + percent), 100n);\n return bumped > value ? bumped : value + 1n;\n };\n return previous.type === 'eip1559'\n ? {\n type: 'eip1559',\n maxFeePerGas: up(previous.maxFeePerGas),\n maxPriorityFeePerGas: up(previous.maxPriorityFeePerGas),\n }\n : { type: 'legacy', gasPrice: up(previous.gasPrice) };\n}\n"]}
|
|
@@ -15,6 +15,6 @@ declare module '../../index' {
|
|
|
15
15
|
}
|
|
16
16
|
export { EVM_PEER_DEPENDENCIES, evmChainPlugin } from './plugin';
|
|
17
17
|
export type { EvmChainPluginOptions } from './plugin';
|
|
18
|
-
export { DEFAULT_MAX_FEE_PER_GAS } from './fees';
|
|
18
|
+
export { DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_GAS_LIMIT } from './fees';
|
|
19
19
|
export { EVM_CAPABILITIES } from './network';
|
|
20
20
|
export type { EvmExt, EvmFeeDetails, EvmFeeOverride } from './types';
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EVM_CAPABILITIES = exports.DEFAULT_MAX_FEE_PER_GAS = exports.evmChainPlugin = exports.EVM_PEER_DEPENDENCIES = void 0;
|
|
3
|
+
exports.EVM_CAPABILITIES = exports.DEFAULT_MAX_GAS_LIMIT = exports.DEFAULT_MAX_FEE_PER_GAS = exports.evmChainPlugin = exports.EVM_PEER_DEPENDENCIES = void 0;
|
|
4
4
|
var plugin_1 = require("./plugin");
|
|
5
5
|
Object.defineProperty(exports, "EVM_PEER_DEPENDENCIES", { enumerable: true, get: function () { return plugin_1.EVM_PEER_DEPENDENCIES; } });
|
|
6
6
|
Object.defineProperty(exports, "evmChainPlugin", { enumerable: true, get: function () { return plugin_1.evmChainPlugin; } });
|
|
7
7
|
var fees_1 = require("./fees");
|
|
8
8
|
Object.defineProperty(exports, "DEFAULT_MAX_FEE_PER_GAS", { enumerable: true, get: function () { return fees_1.DEFAULT_MAX_FEE_PER_GAS; } });
|
|
9
|
+
Object.defineProperty(exports, "DEFAULT_MAX_GAS_LIMIT", { enumerable: true, get: function () { return fees_1.DEFAULT_MAX_GAS_LIMIT; } });
|
|
9
10
|
var network_1 = require("./network");
|
|
10
11
|
Object.defineProperty(exports, "EVM_CAPABILITIES", { enumerable: true, get: function () { return network_1.EVM_CAPABILITIES; } });
|
|
11
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/evm/index.ts"],"names":[],"mappings":";;;AAmBA,mCAAiE;AAAxD,+GAAA,qBAAqB,OAAA;AAAE,wGAAA,cAAc,OAAA;AAE9C,+
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/evm/index.ts"],"names":[],"mappings":";;;AAmBA,mCAAiE;AAAxD,+GAAA,qBAAqB,OAAA;AAAE,wGAAA,cAAc,OAAA;AAE9C,+BAAwE;AAA/D,+GAAA,uBAAuB,OAAA;AAAE,6GAAA,qBAAqB,OAAA;AACvD,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA","sourcesContent":["/**\n * `crypto-aio/evm`: EVM chains of your own (`evmChainPlugin`), the SDK-free EVM types, and\n * the `crypto-aio/native` client types: importing this entry types `native(bc, 'ethers')`\n * as an ethers `JsonRpcApiProvider` and `native(bc, 'web3')` as a `Web3` instance.\n *\n * @module crypto-aio/evm\n */\nimport type { JsonRpcApiProvider } from 'ethers';\nimport type { Web3 } from 'web3';\n\n// Through the package entry, never a core module. SDK types appear only here, in the\n// adapter's entry, so the main entry's typings name no SDK.\ndeclare module '../../index' {\n interface NativeClientMap {\n ethers: JsonRpcApiProvider;\n web3: Web3;\n }\n}\n\nexport { EVM_PEER_DEPENDENCIES, evmChainPlugin } from './plugin';\nexport type { EvmChainPluginOptions } from './plugin';\nexport { DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_GAS_LIMIT } from './fees';\nexport { EVM_CAPABILITIES } from './network';\nexport type { EvmExt, EvmFeeDetails, EvmFeeOverride } from './types';\n"]}
|
|
@@ -36,6 +36,11 @@ export interface EvmNetworkConfig {
|
|
|
36
36
|
* `DEFAULT_MAX_FEE_PER_GAS`.
|
|
37
37
|
*/
|
|
38
38
|
readonly maxFeePerGas: bigint;
|
|
39
|
+
/**
|
|
40
|
+
* The highest gas limit a transaction signs: the handle's `maxGasLimit` option, else the
|
|
41
|
+
* network's `params.maxGasLimit`, else `DEFAULT_MAX_GAS_LIMIT`.
|
|
42
|
+
*/
|
|
43
|
+
readonly maxGasLimit: bigint;
|
|
39
44
|
}
|
|
40
45
|
/** The OP Stack `GasPriceOracle` predeploy. */
|
|
41
46
|
export declare const GAS_PRICE_ORACLE = "0x420000000000000000000000000000000000000F";
|
|
@@ -16,12 +16,14 @@ exports.EVM_CAPABILITIES = [
|
|
|
16
16
|
'cancel',
|
|
17
17
|
];
|
|
18
18
|
/**
|
|
19
|
-
* The only driver
|
|
19
|
+
* The only driver options (`HandleOptions.options`) the EVM driver reads. Any other key is
|
|
20
20
|
* refused, so a typo, or another family's option such as Tron's `maxFeeLimit`, fails loudly
|
|
21
21
|
* instead of leaving the default in place.
|
|
22
22
|
*/
|
|
23
|
-
const OPTION_KEYS = Object.freeze(['maxFeePerGas']);
|
|
23
|
+
const OPTION_KEYS = Object.freeze(['maxFeePerGas', 'maxGasLimit']);
|
|
24
24
|
const MAX_UINT256 = 2n ** 256n - 1n;
|
|
25
|
+
/** The largest gas limit a transaction carries: clients read it as a `uint64`. */
|
|
26
|
+
const MAX_UINT64 = 2n ** 64n - 1n;
|
|
25
27
|
/** A price ceiling: a bigint of wei per gas that an EVM transaction can carry. */
|
|
26
28
|
function priceCeiling(value, name, fail) {
|
|
27
29
|
if (typeof value !== 'bigint' || value < 1n || value > MAX_UINT256) {
|
|
@@ -29,6 +31,16 @@ function priceCeiling(value, name, fail) {
|
|
|
29
31
|
}
|
|
30
32
|
return value;
|
|
31
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* A gas-limit bound: a bigint of gas a transaction can carry, and at least a plain
|
|
36
|
+
* transfer's 21,000, below which nothing could be signed.
|
|
37
|
+
*/
|
|
38
|
+
function gasBound(value, name, fail) {
|
|
39
|
+
if (typeof value !== 'bigint' || value < fees_1.TRANSFER_GAS || value > MAX_UINT64) {
|
|
40
|
+
fail(`${name} must be a bigint of gas from 21,000 to 2^64 − 1`);
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
32
44
|
/** The OP Stack `GasPriceOracle` predeploy. */
|
|
33
45
|
exports.GAS_PRICE_ORACLE = '0x420000000000000000000000000000000000000F';
|
|
34
46
|
/**
|
|
@@ -115,6 +127,12 @@ function evmNetworkConfig(chain, network, options = {}) {
|
|
|
115
127
|
const maxFeePerGas = options.maxFeePerGas !== undefined
|
|
116
128
|
? priceCeiling(options.maxFeePerGas, 'maxFeePerGas', fail)
|
|
117
129
|
: (networkCeiling ?? fees_1.DEFAULT_MAX_FEE_PER_GAS);
|
|
130
|
+
// The gas-limit bound resolves the same way.
|
|
131
|
+
const ownGas = params.maxGasLimit;
|
|
132
|
+
const networkGas = ownGas === undefined ? undefined : gasBound(ownGas, 'params.maxGasLimit', fail);
|
|
133
|
+
const maxGasLimit = options.maxGasLimit !== undefined
|
|
134
|
+
? gasBound(options.maxGasLimit, 'maxGasLimit', fail)
|
|
135
|
+
: (networkGas ?? fees_1.DEFAULT_MAX_GAS_LIMIT);
|
|
118
136
|
const replaces = capabilities.has('replace-fee') || capabilities.has('cancel');
|
|
119
137
|
return {
|
|
120
138
|
chainId: BigInt(network.identity),
|
|
@@ -126,6 +144,7 @@ function evmNetworkConfig(chain, network, options = {}) {
|
|
|
126
144
|
polygonSystemLogs: params.systemLogs === 'bor',
|
|
127
145
|
capabilities,
|
|
128
146
|
maxFeePerGas,
|
|
147
|
+
maxGasLimit,
|
|
129
148
|
};
|
|
130
149
|
}
|
|
131
150
|
//# sourceMappingURL=network.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../../src/adapters/evm/network.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What the EVM driver needs from a network's registry entry (each network keeps its own\n * registry identity, its decimal chain id), validated once when a driver is created, so a\n * custom EVM chain with inconsistent data fails with `CONFIG_INVALID` instead of\n * misbehaving.\n */\nimport type { Capability } from '../../core/model/capability';\nimport type { ChainInfo, FinalityPolicy, NetworkInfo } from '../../core/model/chain';\nimport { ConfigError } from '../../core/errors/error';\nimport { unknownName } from '../../core/util/names';\nimport { DEFAULT_MAX_FEE_PER_GAS, type EvmFeeModel } from './fees';\n\n/** Every capability an EVM network can have; a network removes what it lacks. */\nexport const EVM_CAPABILITIES: readonly Capability[] = [\n 'tokens',\n 'block-scan',\n 'hd-public-derivation',\n 'fee-market-1559',\n 'finality-tag',\n 'replace-fee',\n 'cancel',\n];\n\nexport type EvmFinality =\n | { readonly kind: 'tag' }\n | { readonly kind: 'confirmations'; readonly confirmations: number };\n\nexport interface EvmNetworkConfig {\n readonly chainId: bigint;\n readonly feeModel: EvmFeeModel;\n readonly finality: EvmFinality;\n /** The txpool's price bump; `undefined` when the network has no replace or cancel. */\n readonly minBumpPercent?: number;\n readonly minPriorityFeePerGas: bigint;\n /** OP Stack: transactions also pay an L1 data fee (`GasPriceOracle.getL1Fee`). */\n readonly l1DataFee: boolean;\n /**\n * bor-based networks (`params.systemLogs: 'bor'`, as on Polygon PoS): receipts carry bor's\n * `POLYGON_FEE_LOG` and `POLYGON_TRANSFER_LOG`.\n */\n readonly polygonSystemLogs: boolean;\n readonly capabilities: ReadonlySet<Capability>;\n /**\n * The highest price per gas (wei) a transaction signs: the handle's\n * `maxFeePerGas` option, else the network's `params.maxFeePerGas`, else\n * `DEFAULT_MAX_FEE_PER_GAS`.\n */\n readonly maxFeePerGas: bigint;\n}\n\n/**\n * The only driver option (`HandleOptions.options`) the EVM driver reads. Any other key is\n * refused, so a typo, or another family's option such as Tron's `maxFeeLimit`, fails loudly\n * instead of leaving the default in place.\n */\nconst OPTION_KEYS: readonly string[] = Object.freeze(['maxFeePerGas']);\n\nconst MAX_UINT256 = 2n ** 256n - 1n;\n\n/** A price ceiling: a bigint of wei per gas that an EVM transaction can carry. */\nfunction priceCeiling(\n value: unknown,\n name: string,\n fail: (reason: string) => never,\n): bigint {\n if (typeof value !== 'bigint' || value < 1n || value > MAX_UINT256) {\n fail(`${name} must be a bigint of wei per gas from 1 to 2^256 − 1`);\n }\n return value as bigint;\n}\n\n/** The OP Stack `GasPriceOracle` predeploy. */\nexport const GAS_PRICE_ORACLE = '0x420000000000000000000000000000000000000F';\n\n/**\n * The `LogFeeTransfer(address,address,address,uint256,uint256,uint256,uint256,uint256)`\n * system log that Polygon PoS's client (bor, `core/bor_fee_log.go`) adds to every\n * fee-paying transaction, emitted from the MRC20 predeploy. It says nothing about code.\n */\nexport const POLYGON_FEE_LOG = {\n address: '0x0000000000000000000000000000000000001010',\n topic: '0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63',\n} as const;\n\n/**\n * bor's `LogTransfer(address,address,address,uint256,uint256,uint256,uint256,uint256)`\n * system log for a native POL value transfer (`core/evm.go` `Transfer`), from the same\n * predeploy. Its topic is not ERC-20 `Transfer`'s, so it never decodes as a token movement.\n */\nexport const POLYGON_TRANSFER_LOG = {\n address: POLYGON_FEE_LOG.address,\n topic: '0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4',\n} as const;\n\nfunction finalityOf(\n policy: FinalityPolicy,\n fail: (reason: string) => never,\n): EvmFinality {\n if (policy.kind === 'tag') return { kind: 'tag' };\n if (policy.kind === 'confirmations') {\n // The final height is `head - confirmations + 1`, so fewer than one is the future.\n const confirmations: unknown = policy.confirmations;\n if (!Number.isSafeInteger(confirmations) || (confirmations as number) < 1) {\n return fail('finality confirmations must be an integer of at least 1');\n }\n return { kind: 'confirmations', confirmations: confirmations as number };\n }\n return fail(\n `finality '${policy.kind}' is not an EVM policy (use 'tag' or 'confirmations')`,\n );\n}\n\nexport function evmNetworkConfig(\n chain: ChainInfo,\n network: NetworkInfo,\n options: Readonly<Record<string, unknown>> = {},\n): EvmNetworkConfig {\n const fail = (reason: string): never => {\n throw new ConfigError(\n 'CONFIG_INVALID',\n `EVM network ${chain.id}:${network.id}: ${reason}`,\n );\n };\n if (network.identity === undefined || !/^[1-9][0-9]*$/.test(network.identity)) {\n fail('its identity must be the decimal chain id');\n }\n const feeModel = network.feeModel;\n if (feeModel !== 'evm-1559' && feeModel !== 'evm-legacy') {\n fail(`fee model '${feeModel}' is not 'evm-1559' or 'evm-legacy'`);\n }\n const finality = finalityOf(network.finality, fail);\n const capabilities = new Set<Capability>(EVM_CAPABILITIES);\n for (const c of network.capabilities?.add ?? []) capabilities.add(c);\n for (const c of network.capabilities?.remove ?? []) capabilities.delete(c);\n if (capabilities.has('fee-market-1559') !== (feeModel === 'evm-1559')) {\n fail(`'fee-market-1559' must be present exactly on 'evm-1559' networks`);\n }\n if (capabilities.has('finality-tag') !== (finality.kind === 'tag')) {\n fail(`'finality-tag' must be present exactly on 'tag' finality networks`);\n }\n // The fee policy computes `BigInt(100 + percent)`, which throws on a fraction.\n const bump: unknown = network.replacement?.minBumpPercent;\n if (bump !== undefined && !(Number.isSafeInteger(bump) && (bump as number) >= 0)) {\n fail('replacement.minBumpPercent must be a non-negative integer');\n }\n const params = network.params ?? {};\n const minTip = params.minPriorityFeePerGas;\n if (minTip !== undefined && typeof minTip !== 'bigint') {\n fail('params.minPriorityFeePerGas must be a bigint');\n }\n if (params.l1DataFee !== undefined && params.l1DataFee !== 'op-stack') {\n fail(`params.l1DataFee must be 'op-stack'`);\n }\n // Data, not the chain id, so a bor chain served through evmChainPlugin can opt in.\n if (params.systemLogs !== undefined && params.systemLogs !== 'bor') {\n fail(`params.systemLogs must be 'bor'`);\n }\n // The refusal lists the accepted name, never the caller's key or its value: either may\n // be a secret typed in the wrong place.\n for (const key of Object.keys(options)) {\n if (!OPTION_KEYS.includes(key)) fail(unknownName('option', OPTION_KEYS));\n }\n // The handle's option, else the network entry's own, else the\n // default. A network value is checked even where an option overrides it.\n const own = params.maxFeePerGas;\n const networkCeiling =\n own === undefined ? undefined : priceCeiling(own, 'params.maxFeePerGas', fail);\n const maxFeePerGas =\n options.maxFeePerGas !== undefined\n ? priceCeiling(options.maxFeePerGas, 'maxFeePerGas', fail)\n : (networkCeiling ?? DEFAULT_MAX_FEE_PER_GAS);\n const replaces = capabilities.has('replace-fee') || capabilities.has('cancel');\n return {\n chainId: BigInt(network.identity as string),\n feeModel: feeModel as EvmFeeModel,\n finality,\n ...(replaces ? { minBumpPercent: network.replacement?.minBumpPercent ?? 10 } : {}),\n minPriorityFeePerGas: (minTip as bigint | undefined) ?? 0n,\n l1DataFee: params.l1DataFee === 'op-stack',\n polygonSystemLogs: params.systemLogs === 'bor',\n capabilities,\n maxFeePerGas,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../../src/adapters/evm/network.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What the EVM driver needs from a network's registry entry (each network keeps its own\n * registry identity, its decimal chain id), validated once when a driver is created, so a\n * custom EVM chain with inconsistent data fails with `CONFIG_INVALID` instead of\n * misbehaving.\n */\nimport type { Capability } from '../../core/model/capability';\nimport type { ChainInfo, FinalityPolicy, NetworkInfo } from '../../core/model/chain';\nimport { ConfigError } from '../../core/errors/error';\nimport { unknownName } from '../../core/util/names';\nimport {\n DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_MAX_GAS_LIMIT,\n TRANSFER_GAS,\n type EvmFeeModel,\n} from './fees';\n\n/** Every capability an EVM network can have; a network removes what it lacks. */\nexport const EVM_CAPABILITIES: readonly Capability[] = [\n 'tokens',\n 'block-scan',\n 'hd-public-derivation',\n 'fee-market-1559',\n 'finality-tag',\n 'replace-fee',\n 'cancel',\n];\n\nexport type EvmFinality =\n | { readonly kind: 'tag' }\n | { readonly kind: 'confirmations'; readonly confirmations: number };\n\nexport interface EvmNetworkConfig {\n readonly chainId: bigint;\n readonly feeModel: EvmFeeModel;\n readonly finality: EvmFinality;\n /** The txpool's price bump; `undefined` when the network has no replace or cancel. */\n readonly minBumpPercent?: number;\n readonly minPriorityFeePerGas: bigint;\n /** OP Stack: transactions also pay an L1 data fee (`GasPriceOracle.getL1Fee`). */\n readonly l1DataFee: boolean;\n /**\n * bor-based networks (`params.systemLogs: 'bor'`, as on Polygon PoS): receipts carry bor's\n * `POLYGON_FEE_LOG` and `POLYGON_TRANSFER_LOG`.\n */\n readonly polygonSystemLogs: boolean;\n readonly capabilities: ReadonlySet<Capability>;\n /**\n * The highest price per gas (wei) a transaction signs: the handle's\n * `maxFeePerGas` option, else the network's `params.maxFeePerGas`, else\n * `DEFAULT_MAX_FEE_PER_GAS`.\n */\n readonly maxFeePerGas: bigint;\n /**\n * The highest gas limit a transaction signs: the handle's `maxGasLimit` option, else the\n * network's `params.maxGasLimit`, else `DEFAULT_MAX_GAS_LIMIT`.\n */\n readonly maxGasLimit: bigint;\n}\n\n/**\n * The only driver options (`HandleOptions.options`) the EVM driver reads. Any other key is\n * refused, so a typo, or another family's option such as Tron's `maxFeeLimit`, fails loudly\n * instead of leaving the default in place.\n */\nconst OPTION_KEYS: readonly string[] = Object.freeze(['maxFeePerGas', 'maxGasLimit']);\n\nconst MAX_UINT256 = 2n ** 256n - 1n;\n/** The largest gas limit a transaction carries: clients read it as a `uint64`. */\nconst MAX_UINT64 = 2n ** 64n - 1n;\n\n/** A price ceiling: a bigint of wei per gas that an EVM transaction can carry. */\nfunction priceCeiling(\n value: unknown,\n name: string,\n fail: (reason: string) => never,\n): bigint {\n if (typeof value !== 'bigint' || value < 1n || value > MAX_UINT256) {\n fail(`${name} must be a bigint of wei per gas from 1 to 2^256 − 1`);\n }\n return value as bigint;\n}\n\n/**\n * A gas-limit bound: a bigint of gas a transaction can carry, and at least a plain\n * transfer's 21,000, below which nothing could be signed.\n */\nfunction gasBound(value: unknown, name: string, fail: (reason: string) => never): bigint {\n if (typeof value !== 'bigint' || value < TRANSFER_GAS || value > MAX_UINT64) {\n fail(`${name} must be a bigint of gas from 21,000 to 2^64 − 1`);\n }\n return value as bigint;\n}\n\n/** The OP Stack `GasPriceOracle` predeploy. */\nexport const GAS_PRICE_ORACLE = '0x420000000000000000000000000000000000000F';\n\n/**\n * The `LogFeeTransfer(address,address,address,uint256,uint256,uint256,uint256,uint256)`\n * system log that Polygon PoS's client (bor, `core/bor_fee_log.go`) adds to every\n * fee-paying transaction, emitted from the MRC20 predeploy. It says nothing about code.\n */\nexport const POLYGON_FEE_LOG = {\n address: '0x0000000000000000000000000000000000001010',\n topic: '0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63',\n} as const;\n\n/**\n * bor's `LogTransfer(address,address,address,uint256,uint256,uint256,uint256,uint256)`\n * system log for a native POL value transfer (`core/evm.go` `Transfer`), from the same\n * predeploy. Its topic is not ERC-20 `Transfer`'s, so it never decodes as a token movement.\n */\nexport const POLYGON_TRANSFER_LOG = {\n address: POLYGON_FEE_LOG.address,\n topic: '0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4',\n} as const;\n\nfunction finalityOf(\n policy: FinalityPolicy,\n fail: (reason: string) => never,\n): EvmFinality {\n if (policy.kind === 'tag') return { kind: 'tag' };\n if (policy.kind === 'confirmations') {\n // The final height is `head - confirmations + 1`, so fewer than one is the future.\n const confirmations: unknown = policy.confirmations;\n if (!Number.isSafeInteger(confirmations) || (confirmations as number) < 1) {\n return fail('finality confirmations must be an integer of at least 1');\n }\n return { kind: 'confirmations', confirmations: confirmations as number };\n }\n return fail(\n `finality '${policy.kind}' is not an EVM policy (use 'tag' or 'confirmations')`,\n );\n}\n\nexport function evmNetworkConfig(\n chain: ChainInfo,\n network: NetworkInfo,\n options: Readonly<Record<string, unknown>> = {},\n): EvmNetworkConfig {\n const fail = (reason: string): never => {\n throw new ConfigError(\n 'CONFIG_INVALID',\n `EVM network ${chain.id}:${network.id}: ${reason}`,\n );\n };\n if (network.identity === undefined || !/^[1-9][0-9]*$/.test(network.identity)) {\n fail('its identity must be the decimal chain id');\n }\n const feeModel = network.feeModel;\n if (feeModel !== 'evm-1559' && feeModel !== 'evm-legacy') {\n fail(`fee model '${feeModel}' is not 'evm-1559' or 'evm-legacy'`);\n }\n const finality = finalityOf(network.finality, fail);\n const capabilities = new Set<Capability>(EVM_CAPABILITIES);\n for (const c of network.capabilities?.add ?? []) capabilities.add(c);\n for (const c of network.capabilities?.remove ?? []) capabilities.delete(c);\n if (capabilities.has('fee-market-1559') !== (feeModel === 'evm-1559')) {\n fail(`'fee-market-1559' must be present exactly on 'evm-1559' networks`);\n }\n if (capabilities.has('finality-tag') !== (finality.kind === 'tag')) {\n fail(`'finality-tag' must be present exactly on 'tag' finality networks`);\n }\n // The fee policy computes `BigInt(100 + percent)`, which throws on a fraction.\n const bump: unknown = network.replacement?.minBumpPercent;\n if (bump !== undefined && !(Number.isSafeInteger(bump) && (bump as number) >= 0)) {\n fail('replacement.minBumpPercent must be a non-negative integer');\n }\n const params = network.params ?? {};\n const minTip = params.minPriorityFeePerGas;\n if (minTip !== undefined && typeof minTip !== 'bigint') {\n fail('params.minPriorityFeePerGas must be a bigint');\n }\n if (params.l1DataFee !== undefined && params.l1DataFee !== 'op-stack') {\n fail(`params.l1DataFee must be 'op-stack'`);\n }\n // Data, not the chain id, so a bor chain served through evmChainPlugin can opt in.\n if (params.systemLogs !== undefined && params.systemLogs !== 'bor') {\n fail(`params.systemLogs must be 'bor'`);\n }\n // The refusal lists the accepted name, never the caller's key or its value: either may\n // be a secret typed in the wrong place.\n for (const key of Object.keys(options)) {\n if (!OPTION_KEYS.includes(key)) fail(unknownName('option', OPTION_KEYS));\n }\n // The handle's option, else the network entry's own, else the\n // default. A network value is checked even where an option overrides it.\n const own = params.maxFeePerGas;\n const networkCeiling =\n own === undefined ? undefined : priceCeiling(own, 'params.maxFeePerGas', fail);\n const maxFeePerGas =\n options.maxFeePerGas !== undefined\n ? priceCeiling(options.maxFeePerGas, 'maxFeePerGas', fail)\n : (networkCeiling ?? DEFAULT_MAX_FEE_PER_GAS);\n // The gas-limit bound resolves the same way.\n const ownGas = params.maxGasLimit;\n const networkGas =\n ownGas === undefined ? undefined : gasBound(ownGas, 'params.maxGasLimit', fail);\n const maxGasLimit =\n options.maxGasLimit !== undefined\n ? gasBound(options.maxGasLimit, 'maxGasLimit', fail)\n : (networkGas ?? DEFAULT_MAX_GAS_LIMIT);\n const replaces = capabilities.has('replace-fee') || capabilities.has('cancel');\n return {\n chainId: BigInt(network.identity as string),\n feeModel: feeModel as EvmFeeModel,\n finality,\n ...(replaces ? { minBumpPercent: network.replacement?.minBumpPercent ?? 10 } : {}),\n minPriorityFeePerGas: (minTip as bigint | undefined) ?? 0n,\n l1DataFee: params.l1DataFee === 'op-stack',\n polygonSystemLogs: params.systemLogs === 'bor',\n capabilities,\n maxFeePerGas,\n maxGasLimit,\n };\n}\n"]}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The EVM family plugin: chains, tokens and provider presets as data, plus one
|
|
3
|
-
* adapter manifest per library. SDK-free: only a manifest's `load()` requires a client
|
|
4
|
-
* module, and with it the SDK. `ethers` is registered first, so it is the family default.
|
|
5
|
-
*/
|
|
6
1
|
import type { AdapterManifest, PeerDependency } from '../../core/driver/types';
|
|
7
2
|
import type { ChainInfo } from '../../core/model/chain';
|
|
8
3
|
import type { AssetRegistration } from '../../core/registry/assets';
|
|
@@ -27,10 +22,14 @@ export interface EvmChainPluginOptions {
|
|
|
27
22
|
/** Chains with `family: 'evm'`, nonce ordering and the `secp256k1-ecdsa` scheme. */
|
|
28
23
|
readonly chains: readonly ChainInfo[];
|
|
29
24
|
readonly presets?: readonly ProviderPreset[];
|
|
25
|
+
/**
|
|
26
|
+
* Tokens: `erc20` refs, each registered under its EIP-55 checksummed contract, whatever
|
|
27
|
+
* case it is given in, so its alias and its transfers name one asset id.
|
|
28
|
+
*/
|
|
30
29
|
readonly assets?: readonly AssetRegistration[];
|
|
31
30
|
}
|
|
32
31
|
/**
|
|
33
32
|
* A plugin for EVM chains of your own, served by the built-in EVM driver with either
|
|
34
|
-
* library. Every network is validated here, so bad data fails at registration.
|
|
33
|
+
* library. Every network and token is validated here, so bad data fails at registration.
|
|
35
34
|
*/
|
|
36
35
|
export declare function evmChainPlugin(options: EvmChainPluginOptions): Plugin;
|