diff --git a/.changeset/olive-ants-draw.md b/.changeset/olive-ants-draw.md new file mode 100644 index 00000000..f61be929 --- /dev/null +++ b/.changeset/olive-ants-draw.md @@ -0,0 +1,49 @@ +--- +"op-viem": patch +--- + +Actions now receive contract addresses instead of L2 config objects for simplicty and Viem upstream compatibility. op-viem/chains now eexports addresses objects that be spread into actions to pass the required address. + +Previously + +```ts +import { publicL1Actions } from 'op-viem' +import { base } from 'op-viem/chains' +import { createPublicClient } from 'viem' + +const publicClient = createPublicClient({ + account, + chain: mainnet, + transport: http(), +}).extend(publicL1Actions) + +await getOutputForL2Block(publicClient, { + blockNumber: 2725977n, + l2Chain: base, +}) +``` + +Now + +```ts +import { publicL1Actions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' +import { createPublicClient } from 'viem' + +const publicClient = createPublicClient({ + account, + chain: mainnet, + transport: http(), +}).extend(publicL1Actions) + +await getOutputForL2Block(publicClient, { + blockNumber: 2725977n, + l2OutputOracle: baseAddresses.l2OutputOracle, +}) + +// more simply +await getOutputForL2Block(publicClient, { + blockNumber: 2725977n, + ...baseAddresses, +}) +``` diff --git a/.vscode/settings.json b/.vscode/settings.json index ca089449..7c77c161 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,8 @@ "typescript.enablePromptUseWorkspaceTsdk": true, "editor.codeActionsOnSave": { "source.organizeImports.biome": true + }, + "[typescript]": { + "editor.defaultFormatter": "dprint.dprint" } } diff --git a/site/docs/actions/public/L1/getOutputForL2Block.md b/site/docs/actions/public/L1/getOutputForL2Block.md index 8d443520..a974b3a6 100644 --- a/site/docs/actions/public/L1/getOutputForL2Block.md +++ b/site/docs/actions/public/L1/getOutputForL2Block.md @@ -4,7 +4,7 @@ Calls to the L2OutputOracle contract on L1 to get the output for a given L2 bloc ```ts [example.ts] import { publicL1Actions } from 'op-viem' -import { base } from 'op-viem/chains' +import { baseAddresses } from 'op-viem/chains' import { createPublicClient } from 'viem' const publicClient = createPublicClient({ @@ -15,6 +15,43 @@ const publicClient = createPublicClient({ await getOutputForL2Block(publicClient, { blockNumber: 2725977n, - l2Chain: base, + l2OutputOracle: baseAddresses.l2OutputOracle, +}) + +// more simply +await getOutputForL2Block(publicClient, { + blockNumber: 2725977n, + ...baseAddresses, }) ``` + +## Return Value + +Returns `GetOutputForL2BlockReturnType`. + +```ts [example.ts] +export type Proposal = { + outputRoot: Hex + timestamp: bigint + l2BlockNumber: bigint +} + +export type GetOutputForL2BlockReturnType = { + proposal: Proposal + outputIndex: bigint +} +``` + +## Parameters + +### blockNumber + +- **Type:** `bigint` + +The block number of the L2 block for which to get the output. + +### l2OutputOracle + +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) + +The address of the L2OutputOracle contract where the `getOutputForL2Block` call will be made. diff --git a/site/docs/actions/public/L1/getSecondsToFinalizable.md b/site/docs/actions/public/L1/getSecondsToFinalizable.md index 4ce0ec3a..ca3aa16f 100644 --- a/site/docs/actions/public/L1/getSecondsToFinalizable.md +++ b/site/docs/actions/public/L1/getSecondsToFinalizable.md @@ -4,6 +4,7 @@ Returns the number of seconds until a withdrawal is finalized for a given withdr ```ts [example.ts] import { publicL1Actions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' import { createPublicClient } from 'viem' const publicClient = createPublicClient({ @@ -13,7 +14,15 @@ const publicClient = createPublicClient({ }).extend(publicL1Actions) const seconds = await getSecondsToFinalizable(publicClient, { - l2Chain: base, + portal: baseAddresses.portal, + l2OutputOracle: baseAddresses.l2OutputOracle, + withdrawalHash: + '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', +}) + +// or more simply +const seconds = await getSecondsToFinalizable(publicClient, { + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -25,23 +34,17 @@ Returns a `number` representative of the seconds until withdrawal finalization. ## Parameters -### l2chain (optional) - -- **Type:** `OpStackChain` - -The L2 chain to deposit to. - -### optimismPortalAddress (optional) +### portal -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The address of the `OptimismPortal` contract where the `readProvenWithdrawals` call will be made. MUST be specified if [l2Chain](#l2chain-optional) not passed. +The address of the `OptimismPortal` contract where the `readProvenWithdrawals` call will be made. -### l2OutputOracleAddress (optional) +### l2OutputOracle -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The address of the L2OutputOracle contract where the `FINALIZATION_PERIOD_SECONDS` call will be made. MUST be provied if [l2Chain](l2chain-optional) is not. +The address of the L2OutputOracle contract where the `FINALIZATION_PERIOD_SECONDS` call will be made. ### withdrawalHash diff --git a/site/docs/actions/public/L1/getSecondsToNextL2Output.md b/site/docs/actions/public/L1/getSecondsToNextL2Output.md index 3b747fdd..4e04cbe2 100644 --- a/site/docs/actions/public/L1/getSecondsToNextL2Output.md +++ b/site/docs/actions/public/L1/getSecondsToNextL2Output.md @@ -16,7 +16,12 @@ const l1Client = createPublicClient({ const time = await l1Client.getSecondsToNextL2Output(, { latestL2BlockNumber, - l2Chain: base, + l2OutputOracle: baseAddresses.l2OutputOracle, +}) +// Or +const time = await l1Client.getSecondsToNextL2Output(, { + latestL2BlockNumber, + ...baseAddresses, }) ``` @@ -28,14 +33,14 @@ Seconds until the next L2 output should be posted. ## Parameters -### l2Chain (optional) +### latestL2BlockNumber -- **Type:** `OpStackChain` +- **Type:** `bigint` -The L2 chain that we are waiting on the output of. +The latest L2 block number. -### l2OutputOracleAddress (optional) +### l2OutputOracle -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The address of the L2OutputOracle contract. MUST be provied if [l2Chain](l2chain-optional) is not. +The address of the L2OutputOracle contract. diff --git a/site/docs/actions/public/L1/readFinalizedWithdrawals.md b/site/docs/actions/public/L1/readFinalizedWithdrawals.md index 69c91227..57a37051 100644 --- a/site/docs/actions/public/L1/readFinalizedWithdrawals.md +++ b/site/docs/actions/public/L1/readFinalizedWithdrawals.md @@ -13,7 +13,13 @@ const publicClient = createPublicClient({ }).extend(publicL1Actions) const finalizedWithdrawal = await readFinalizedWithdrawals(publicClient, { - l2Chain: base, + portal: baseAddresses.portal, + withdrawalHash: + '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', +}) +// Or +const finalizedWithdrawal = await readFinalizedWithdrawals(publicClient, { + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -25,17 +31,11 @@ Returns a `boolean` for whether the withdrawal has been finalized. ## Parameters -### l2chain (optional) - -- **Type:** `OpStackChain` - -The L2 chain to deposit to. - -### optimismPortalAddress (optional) +### portalAddress -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The `OptimismPortal` contract where the sendMessage call should be made. MUST be specified if [l2Chain](#l2chain-optional) not passed. +The `OptimismPortal` contract where the sendMessage call should be made. ### withdrawalHash diff --git a/site/docs/actions/public/L1/readProvenWithdrawals.md b/site/docs/actions/public/L1/readProvenWithdrawals.md index bd406df2..7bccb0f6 100644 --- a/site/docs/actions/public/L1/readProvenWithdrawals.md +++ b/site/docs/actions/public/L1/readProvenWithdrawals.md @@ -4,6 +4,7 @@ Returns a `ProvenWithdrawal` struct containing the `outputRoot`, `timestamp`, an ```ts [example.ts] import { publicL1Actions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' import { createPublicClient } from 'viem' const publicClient = createPublicClient({ @@ -13,7 +14,13 @@ const publicClient = createPublicClient({ }).extend(publicL1Actions) const provenWithdrawal = await readProvenWithdrawals(publicClient, { - l2Chain: base, + portal: baseAddresses.portal, + withdrawalHash: + '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', +}) +// or +const provenWithdrawal = await readProvenWithdrawals(publicClient, { + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -23,19 +30,21 @@ const provenWithdrawal = await readProvenWithdrawals(publicClient, { Returns an object that represents a `ProvenWithdrawl` struct that contains the `outputRoot`, `timestamp`, and `l2OutputIndex` -## Parameters - -### l2chain (optional) - -- **Type:** `OpStackChain` +```ts +type ProvenWithdrawal = { + outputRoot: Hex + timestamp: bigint + l2OutputIndex: bigint +} +``` -### optimismPortalAddress (optional) +## Parameters -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) +### portal -The `OptimismPortal` contract where the sendMessage call should be made. MUST be specified if [l2Chain](#l2chain-optional) not passed. +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The L2 chain to deposit to. +The `OptimismPortal` contract where the sendMessage call should be made. ### withdrawalHash diff --git a/site/docs/actions/public/L1/simulateDepositERC20.md b/site/docs/actions/public/L1/simulateDepositERC20.md index 8f504e39..1c7abd1e 100644 --- a/site/docs/actions/public/L1/simulateDepositERC20.md +++ b/site/docs/actions/public/L1/simulateDepositERC20.md @@ -4,6 +4,7 @@ Simulates a deposit of ERC20 tokens to L2. ```ts [example.ts] import { base, publicL1Actions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' import { createPublicClient } from 'viem' const USDCL1 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' @@ -23,7 +24,7 @@ const { request } = await publicClient.simulateDepositERC20({ amount: 1n, minGasLimit: 100000, }, - l2chain: base, + l1StandardBridge: baseAddresses.l1StandardBridge, account: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045', }) ``` @@ -60,11 +61,11 @@ Returns a `request` that can be passed to Viem's `writeContract` and a `result` - **Type:** `Hex` - Extra data to include in the transaction. -### l2chain +### l1StandardBridge -- **Type:** `OpStackChain` +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The L2 chain to deposit to. +The `L1StandardBridge` contract. ### account diff --git a/site/docs/actions/public/L1/simulateDepositETH.md b/site/docs/actions/public/L1/simulateDepositETH.md index 1282d37e..9fe705c1 100644 --- a/site/docs/actions/public/L1/simulateDepositETH.md +++ b/site/docs/actions/public/L1/simulateDepositETH.md @@ -3,7 +3,8 @@ Simulates a deposit of ETH from L1 to L2. ```ts [example.ts] -import { base, publicL1Actions } from 'op-viem' +import { publicL1Actions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' import { createPublicClient } from 'viem' const publicClient = createPublicClient({ @@ -18,7 +19,7 @@ const { request } = await publicClient.simulateDepositETH({ gasLimit: 100000, }, value: 1n, - l2chain: base, + portal: baseAddresses.portal, account: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045', }) ``` @@ -29,17 +30,15 @@ Returns a `request` that can be passed to Viem's `writeContract` and a `result` ## Parameters -### to +### args -- **Type:** `Address` - -The address to deposit the tokens to. - -### gasLimit - -- **Type:** `number` +- #### to + - **Type:** `Address` + - The address to deposit the tokens to. -The minimum gas limit to use for the deposit transaction. +- #### gasLimit + - **Type:** `number` + - The minimum gas limit to use for the deposit transaction. ### value @@ -47,11 +46,11 @@ The minimum gas limit to use for the deposit transaction. The amount of ETH to deposit. -### l2chain +### portal -- **Type:** `OpStackChain` +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The L2 chain to deposit to. +The `OptimismPortal` contract. ### account diff --git a/site/docs/actions/public/L1/simulateFinalizeWithdrawalTransaction.md b/site/docs/actions/public/L1/simulateFinalizeWithdrawalTransaction.md index e69de29b..7e0d34c9 100644 --- a/site/docs/actions/public/L1/simulateFinalizeWithdrawalTransaction.md +++ b/site/docs/actions/public/L1/simulateFinalizeWithdrawalTransaction.md @@ -0,0 +1,62 @@ +# simulateFinalizeWithdrawalTransaction + +Simulates a call to finalizeWithdrawalTranasction on the OptimismPortal contract. + +```ts [example.ts] +import { publicL1Actions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' +import { createPublicClient } from 'viem' + +const publicClient = createPublicClient({ + account, + chain: mainnet, + transport: http(), +}).extend(publicL1Actions) + +const withdrawal: FinalizeWithdrawalTransactionParameters = { + nonce: + 1766847064778384329583297500742918515827483896875618958121606201292641795n, + sender: '0x02f086dBC384d69b3041BC738F0a8af5e49dA181', + target: '0x02f086dBC384d69b3041BC738F0a8af5e49dA181', + value: 335000000000000000000n, + gasLimit: 100000n, + data: '0x01', +} + +const { request } = await publicClient.simulateFinalizeWithdrawalTransaction({ + ...baseAddresses, + withdrawal, + account: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045', +}) +``` + +## Return Value + +Returns a `request` that can be passed to Viem's `writeContract` and a `result` indicating whether the simulation succeeded. + +## Parameters + +### withdrawal + +```ts +type FinalizeWithdrawalTransactionParameters = { + nonce: bigint + sender: `0x${string}` + target: `0x${string}` + value: bigint + gasLimit: bigint + data: `0x${string}` +} +``` + +### portal + +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) + +The `OptimismPortal` contract. + +### account + +- **Type:** `Address` + +The address of the account to use. diff --git a/site/docs/actions/public/L1/simulateProveWithdrawalTransaction.md b/site/docs/actions/public/L1/simulateProveWithdrawalTransaction.md index fcf8ea5c..638bba81 100644 --- a/site/docs/actions/public/L1/simulateProveWithdrawalTransaction.md +++ b/site/docs/actions/public/L1/simulateProveWithdrawalTransaction.md @@ -153,7 +153,7 @@ await walletClient.simulateProveWithdrawalTransaction({ }) ``` -### optimismPortalAddress (optional) +### portalAddress (optional) - **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) @@ -162,7 +162,7 @@ The `OptimismPortal` contract where the sendMessage call should be made. MUST be ```ts await walletClient.simulateProveWithdrawalTransaction({ args, - optimismPortalAddress: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e', // [!code focus:1] + portalAddress: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e', // [!code focus:1] }) ``` diff --git a/site/docs/actions/wallet/L1/writeDepositERC20.md b/site/docs/actions/wallet/L1/writeDepositERC20.md index dbbb352c..1ca96ff8 100644 --- a/site/docs/actions/wallet/L1/writeDepositERC20.md +++ b/site/docs/actions/wallet/L1/writeDepositERC20.md @@ -3,7 +3,8 @@ Writes a deposit of ERC20 tokens from L1 to L2. ```ts [example.ts] -import { base, walletL1OpStackActions } from 'op-viem' +import { walletL1OpStackActions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' import { createWalletClient } from 'viem' const USDCL1 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' @@ -22,7 +23,7 @@ const { request } = await walletClient.writeDepositERC20({ amount: 1n, minGasLimit: 100000, }, - l2chain: base, + ...baseAddresses, account: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045', }) ``` @@ -33,47 +34,49 @@ Returns a transaction hash of the deposit transaction. ## Parameters -### l1Token +### args + +#### l1Token - **Type:** `Address` The L1 token contract address. -### l2Token +#### l2Token - **Type:** `Address` The L2 token contract address. -### to +#### to - **Type:** `Address` The address to deposit the tokens to. -### amount +#### amount - **Type:** `bigint` The amount of tokens to deposit. -### gasLimit +#### gasLimit - **Type:** `bigint` The gas limit for the transaction. -### extraData (optional) +#### extraData (optional) - **Type:** `data` Extra data to include in the transaction. -### l2chain +### l1StandardBridge -- **Type:** `OpStackChain` +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The L2 chain to deposit to. +The `L1StandardBridge` contract. ### account diff --git a/site/docs/actions/wallet/L1/writeDepositETH.md b/site/docs/actions/wallet/L1/writeDepositETH.md index 0f4fa51c..0a5e4dfb 100644 --- a/site/docs/actions/wallet/L1/writeDepositETH.md +++ b/site/docs/actions/wallet/L1/writeDepositETH.md @@ -3,7 +3,8 @@ Writes a deposit of ETH from L1 to L2. ```ts [example.ts] -import { base, walletL1OpStackActions } from 'op-viem' +import { walletL1OpStackActions } from 'op-viem' +import { baseAddresses } from 'op-viem/chains' import { createWalletClient } from 'viem' const walletClient = createWalletClient({ @@ -16,8 +17,8 @@ const hash = await walletClient.writeDepositETH({ to: '0xFd4F24676eD4588928213F37B126B53c07186F45', gasLimit: 100000, }, + ...baseAddresses, value: 1n, - l2chain: base, account: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045', }) ``` @@ -28,13 +29,15 @@ Returns a transaction hash of the deposit transaction. ## Parameters -### to +### args + +#### to - **Type:** `Address` The address to deposit the tokens to. -### gasLimit +#### gasLimit - **Type:** `number` @@ -46,11 +49,11 @@ The minimum gas limit to use for the deposit transaction. The amount of ETH to deposit. -### l2chain +### portal -- **Type:** `OpStackChain` +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The L2 chain to deposit to. +The `OptimismPortal` contract. ### account diff --git a/site/docs/actions/wallet/L1/writeDepositTransaction.md b/site/docs/actions/wallet/L1/writeDepositTransaction.md index 42833f3f..cd8a5b74 100644 --- a/site/docs/actions/wallet/L1/writeDepositTransaction.md +++ b/site/docs/actions/wallet/L1/writeDepositTransaction.md @@ -20,7 +20,7 @@ In this case, you can use [simulateSendMessage](/docs/actions/wallet/L1/simulate ```ts [example.ts] import { DepositTransactionParameters } from 'op-viem' -import { base } from 'op-viem/chains' +import { baseAddresses } from 'op-viem/chains' import { account, l2PublicClient, opStackL1WalletClient } from './config' const args: DepositTransactionParameters = { @@ -42,7 +42,7 @@ args.gasLimit = gas const hash = await opStackL1WalletClient.writeDepositTransaction({ args, - l2Chain: base, + ...baseAddresses, value: 1n, }) ``` @@ -120,29 +120,16 @@ await walletClient.writeDepositTransaction({ }) ``` -### l2Chain (optional) - -- **Type:** `OpStackChain` - -The destination L2 chain of the deposit transaction. `l2Chain.opStackConfig.l1.chainId` must match `chain.id` (from `client.chain` or `chain` passed explicitly as an arg). The address at `l2Chain.opStackConfig.l1.contracts.optimismPortal.address` will be used for the contract call. If this is argument not passed or if no such contract definition exists, [optimismPortalAddress](#optimismPortalAddress) must be passed explicitly. - -```ts -await walletClient.writeDepositTransaction({ - args, - l2Chain: base, // [!code focus:1] -}) -``` - -### optimismPortalAddress (optional) +### portal -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) The `OptimismPortal` contract where the depositTransaction call should be made. ```ts await walletClient.writeDepositTransaction({ args, - optimismPortalAddress: portal, // [!code focus:1] + portalAddress: portal, // [!code focus:1] }) ``` @@ -155,7 +142,7 @@ Value in wei sent with this transaction. This value will be credited to the bala ```ts await walletClient.writeDepositTransaction({ args, - optimismPortalAddress: portal, + portalAddress: portal, value: parseEther(1), // [!code focus:1] }) ``` diff --git a/site/docs/actions/wallet/L1/writeFinalizeWithdrawalTransaction.md b/site/docs/actions/wallet/L1/writeFinalizeWithdrawalTransaction.md index a4b22a37..da57cf1b 100644 --- a/site/docs/actions/wallet/L1/writeFinalizeWithdrawalTransaction.md +++ b/site/docs/actions/wallet/L1/writeFinalizeWithdrawalTransaction.md @@ -1,3 +1,5 @@ +# writeFinalizeWithdrawalTransaction + ```ts const withdrawal: FinalizeWithdrawalTransactionParameters = { nonce: 176684 7064778384329583297500742918515827483896875618958121606201292641795n, @@ -9,8 +11,35 @@ const withdrawal: FinalizeWithdrawalTransactionParameters = { } const hash = await opStackL1WalletClient.writeFinalizeWithdrawalTranasction({ - l2Chain: base, + portal: baseAddresses.portal, withdrawal, account, }) ``` + +## Return Value + +[`Hash`](https://viem.sh/docs/glossary/types#hash) + +A [Transaction Hash](https://viem.sh/docs/glossary/terms#hash). + +## Parameters + +### withdrawal + +```ts +type FinalizeWithdrawalTransactionParameters = { + nonce: bigint + sender: `0x${string}` + target: `0x${string}` + value: bigint + gasLimit: bigint + data: `0x${string}` +} +``` + +### portal + +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) + +The `OptimismPortal` contract. diff --git a/site/docs/actions/wallet/L1/writeProveWithdrawalTransaction.md b/site/docs/actions/wallet/L1/writeProveWithdrawalTransaction.md index 4578bd96..7ba7129f 100644 --- a/site/docs/actions/wallet/L1/writeProveWithdrawalTransaction.md +++ b/site/docs/actions/wallet/L1/writeProveWithdrawalTransaction.md @@ -27,7 +27,7 @@ In this case, you can use [simulateProveWithdrawalTransactoin](/docs/actions/pub ```ts [example.ts] import { ProveWithdrawalTransactionArgs } from 'op-viem' -import { base } from 'op-viem/chains' +import { baseAddresses } from 'op-viem/chains' import { account, opStackL1PublicClient, @@ -74,7 +74,7 @@ const withdrawalMessages = await opStackL2PublicClient.getWithdrawalMessages({ const output = await opStackL1PublicClient.getOutputForL2Block({ l2BlockNumber: withdrawalMessages.blockNumber, - l2Chain: base, + ...baseAddresses, }) const args = await opStackL2PublicClient.getProveWithdrawalTransactionArgs({ @@ -84,7 +84,7 @@ const args = await opStackL2PublicClient.getProveWithdrawalTransactionArgs({ const hash = await opStackL1WalletClient.writeProveWithdrawalTransaction({ args, - l2Chain: base, + ...baseAdddresses, account: account, }) ``` @@ -178,33 +178,20 @@ await walletClient.writeProveWithdrawalTransaction({ '0xe09e3244a3f2d3e778ea2b2c739f085da3cf4453befda1c8c31c84e17e18a39301', ], } - l2Chain: base, + ...baseAddresses }) ``` -### l2Chain (optional) +### portal -- **Type:** `OpStackChain` +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The chain on which the withdrawal was initiated, used to determine which `OptimismPortal` to call. +The `OptimismPortal` contract where the sendMessage call should be made. ```ts await walletClient.writeProveWithdrawalTransaction({ args, - l2Chain: base, // [!code focus:1] -}) -``` - -### optimismPortalAddress (optional) - -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) - -The `OptimismPortal` contract where the sendMessage call should be made. MUST be specified if [l2Chain](#l2chain-optional) not passed. - -```ts -await walletClient.writeProveWithdrawalTransaction({ - args, - optimismPortalAddress: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e', // [!code focus:1] + portal: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e', // [!code focus:1] }) ``` diff --git a/site/docs/actions/wallet/L1/writeSendMessage.md b/site/docs/actions/wallet/L1/writeSendMessage.md index c11e48b5..1e6a2ffa 100644 --- a/site/docs/actions/wallet/L1/writeSendMessage.md +++ b/site/docs/actions/wallet/L1/writeSendMessage.md @@ -16,7 +16,7 @@ In this case, you can use [simulateSendMessage](/docs/actions/wallet/L1/simulate ```ts [example.ts] import { SendMessageParameters } from 'op-viem' -import { base } from 'op-viem/chains' +import { baseAddresses } from 'op-viem/chains' import { account, opStackL1WalletClient } from './config' const args: SendMessageParameters = { @@ -27,7 +27,7 @@ const args: SendMessageParameters = { const hash = await opStackL1WalletClient.writeSendMessage({ args, - l2Chain: base, + ...baseAddresses, value: 1n, }) ``` @@ -83,28 +83,15 @@ await walletClient.writeSendMessage({ minGasLimit: 85000, message: '0x8c874ebd0021fb3f', } - l2Chain: base, + ...baseAddresses }) ``` -### l2Chain (optional) +### l1CrossDomainMessenger -- **Type:** `OpStackChain` +- **Type:** [`RawOrContractAddress`](https://viem.sh/docs/glossary/types#raworcontractaddress) -The destination L2 chain of the deposit transaction. `l2Chain.opStackConfig.l1.chainId` must match `chain.id` (from `client.chain` or `chain` passed explicitly as an arg). The address at `l2Chain.opStackConfig.l1.contracts.l1CrossDomainMessenger.address` will be used for the contract call. If this is argument not passed or if no such contract definition exists, [l1CrossDomainMessengerAddress](#l1CrossDomainMessengerAddress) must be passed explicitly. - -```ts -await walletClient.writeSendMessage({ - args, - l2Chain: base, // [!code focus:1] -}) -``` - -### l1CrossDomainMessengerAddress (optional) - -- **Type:** [`Address`](https://viem.sh/docs/glossary/types#address) - -The `L1CrossDomainMessengerAddress` contract where the sendMessage call should be made. +The `L1CrossDomainMessenger` contract where the sendMessage call should be made. ```ts await walletClient.writeSendMessage({ @@ -120,9 +107,9 @@ await walletClient.writeSendMessage({ Value in wei sent with this transaction. This value will be credited to the balance of the caller address on L2 _before_ the L2 transaction created by this transaction is made. ```ts -await walletClient.writeDepositTransaction({ +await walletClient.writeSendMessage({ args, - optimismPortalAddress: portal, + l1CrossDomainMessengerAddress: messenger, value: parseEther(1), // [!code focus:1] }) ``` diff --git a/site/docs/actions/wallet/L2/writeOpStackL2.md b/site/docs/actions/wallet/L2/writeOpStackL2.md deleted file mode 100644 index a4c4c2b9..00000000 --- a/site/docs/actions/wallet/L2/writeOpStackL2.md +++ /dev/null @@ -1,3 +0,0 @@ -# writeOpStackL2 - -A generic function for making a write call to a known OpStack predeploy contract. diff --git a/site/docs/glossary/types.md b/site/docs/glossary/types.md index a5200641..d58d57f3 100644 --- a/site/docs/glossary/types.md +++ b/site/docs/glossary/types.md @@ -37,3 +37,18 @@ An [event](https://github.com/ethereum-optimism/optimism/blob/f368843d5b5a730a6b ## WithdrawalProof A dynamic-length array of bytes used in proving transactions in the [OptimismPortal](https://github.com/ethereum-optimism/optimism/blob/adf55b3a60279e4750ab0682cb92d19921bbd92a/packages/contracts-bedrock/src/L1/OptimismPortal.sol#L212). The proving transaction [must verify](https://github.com/ethereum-optimism/optimism/blob/adf55b3a60279e4750ab0682cb92d19921bbd92a/packages/contracts-bedrock/src/L1/OptimismPortal.sol#L263) that this hash is contained in the L2ToL1MessagePasser's storage. + +## RawOrContractAddress + +```ts [example.ts] +export type ContractAddress = { + address: `0x${string}` + chainId: chainId + blockCreated: number +} +export type RawOrContractAddress = + | `0x${string}` + | ContractAddress +``` + +Either a raw address string or an annotated ContractAddress such as found in the chain addresses object. diff --git a/site/docs/utilities/deposits/getDepositTransaction.md b/site/docs/utilities/deposits/getDepositTransaction.md index 053c9785..9154a931 100644 --- a/site/docs/utilities/deposits/getDepositTransaction.md +++ b/site/docs/utilities/deposits/getDepositTransaction.md @@ -76,13 +76,13 @@ Can be provided instead of [l1BlockHash](#l1blockhash-optional) and [logIndex](# - **Type:** `number` -The index of the given [`TransactionDepositedEvent`](/docs/glossary/types#transactiondepositedevent) log among all events emitted in the same L1 block. MUST be provied with [l1BlockHash](#l1BlockHash-optional) if sourceHash not passed. +The index of the given [`TransactionDepositedEvent`](/docs/glossary/types#transactiondepositedevent) log among all events emitted in the same L1 block. MUST be provided with [l1BlockHash](#l1BlockHash-optional) if sourceHash not passed. ### l1BlockHash (optional) - **Type:** `Hex` -The blockhash of the L1 block in which the passed [event](#event) was emitted. MUST be provied with [logIndex](#logIndex-optional) if sourceHash not passed. +The blockhash of the L1 block in which the passed [event](#event) was emitted. MUST be provided with [logIndex](#logIndex-optional) if sourceHash not passed. ### domain (optional) diff --git a/src/_test/live.test.ts b/src/_test/live.test.ts index 7841acd1..03bc073d 100644 --- a/src/_test/live.test.ts +++ b/src/_test/live.test.ts @@ -4,7 +4,7 @@ import { estimateGas } from 'viem/actions' import { goerli } from 'viem/chains' import { test } from 'vitest' import type { DepositTransactionParameters } from '../actions/wallet/L1/writeDepositTransaction.js' -import { baseGoerli } from '../chains/baseGoerli.js' +import { baseGoerliAddresses } from '../chains/baseGoerli.js' import { publicL1OpStackActions } from '../decorators/publicL1OpStackActions.js' import { walletL1OpStackActions } from '../decorators/walletL1OpStackActions.js' @@ -46,7 +46,7 @@ test('correctly retrieves L2 hash', async () => { args.gasLimit = gas const depositHash = await walletClient.writeDepositTransaction({ - l2Chain: baseGoerli, + ...baseGoerliAddresses, args, value: 1n, }) diff --git a/src/_test/utils.ts b/src/_test/utils.ts index 756bfe98..8f96ffce 100644 --- a/src/_test/utils.ts +++ b/src/_test/utils.ts @@ -10,10 +10,8 @@ import { RpcRequestError, webSocket, } from 'viem' -import { localhost, mainnet } from 'viem/chains' +import { base, localhost, mainnet } from 'viem/chains' import { rpc } from 'viem/utils' -import { base } from '../chains/base.js' -import type { OpStackChain } from '../types/opStackChain.js' import { accounts, localHttpUrl, localRollupHttpUrl, localWsUrl, locaRolluplWsUrl } from './constants.js' export class ProviderRpcError extends Error { @@ -65,7 +63,7 @@ export const rollupAnvilChain = { webSocket: [locaRolluplWsUrl], }, }, -} as const satisfies OpStackChain +} as const satisfies Chain const provider: EIP1193Provider = { on: (message, listener) => { diff --git a/src/actions/index.ts b/src/actions/index.ts index f451b125..a93413de 100644 --- a/src/actions/index.ts +++ b/src/actions/index.ts @@ -72,7 +72,6 @@ export { writeFinalizeWithdrawalTranasction, type WriteFinalizeWithdrawalTransactionParameters, } from './wallet/L1/writeFinalizeWithdrawalTransaction.js' -export { writeOpStackL1, type WriteOpStackL1Parameters } from './wallet/L1/writeOpStackL1.js' export { writeProveWithdrawalTransaction, type WriteProveWithdrawalTransactionParameters, @@ -82,6 +81,5 @@ export { writeSendMessage, type WriteSendMessageParameters, } from './wallet/L1/writeSendMessage.js' -export { writeOpStackL2, type WriteOpStackL2Parameters } from './wallet/L2/writeOpStackL2.js' export { writeWithdrawERC20, type WriteWithdrawERC20Parameters } from './wallet/L2/writeWithdrawERC20.js' export { writeWithdrawETH, type WriteWithdrawETHParameters } from './wallet/L2/writeWithdrawETH.js' diff --git a/src/actions/public/L1/getL2HashesForDepositTx.bench.ts b/src/actions/public/L1/getL2HashesForDepositTx.bench.ts index 0b817def..f684bcd2 100644 --- a/src/actions/public/L1/getL2HashesForDepositTx.bench.ts +++ b/src/actions/public/L1/getL2HashesForDepositTx.bench.ts @@ -4,7 +4,7 @@ import { ethers } from 'ethers' import { bench, describe } from 'vitest' import { ethersProvider } from '../../../_test/bench.js' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/base.js' import { getL2HashesForDepositTx } from './getL2HashesForDepositTx.js' describe('Computes L2 hash for L1 event', () => { @@ -19,7 +19,7 @@ describe('Computes L2 hash for L1 event', () => { // I am not sure how to produce an event from a transaction receipt. // Happy to update this if there is a better comparison const contract = new ethers.Contract( - base.opStackConfig.l1.contracts.optimismPortal.address, + baseAddresses.portal.address, optimismPortalABI, ethersProvider, ) diff --git a/src/actions/public/L1/getL2HashesForDepositTx.test.ts b/src/actions/public/L1/getL2HashesForDepositTx.test.ts index 80c86a58..e6b884ce 100644 --- a/src/actions/public/L1/getL2HashesForDepositTx.test.ts +++ b/src/actions/public/L1/getL2HashesForDepositTx.test.ts @@ -4,7 +4,7 @@ import { ethers } from 'ethers' import { expect, test } from 'vitest' import { ethersProvider } from '../../../_test/bench.js' import { publicClient } from '../../../_test/utils.js' -import { optimism } from '../../../chains/optimism.js' +import { optimismAddresses } from '../../../chains/optimism.js' import { getL2HashesForDepositTx } from './getL2HashesForDepositTx.js' test('correctly retrieves L2 hash', async () => { @@ -40,7 +40,7 @@ test('matches @eth-optimism/core-utils', async () => { }) const contract = new ethers.Contract( - optimism.opStackConfig.l1.contracts.optimismPortal.address, + optimismAddresses.portal.address, optimismPortalABI, ethersProvider, ) diff --git a/src/actions/public/L1/getOutputForL2Block.test.ts b/src/actions/public/L1/getOutputForL2Block.test.ts index 3c7529a2..3b0eff7d 100644 --- a/src/actions/public/L1/getOutputForL2Block.test.ts +++ b/src/actions/public/L1/getOutputForL2Block.test.ts @@ -1,12 +1,12 @@ import { expect, test } from 'vitest' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { getOutputForL2Block } from './getOutputForL2Block.js' test('retrieves correctly', async () => { const result = await getOutputForL2Block(publicClient, { l2BlockNumber: 2725977n, - l2Chain: base, + ...baseAddresses, }) expect(result.proposal).toBeDefined() expect(result.outputIndex).toBeDefined() diff --git a/src/actions/public/L1/getOutputForL2Block.ts b/src/actions/public/L1/getOutputForL2Block.ts index da04ff0a..6348cd8d 100644 --- a/src/actions/public/L1/getOutputForL2Block.ts +++ b/src/actions/public/L1/getOutputForL2Block.ts @@ -1,11 +1,7 @@ import { l2OutputOracleABI } from '@eth-optimism/contracts-ts' import type { Chain, Hex, PublicClient, Transport } from 'viem' import { readContract } from 'viem/actions' -import { L1ChainMismatchError, L2ChainOrAddressError } from '../../../errors/action.js' -import type { GetL2Chain, L1ActionBaseType } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' - -const CONTRACT = OpStackL1Contract.L2OutputOracle +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' export type Proposal = { outputRoot: Hex @@ -14,13 +10,9 @@ export type Proposal = { } export type GetOutputForL2BlockParameters< - TChain extends Chain | undefined = Chain, -> = - & { l2BlockNumber: bigint } - & L1ActionBaseType< - GetL2Chain, - typeof CONTRACT - > + TChain extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, +> = { l2BlockNumber: bigint; l2OutputOracle: RawOrContractAddress<_chainId> } export type GetOutputForL2BlockReturnType = { proposal: Proposal @@ -38,17 +30,10 @@ export async function getOutputForL2Block( client: PublicClient, { l2BlockNumber, - l2Chain, - l2OutputOracleAddress, + l2OutputOracle, }: GetOutputForL2BlockParameters, ): Promise { - if (l2Chain && l2Chain.opStackConfig.l1.chainId !== client.chain?.id) { - throw new L1ChainMismatchError({ chainId: client.chain?.id, opChainL1ChainId: l2Chain.opStackConfig.l1.chainId }) - } - if (!l2OutputOracleAddress && (!l2Chain || !l2Chain.opStackConfig.l1.contracts[CONTRACT])) { - throw new L2ChainOrAddressError({ contract: CONTRACT }) - } - const resolvedAddress = l2OutputOracleAddress ?? l2Chain.opStackConfig.l1.contracts[CONTRACT].address + const resolvedAddress = resolveAddress(l2OutputOracle) const outputIndex = await readContract(client, { address: resolvedAddress, abi: l2OutputOracleABI, diff --git a/src/actions/public/L1/getSecondsToFinalizable.test.ts b/src/actions/public/L1/getSecondsToFinalizable.test.ts index 3f49fbef..20302a37 100644 --- a/src/actions/public/L1/getSecondsToFinalizable.test.ts +++ b/src/actions/public/L1/getSecondsToFinalizable.test.ts @@ -1,11 +1,11 @@ import { expect, test, vi } from 'vitest' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { getSecondsToFinalizable } from './getSecondsToFinalizable.js' test('returns 0 if seconds would be negative', async () => { const seconds = await getSecondsToFinalizable(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -21,7 +21,7 @@ test('returns correctly seconds', async () => { const date = new Date(parseInt(block.timestamp.toString()) * 1000) vi.setSystemTime(date) const seconds = await getSecondsToFinalizable(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -32,7 +32,7 @@ test('returns correctly seconds', async () => { test('raises error if cannot find', async () => { expect(() => getSecondsToFinalizable(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F5EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) ).rejects.toThrowError( diff --git a/src/actions/public/L1/getSecondsToFinalizable.ts b/src/actions/public/L1/getSecondsToFinalizable.ts index ba71cb81..005d64cb 100644 --- a/src/actions/public/L1/getSecondsToFinalizable.ts +++ b/src/actions/public/L1/getSecondsToFinalizable.ts @@ -1,56 +1,39 @@ import { l2OutputOracleABI } from '@eth-optimism/contracts-ts' -import type { Address, Chain, PublicClient, Transport } from 'viem' +import type { Chain, PublicClient, ReadContractParameters, Transport } from 'viem' +import { readContract } from 'viem/actions' import type { MessagePassedEvent } from '../../../index.js' -import type { GetL2Chain, L1ActionBaseType } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { - resolveL1OpStackContractAddress, - type ResolveL1OpStackContractAddressParameters, -} from '../../../utils/resolveL1OpStackContractAddress.js' -import { readOpStackL1, type ReadOpStackL1Parameters } from './readOpStackL1.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import { readProvenWithdrawals } from './readProvenWithdrawals.js' const ABI = l2OutputOracleABI -const CONTRACT = OpStackL1Contract.L2OutputOracle export type GetSecondsToFinalizableParameters< - TChain extends Chain | undefined = Chain, -> = - & { withdrawalHash: MessagePassedEvent['withdrawalHash']; optimismPortalAddress?: Address } - & L1ActionBaseType< - GetL2Chain, - typeof CONTRACT - > + TChain extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, +> = { + withdrawalHash: MessagePassedEvent['withdrawalHash'] + portal: RawOrContractAddress<_chainId> + l2OutputOracle: RawOrContractAddress<_chainId> +} export async function getSecondsToFinalizable( client: PublicClient, { withdrawalHash, - l2OutputOracleAddress, - optimismPortalAddress, - l2Chain, - }: GetSecondsToFinalizableParameters, + l2OutputOracle, + portal, + }: GetSecondsToFinalizableParameters, ): Promise { - const resolvedPortalAddress = resolveL1OpStackContractAddress( - { - l2Chain, - chain: client.chain, - contract: OpStackL1Contract.OptimismPortal, - address: optimismPortalAddress, - } as ResolveL1OpStackContractAddressParameters, - ) const provenWithdrawal = await readProvenWithdrawals(client, { - optimismPortalAddress: resolvedPortalAddress, + portal: resolveAddress(portal), withdrawalHash, }) - const finalizationPeriod = await readOpStackL1(client, { - contract: OpStackL1Contract.L2OutputOracle, + const finalizationPeriod = await readContract(client, { abi: l2OutputOracleABI, functionName: 'FINALIZATION_PERIOD_SECONDS', - l2Chain, - address: l2OutputOracleAddress, - } as ReadOpStackL1Parameters) + address: resolveAddress(l2OutputOracle), + } as ReadContractParameters) const timeSinceProven = BigInt(Date.now()) / 1000n - provenWithdrawal.timestamp diff --git a/src/actions/public/L1/getSecondsToNextL2Output.test.ts b/src/actions/public/L1/getSecondsToNextL2Output.test.ts index ac1025a2..371f6f0f 100644 --- a/src/actions/public/L1/getSecondsToNextL2Output.test.ts +++ b/src/actions/public/L1/getSecondsToNextL2Output.test.ts @@ -1,7 +1,7 @@ import { createPublicClient, http } from 'viem' -import { mainnet } from 'viem/chains' +import { base, mainnet } from 'viem/chains' import { expect, test } from 'vitest' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { getSecondsToNextL2Output } from './getSecondsToNextL2Output.js' test('get seconds to next L2 output', async () => { @@ -16,7 +16,7 @@ test('get seconds to next L2 output', async () => { transport: http(), }) - const time = await getSecondsToNextL2Output(l1Client, { latestL2BlockNumber, l2Chain: base }) + const time = await getSecondsToNextL2Output(l1Client, { latestL2BlockNumber, ...baseAddresses }) expect(time).toBeDefined() // this is too noisy to node issues, // but I do think we should revert if latestL2BlockNumber diff --git a/src/actions/public/L1/getSecondsToNextL2Output.ts b/src/actions/public/L1/getSecondsToNextL2Output.ts index 97a570d7..3a34441d 100644 --- a/src/actions/public/L1/getSecondsToNextL2Output.ts +++ b/src/actions/public/L1/getSecondsToNextL2Output.ts @@ -1,52 +1,40 @@ import { l2OutputOracleABI } from '@eth-optimism/contracts-ts' -import type { Chain, PublicClient, Transport } from 'viem' -import type { GetL2Chain, L1ActionBaseType } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { readOpStackL1, type ReadOpStackL1Parameters } from './readOpStackL1.js' +import type { Chain, PublicClient, ReadContractParameters, Transport } from 'viem' +import { readContract } from 'viem/actions' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' const ABI = l2OutputOracleABI -const CONTRACT = OpStackL1Contract.L2OutputOracle export type GetSecondsToNextL2OutputParameters< - TChain extends Chain | undefined = Chain, -> = - & { latestL2BlockNumber: bigint } - & L1ActionBaseType< - GetL2Chain, - typeof CONTRACT - > + TChain extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, +> = { latestL2BlockNumber: bigint; l2OutputOracle: RawOrContractAddress<_chainId> } export async function getSecondsToNextL2Output( client: PublicClient, { latestL2BlockNumber, - l2OutputOracleAddress, - l2Chain, + l2OutputOracle, }: GetSecondsToNextL2OutputParameters, ): Promise { - const latestBlockNumber = await readOpStackL1(client, { - contract: CONTRACT, + const address = resolveAddress(l2OutputOracle) + const latestBlockNumber = await readContract(client, { abi: ABI, functionName: 'latestBlockNumber', - l2Chain, - address: l2OutputOracleAddress, - } as ReadOpStackL1Parameters) + address, + } as ReadContractParameters) - const interval = await readOpStackL1(client, { - contract: CONTRACT, + const interval = await readContract(client, { abi: ABI, functionName: 'SUBMISSION_INTERVAL', - l2Chain, - address: l2OutputOracleAddress, - } as ReadOpStackL1Parameters) + address, + } as ReadContractParameters) - const blockTime = await readOpStackL1(client, { - contract: CONTRACT, + const blockTime = await readContract(client, { abi: ABI, functionName: 'L2_BLOCK_TIME', - l2Chain, - address: l2OutputOracleAddress, - } as ReadOpStackL1Parameters) + address, + } as ReadContractParameters) const blocksTillUpdate = interval - (latestL2BlockNumber - latestBlockNumber) // NOTE(Wilson): incase there is some problem diff --git a/src/actions/public/L1/readFinalizedWithdrawals.test.ts b/src/actions/public/L1/readFinalizedWithdrawals.test.ts index c957186a..060dd47b 100644 --- a/src/actions/public/L1/readFinalizedWithdrawals.test.ts +++ b/src/actions/public/L1/readFinalizedWithdrawals.test.ts @@ -1,11 +1,11 @@ import { expect, test } from 'vitest' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { readFinalizedWithdrawals } from './readFinalizedWithdrawals.js' test('read finalized withdrawals', async () => { const finalizedWithdrawal = await readFinalizedWithdrawals(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -14,7 +14,7 @@ test('read finalized withdrawals', async () => { test('returns false if not finalized', async () => { const finalizedWithdrawal = await readFinalizedWithdrawals(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0C18D4889A23E74692101BA4C6DC9B5709', }) diff --git a/src/actions/public/L1/readFinalizedWithdrawals.ts b/src/actions/public/L1/readFinalizedWithdrawals.ts index a5c15819..7286534f 100644 --- a/src/actions/public/L1/readFinalizedWithdrawals.ts +++ b/src/actions/public/L1/readFinalizedWithdrawals.ts @@ -1,40 +1,34 @@ import { optimismPortalABI } from '@eth-optimism/contracts-ts' -import type { Chain, PublicClient, Transport } from 'viem' +import type { Chain, PublicClient, ReadContractParameters, Transport } from 'viem' +import { readContract } from 'viem/actions' import type { MessagePassedEvent } from '../../../index.js' -import type { GetL2Chain, L1ActionBaseType } from '../../../types/l1Actions.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { readOpStackL1, type ReadOpStackL1Parameters } from './readOpStackL1.js' const ABI = optimismPortalABI const CONTRACT = OpStackL1Contract.OptimismPortal const FUNCTION_NAME = 'finalizedWithdrawals' export type ReadFinalizedWithdrawalsParameters< - TChain extends Chain | undefined = Chain, -> = - & { withdrawalHash: MessagePassedEvent['withdrawalHash'] } - & L1ActionBaseType< - GetL2Chain, - typeof CONTRACT - > + TChain extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, +> = { withdrawalHash: MessagePassedEvent['withdrawalHash']; portal: RawOrContractAddress<_chainId> } export async function readFinalizedWithdrawals( client: PublicClient, { withdrawalHash, - optimismPortalAddress, - l2Chain, + portal, }: ReadFinalizedWithdrawalsParameters, ): Promise { - const finalizedWithdrawal = await readOpStackL1(client, { + const finalizedWithdrawal = await readContract(client, { contract: CONTRACT, abi: ABI, functionName: FUNCTION_NAME, - l2Chain, - address: optimismPortalAddress, + address: resolveAddress(portal), args: [withdrawalHash], chain: client.chain, - } as ReadOpStackL1Parameters) + } as ReadContractParameters) return finalizedWithdrawal } diff --git a/src/actions/public/L1/readOpStackL1.ts b/src/actions/public/L1/readOpStackL1.ts deleted file mode 100644 index 9e724b37..00000000 --- a/src/actions/public/L1/readOpStackL1.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { Abi, Address, Chain, Client, ReadContractParameters, ReadContractReturnType, Transport } from 'viem' -import { readContract } from 'viem/actions' -import type { GetL2Chain } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { - resolveL1OpStackContractAddress, - type ResolveL1OpStackContractAddressParameters, -} from '../../../utils/resolveL1OpStackContractAddress.js' - -export type ReadOpStackL1Parameters< - TChain extends Chain | undefined = Chain, - TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, -> = - & { contract: OpStackL1Contract; chain: TChain } - & ({ - l2Chain: GetL2Chain - address?: never - } | { - l2Chain?: never - address: Address - }) - & Omit< - ReadContractParameters< - TAbi, - TFunctionName - >, - 'address' - > - -export function readOpStackL1< - TChain extends Chain | undefined, - const TAbi extends Abi | readonly unknown[], - TFunctionName extends string, ->( - client: Client, - { - l2Chain, - contract, - address, - chain = client.chain, - ...rest - }: ReadOpStackL1Parameters, -): Promise> { - const resolvedAddress = resolveL1OpStackContractAddress( - { l2Chain, chain, contract, address } as ResolveL1OpStackContractAddressParameters, - ) - return readContract(client, { - address: resolvedAddress, - ...rest, - } as unknown as ReadContractParameters) -} diff --git a/src/actions/public/L1/readProvenWithdrawals.bench.ts b/src/actions/public/L1/readProvenWithdrawals.bench.ts index 7c1e22c4..9d87a21f 100644 --- a/src/actions/public/L1/readProvenWithdrawals.bench.ts +++ b/src/actions/public/L1/readProvenWithdrawals.bench.ts @@ -1,7 +1,7 @@ import { bench, describe } from 'vitest' import { opSDKMessenger } from '../../../_test/bench.js' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { readProvenWithdrawals } from './readProvenWithdrawals.js' describe('reads proven withdrawal', () => { @@ -10,7 +10,7 @@ describe('reads proven withdrawal', () => { 'op-viem: `readProvenWithdrawals`', async () => { await readProvenWithdrawals(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: withdrawalHash, }) }, diff --git a/src/actions/public/L1/readProvenWithdrawals.test.ts b/src/actions/public/L1/readProvenWithdrawals.test.ts index 0ed95d54..42d2e7ae 100644 --- a/src/actions/public/L1/readProvenWithdrawals.test.ts +++ b/src/actions/public/L1/readProvenWithdrawals.test.ts @@ -1,6 +1,6 @@ import { expect, test } from 'vitest' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { readProvenWithdrawals } from './readProvenWithdrawals.js' test('read proven withdrawals', async () => { @@ -11,7 +11,7 @@ test('read proven withdrawals', async () => { } const provenWithdrawal = await readProvenWithdrawals(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0B18D4889A23E74692101BA4C6DC9B5709', }) @@ -21,7 +21,7 @@ test('read proven withdrawals', async () => { test('raises error if not proven', async () => { expect(() => readProvenWithdrawals(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawalHash: '0xEC0AD491512F4EDC603C2DD7B9371A0C18D4889A23E74692101BA4C6DC9B5709', }) ).rejects.toThrowError( diff --git a/src/actions/public/L1/readProvenWithdrawals.ts b/src/actions/public/L1/readProvenWithdrawals.ts index d2c06d67..33110ea4 100644 --- a/src/actions/public/L1/readProvenWithdrawals.ts +++ b/src/actions/public/L1/readProvenWithdrawals.ts @@ -1,22 +1,16 @@ import { optimismPortalABI } from '@eth-optimism/contracts-ts' -import type { Chain, Hex, PublicClient, Transport } from 'viem' +import type { Chain, Hex, PublicClient, ReadContractParameters, Transport } from 'viem' +import { readContract } from 'viem/actions' import type { MessagePassedEvent } from '../../../index.js' -import type { GetL2Chain, L1ActionBaseType } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { readOpStackL1, type ReadOpStackL1Parameters } from './readOpStackL1.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' const ABI = optimismPortalABI -const CONTRACT = OpStackL1Contract.OptimismPortal const FUNCTION_NAME = 'provenWithdrawals' export type ReadProvenWithdrawalsParameters< - TChain extends Chain | undefined = Chain, -> = - & { withdrawalHash: MessagePassedEvent['withdrawalHash'] } - & L1ActionBaseType< - GetL2Chain, - typeof CONTRACT - > + TChain extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, +> = { withdrawalHash: MessagePassedEvent['withdrawalHash']; portal: RawOrContractAddress<_chainId> } export type ProvenWithdrawal = { outputRoot: Hex @@ -31,19 +25,16 @@ export async function readProvenWithdrawals( client: PublicClient, { withdrawalHash, - optimismPortalAddress, - l2Chain, + portal, }: ReadProvenWithdrawalsParameters, ): Promise { - const values = await readOpStackL1(client, { - contract: CONTRACT, + const values = await readContract(client, { abi: ABI, functionName: FUNCTION_NAME, - l2Chain, - address: optimismPortalAddress, + address: resolveAddress(portal), args: [withdrawalHash], chain: client.chain, - } as ReadOpStackL1Parameters) + } as ReadContractParameters) const provenWithdrawal = { outputRoot: values[0], diff --git a/src/actions/public/L1/simulateDepositERC20.test.ts b/src/actions/public/L1/simulateDepositERC20.test.ts index 3490aaaf..1119bf38 100644 --- a/src/actions/public/L1/simulateDepositERC20.test.ts +++ b/src/actions/public/L1/simulateDepositERC20.test.ts @@ -2,7 +2,7 @@ import { readContract, writeContract } from 'viem/actions' import { expect, test } from 'vitest' import { erc20ABI } from 'wagmi' import { publicClient, testClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { simulateDepositERC20 } from './simulateDepositERC20.js' const USDCL1 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' @@ -22,7 +22,7 @@ test('default', async () => { address: USDCL1, abi: erc20ABI, functionName: 'approve', - args: [base.opStackConfig.l1.contracts.l1StandardBridge.address, 10000n], + args: [baseAddresses.l1StandardBridge.address, 10000n], account: zenaddress, }) const balanceBefore = await readContract(testClient, { @@ -40,7 +40,7 @@ test('default', async () => { amount: 1n, minGasLimit: 100000, }, - l2Chain: base, + ...baseAddresses, account: zenaddress, }) diff --git a/src/actions/public/L1/simulateDepositERC20.ts b/src/actions/public/L1/simulateDepositERC20.ts index 3c8395b8..ba028375 100644 --- a/src/actions/public/L1/simulateDepositERC20.ts +++ b/src/actions/public/L1/simulateDepositERC20.ts @@ -1,14 +1,16 @@ import type { Chain, PublicClient, SimulateContractReturnType, Transport } from 'viem' -import { ABI, CONTRACT, type DepositERC20Parameters, FUNCTION } from '../../../types/depositERC20.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' +import { ABI, type DepositERC20Parameters, FUNCTION } from '../../../types/depositERC20.js' import type { L1SimulateActionBaseType } from '../../../types/l1Actions.js' import { simulateOpStackL1, type SimulateOpStackL1Parameters } from './simulateOpStackL1.js' export type SimulateDepositERC20Parameters< TChain extends Chain | undefined = Chain, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: DepositERC20Parameters } - & L1SimulateActionBaseType + & { args: DepositERC20Parameters; l1StandardBridge: RawOrContractAddress<_chainId> } + & L1SimulateActionBaseType export type SimulateDepositERC20ReturnType< TChain extends Chain | undefined, @@ -27,14 +29,13 @@ export async function simulateDepositERC20< client: PublicClient, { args: { l1Token, l2Token, to, amount, minGasLimit, extraData = '0x' }, - l1StandardBridgeAddress, + l1StandardBridge, ...rest }: SimulateDepositERC20Parameters, ): Promise> { return simulateOpStackL1(client, { - address: l1StandardBridgeAddress, + address: resolveAddress(l1StandardBridge), abi: ABI, - contract: CONTRACT, functionName: FUNCTION, args: [l1Token, l2Token, to, amount, minGasLimit, extraData], ...rest, diff --git a/src/actions/public/L1/simulateDepositETH.test.ts b/src/actions/public/L1/simulateDepositETH.test.ts index 05c9dd1a..3e53778f 100644 --- a/src/actions/public/L1/simulateDepositETH.test.ts +++ b/src/actions/public/L1/simulateDepositETH.test.ts @@ -2,7 +2,7 @@ import { writeContract } from 'viem/actions' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { simulateDepositETH } from './simulateDepositETH.js' test('default', async () => { @@ -12,8 +12,8 @@ test('default', async () => { gasLimit: 100000, }, value: 1n, - l2Chain: base, account: accounts[0].address, + ...baseAddresses, }) expect(request).toBeDefined() expect(await writeContract(walletClient, request)).toBeDefined() diff --git a/src/actions/public/L1/simulateDepositETH.ts b/src/actions/public/L1/simulateDepositETH.ts index ac50a0ca..671772f1 100644 --- a/src/actions/public/L1/simulateDepositETH.ts +++ b/src/actions/public/L1/simulateDepositETH.ts @@ -1,14 +1,16 @@ import type { Chain, PublicClient, SimulateContractReturnType, Transport } from 'viem' -import { ABI, CONTRACT, type DepositETHParameters, FUNCTION } from '../../../types/depositETH.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' +import { ABI, type DepositETHParameters, FUNCTION } from '../../../types/depositETH.js' import type { L1SimulateActionBaseType } from '../../../types/l1Actions.js' import { simulateOpStackL1, type SimulateOpStackL1Parameters } from './simulateOpStackL1.js' export type SimulateDepositETHParameters< TChain extends Chain | undefined = Chain, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: DepositETHParameters } - & L1SimulateActionBaseType + & { args: DepositETHParameters; portal: RawOrContractAddress<_chainId> } + & L1SimulateActionBaseType export type SimulateDepositETHReturnType< TChain extends Chain | undefined, @@ -27,15 +29,14 @@ export async function simulateDepositETH< client: PublicClient, { args: { to, gasLimit, data = '0x' }, - optimismPortalAddress, + portal, value, ...rest }: SimulateDepositETHParameters, ): Promise> { return simulateOpStackL1(client, { - address: optimismPortalAddress, + address: resolveAddress(portal), abi: ABI, - contract: CONTRACT, functionName: FUNCTION, args: [to, value, gasLimit, false, data], value, diff --git a/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.test.ts b/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.test.ts index 4043dd82..d96dffe5 100644 --- a/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.test.ts +++ b/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.test.ts @@ -1,26 +1,27 @@ import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { type FinalizeWithdrawalTransactionParameters } from '../../wallet/L1/writeFinalizeWithdrawalTransaction.js' import { simulateFinalizeWithdrawalTransaction } from './simulateFinalizeWithdrawalTransaction.js' +// From https://etherscan.io/tx/0xcb571be93844895a45a4cf70cc4424fcc6ccf55dd4c14759da1efd57fa593ac5 test('succesfully submits finalizeWithdrawalTransaction', async () => { const withdrawal: FinalizeWithdrawalTransactionParameters = { - nonce: 1766847064778384329583297500742918515827483896875618958121606201292641795n, - sender: '0x02f086dBC384d69b3041BC738F0a8af5e49dA181', - target: '0x02f086dBC384d69b3041BC738F0a8af5e49dA181', - value: 335000000000000000000n, + nonce: 1766847064778384329583297500742918515827483896875618958121606201292642114n, + sender: '0x54392fc895e6e44538975272E0dD7335fCcC9045', + target: '0x54392fc895e6e44538975272E0dD7335fCcC9045', + value: 20000000000000000n, gasLimit: 100000n, data: '0x01', } const { request } = await simulateFinalizeWithdrawalTransaction(publicClient, { - l2Chain: base, + ...baseAddresses, withdrawal, account: accounts[0].address, }) - expect(request.address).toEqual(base.opStackConfig.l1.contracts.optimismPortal.address) + expect(request.address).toEqual(baseAddresses.portal.address) expect(request.args[0]).toEqual(withdrawal) }) diff --git a/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.ts b/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.ts index 79b4b99d..1686f5f8 100644 --- a/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.ts +++ b/src/actions/public/L1/simulateFinalizeWithdrawalTransaction.ts @@ -1,8 +1,8 @@ import type { Chain, PublicClient, SimulateContractReturnType, Transport } from 'viem' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import { type L1SimulateActionBaseType } from '../../../types/l1Actions.js' import { ABI, - CONTRACT, type FinalizeWithdrawalTransactionParameters, FUNCTION, } from '../../wallet/L1/writeFinalizeWithdrawalTransaction.js' @@ -11,13 +11,13 @@ import { simulateOpStackL1, type SimulateOpStackL1Parameters } from './simulateO export type SimulateFinalizeWithdrawalTransactionParameters< TChain extends Chain | undefined = Chain, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { withdrawal: FinalizeWithdrawalTransactionParameters } + & { withdrawal: FinalizeWithdrawalTransactionParameters; portal: RawOrContractAddress<_chainId> } & L1SimulateActionBaseType< TChain, TChainOverride, typeof ABI, - typeof CONTRACT, typeof FUNCTION > @@ -44,7 +44,7 @@ export async function simulateFinalizeWithdrawalTransaction< client: PublicClient, { withdrawal, - optimismPortalAddress, + portal, ...rest }: SimulateFinalizeWithdrawalTransactionParameters< TChain, @@ -52,9 +52,8 @@ export async function simulateFinalizeWithdrawalTransaction< >, ): Promise> { return simulateOpStackL1(client, { - address: optimismPortalAddress, + address: resolveAddress(portal), abi: ABI, - contract: CONTRACT, functionName: FUNCTION, args: [withdrawal], ...rest, diff --git a/src/actions/public/L1/simulateOpStackL1.ts b/src/actions/public/L1/simulateOpStackL1.ts index ae473a44..e9b029b2 100644 --- a/src/actions/public/L1/simulateOpStackL1.ts +++ b/src/actions/public/L1/simulateOpStackL1.ts @@ -1,11 +1,5 @@ import type { Abi, Address, Chain, PublicClient, Transport } from 'viem' import { simulateContract, type SimulateContractParameters, type SimulateContractReturnType } from 'viem/actions' -import type { GetL2Chain, ResolveChain } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { - resolveL1OpStackContractAddress, - type ResolveL1OpStackContractAddressParameters, -} from '../../../utils/resolveL1OpStackContractAddress.js' export type SimulateOpStackL1Parameters< TChain extends Chain | undefined = Chain, @@ -13,14 +7,7 @@ export type SimulateOpStackL1Parameters< TAbi extends Abi | readonly unknown[] = Abi, TFunctionName extends string = string, > = - & { contract: OpStackL1Contract; chain: TChain | TChainOverride } - & ({ - l2Chain: GetL2Chain> - address?: never - } | { - l2Chain?: never - address: Address - }) + & { chain: TChain | TChainOverride; address: Address } & Omit< SimulateContractParameters< TAbi, @@ -39,18 +26,12 @@ export function simulateOpStackL1< >( client: PublicClient, { - l2Chain, - contract, address, - chain = client.chain, ...rest }: SimulateOpStackL1Parameters, ): Promise> { - const resolvedAddress = resolveL1OpStackContractAddress( - { l2Chain, chain, contract, address } as ResolveL1OpStackContractAddressParameters, - ) return simulateContract(client, { - address: resolvedAddress, + address, ...rest, } as unknown as SimulateContractParameters< TAbi, diff --git a/src/actions/public/L1/simulateProveWithdrawalTransaction.test.ts b/src/actions/public/L1/simulateProveWithdrawalTransaction.test.ts index 195600ed..8ecc45a3 100644 --- a/src/actions/public/L1/simulateProveWithdrawalTransaction.test.ts +++ b/src/actions/public/L1/simulateProveWithdrawalTransaction.test.ts @@ -1,7 +1,7 @@ import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { type ProveWithdrawalTransactionParameters } from '../../wallet/L1/writeProveWithdrawalTransaction.js' import { simulateProveWithdrawalTransaction } from './simulateProveWithdrawalTransaction.js' @@ -35,7 +35,7 @@ const args: ProveWithdrawalTransactionParameters = { test('productes correct tx', async () => { const { request } = await simulateProveWithdrawalTransaction(publicClient, { args, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) expect(request.args).toEqual([ @@ -44,5 +44,5 @@ test('productes correct tx', async () => { args.outputRootProof, args.withdrawalProof, ]) - expect(request.address).toEqual(base.opStackConfig.l1.contracts.optimismPortal.address) + expect(request.address).toEqual(baseAddresses.portal.address) }) diff --git a/src/actions/public/L1/simulateProveWithdrawalTransaction.ts b/src/actions/public/L1/simulateProveWithdrawalTransaction.ts index 28d85719..5f0794d9 100644 --- a/src/actions/public/L1/simulateProveWithdrawalTransaction.ts +++ b/src/actions/public/L1/simulateProveWithdrawalTransaction.ts @@ -1,8 +1,8 @@ import type { Chain, PublicClient, SimulateContractReturnType, Transport } from 'viem' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import { type L1SimulateActionBaseType } from '../../../types/l1Actions.js' import { ABI, - CONTRACT, FUNCTION, type ProveWithdrawalTransactionParameters, } from '../../wallet/L1/writeProveWithdrawalTransaction.js' @@ -11,13 +11,13 @@ import { simulateOpStackL1, type SimulateOpStackL1Parameters } from './simulateO export type SimulateProveWithdrawalTransactionParameters< TChain extends Chain | undefined = Chain, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: ProveWithdrawalTransactionParameters } + & { args: ProveWithdrawalTransactionParameters; portal: RawOrContractAddress<_chainId> } & L1SimulateActionBaseType< TChain, TChainOverride, typeof ABI, - typeof CONTRACT, typeof FUNCTION > @@ -45,7 +45,7 @@ export async function simulateProveWithdrawalTransaction< client: PublicClient, { args: { withdrawalTransaction, outputRootProof, withdrawalProof, L2OutputIndex }, - optimismPortalAddress, + portal, ...rest }: SimulateProveWithdrawalTransactionParameters< TChain, @@ -53,9 +53,8 @@ export async function simulateProveWithdrawalTransaction< >, ): Promise> { return simulateOpStackL1(client, { - address: optimismPortalAddress, + address: resolveAddress(portal), abi: ABI, - contract: CONTRACT, functionName: FUNCTION, args: [withdrawalTransaction, L2OutputIndex, outputRootProof, withdrawalProof], ...rest, diff --git a/src/actions/public/L2/getProveWithdrawalTransactionArgs.bench.ts b/src/actions/public/L2/getProveWithdrawalTransactionArgs.bench.ts index b4e66501..d6bc372f 100644 --- a/src/actions/public/L2/getProveWithdrawalTransactionArgs.bench.ts +++ b/src/actions/public/L2/getProveWithdrawalTransactionArgs.bench.ts @@ -1,10 +1,10 @@ import { CrossChainMessenger } from '@eth-optimism/sdk' import { providers } from 'ethers' import { createPublicClient, http } from 'viem' -import { mainnet } from 'viem/chains' +import { base, mainnet } from 'viem/chains' import { bench, describe } from 'vitest' import { forkUrl, rollupForkUrl } from '../../../_test/constants.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { getOutputForL2Block } from '../L1/getOutputForL2Block.js' import { getProveWithdrawalTransactionArgs } from './getProveWithdrawalTransactionArgs.js' import { getWithdrawalMessages } from './getWithdrawalMessages.js' @@ -31,7 +31,7 @@ describe('Computes L1 prove args from L2 tx hash', () => { const output = await getOutputForL2Block(l1Client, { l2BlockNumber: withdrawalMessages.blockNumber, - l2Chain: base, + ...baseAddresses, }) await getProveWithdrawalTransactionArgs(client, { diff --git a/src/actions/public/L2/getProveWithdrawalTransactionArgs.test.ts b/src/actions/public/L2/getProveWithdrawalTransactionArgs.test.ts index 24337656..1dc4936c 100644 --- a/src/actions/public/L2/getProveWithdrawalTransactionArgs.test.ts +++ b/src/actions/public/L2/getProveWithdrawalTransactionArgs.test.ts @@ -1,9 +1,9 @@ import { createPublicClient, http } from 'viem' -import { mainnet } from 'viem/chains' +import { base, mainnet } from 'viem/chains' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { writeProveWithdrawalTransaction } from '../../index.js' import { getOutputForL2Block } from '../L1/getOutputForL2Block.js' import { getProveWithdrawalTransactionArgs } from './getProveWithdrawalTransactionArgs.js' @@ -46,7 +46,7 @@ test('correctly generates args', async () => { const output = await getOutputForL2Block(l1Client, { l2BlockNumber: withdrawalMessages.blockNumber, - l2Chain: base, + ...baseAddresses, }) // TODO(wilson): We should simplify these test to not require so much setup ^ @@ -64,7 +64,7 @@ test('correctly generates args', async () => { const hash = await writeProveWithdrawalTransaction(walletClient, { args, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) expect(hash).toBeDefined() diff --git a/src/actions/wallet/L1/writeContractDeposit.test.ts b/src/actions/wallet/L1/writeContractDeposit.test.ts index 8590142d..fd2884f6 100644 --- a/src/actions/wallet/L1/writeContractDeposit.test.ts +++ b/src/actions/wallet/L1/writeContractDeposit.test.ts @@ -5,7 +5,7 @@ import { expect, test } from 'vitest' import { erc721ABI } from 'wagmi' import { accounts } from '../../../_test/constants.js' import { publicClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { parseOpaqueData } from '../../../utils/getArgsFromTransactionDepositedOpaqueData.js' import { writeContractDeposit } from './writeContractDeposit.js' @@ -20,7 +20,7 @@ test('default', async () => { args, account: accounts[0].address, l2GasLimit, - l2Chain: base, + ...baseAddresses, }) await mine(testClient, { blocks: 1 }) @@ -66,7 +66,7 @@ test('throws error if strict = true and account is smart contract wallet', async args, account: scw_address, l2GasLimit, - l2Chain: base, + ...baseAddresses, }) ).rejects.toThrowError( 'Calling depositTransaction from a smart contract can have unexpected results, see https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md#address-aliasing. Set `strict` to false to disable this check.', @@ -93,8 +93,8 @@ test('allows smart contract wallet if strict = false', async () => { args, account: scw_address, l2GasLimit, - l2Chain: base, strict: false, + ...baseAddresses, }), ).toBeDefined() }) @@ -111,7 +111,7 @@ test('throws error if no account passed', async () => { functionName, args, l2GasLimit, - l2Chain: base, + ...baseAddresses, }) ).rejects.toThrowError( 'No account found', diff --git a/src/actions/wallet/L1/writeContractDeposit.ts b/src/actions/wallet/L1/writeContractDeposit.ts index 51b664f7..4ec49a8e 100644 --- a/src/actions/wallet/L1/writeContractDeposit.ts +++ b/src/actions/wallet/L1/writeContractDeposit.ts @@ -12,8 +12,7 @@ import { } from 'viem' import { getBytecode } from 'viem/actions' import { parseAccount } from 'viem/utils' -import { OpStackL1Contract } from '../../../index.js' -import type { GetL2Chain, L1ActionBaseType, ResolveChain } from '../../../types/l1Actions.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import { writeDepositTransaction, type WriteDepositTransactionParameters } from './writeDepositTransaction.js' export type WriteContractDepositParameters< @@ -22,9 +21,15 @@ export type WriteContractDepositParameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { account: TAccount | Address; l2GasLimit: bigint; l2MsgValue?: bigint; strict?: boolean } - & L1ActionBaseType>, typeof OpStackL1Contract.OptimismPortal> + & { + account: TAccount | Address + l2GasLimit: bigint + l2MsgValue?: bigint + strict?: boolean + portal: RawOrContractAddress<_chainId> + } & Omit< WriteContractParameters< TAbi, @@ -63,8 +68,7 @@ export async function writeContractDeposit< functionName, l2GasLimit, l2MsgValue = 0n, - l2Chain, - optimismPortalAddress, + portal, strict = true, ...request }: WriteContractDepositParameters< @@ -94,8 +98,7 @@ export async function writeContractDeposit< } } return writeDepositTransaction(client, { - optimismPortalAddress, - l2Chain, + portal: resolveAddress(portal), args: { gasLimit: l2GasLimit, to: address, data: calldata, value: l2MsgValue }, account, ...request, diff --git a/src/actions/wallet/L1/writeDepositERC20.test.ts b/src/actions/wallet/L1/writeDepositERC20.test.ts index 03e4e024..3f874c5c 100644 --- a/src/actions/wallet/L1/writeDepositERC20.test.ts +++ b/src/actions/wallet/L1/writeDepositERC20.test.ts @@ -2,7 +2,7 @@ import { mine, writeContract } from 'viem/actions' import { expect, test } from 'vitest' import { erc20ABI } from 'wagmi' import { publicClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { writeDepositERC20 } from './writeDepositERC20.js' const USDCL1 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' @@ -21,7 +21,7 @@ test('default', async () => { address: USDCL1, abi: erc20ABI, functionName: 'approve', - args: [base.opStackConfig.l1.contracts.l1StandardBridge.address, 10000n], + args: [baseAddresses.l1StandardBridge.address, 10000n], account: zenaddress, }) await mine(testClient, { blocks: 1 }) @@ -34,7 +34,7 @@ test('default', async () => { minGasLimit: 21000, extraData: '0x', }, - l2Chain: base, + ...baseAddresses, account: zenaddress, }) await mine(testClient, { blocks: 1 }) diff --git a/src/actions/wallet/L1/writeDepositERC20.ts b/src/actions/wallet/L1/writeDepositERC20.ts index 35a9f51a..34f633d9 100644 --- a/src/actions/wallet/L1/writeDepositERC20.ts +++ b/src/actions/wallet/L1/writeDepositERC20.ts @@ -1,21 +1,20 @@ -import type { Account, Chain, Transport, WalletClient, WriteContractReturnType } from 'viem' +import type { Account, Chain, Transport, WalletClient, WriteContractParameters, WriteContractReturnType } from 'viem' +import { writeContract } from 'viem/actions' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import { ABI, CONTRACT, type DepositERC20Parameters, FUNCTION } from '../../../types/depositERC20.js' import type { L1WriteActionBaseType } from '../../../types/l1Actions.js' -import { writeOpStackL1, type WriteOpStackL1Parameters } from './writeOpStackL1.js' export type WriteDepositERC20Parameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: DepositERC20Parameters } + & { args: DepositERC20Parameters; l1StandardBridge: RawOrContractAddress<_chainId> } & L1WriteActionBaseType< TChain, TAccount, - TChainOverride, - typeof ABI, - typeof CONTRACT, - typeof FUNCTION + TChainOverride > /** @@ -31,7 +30,7 @@ export async function writeDepositERC20< client: WalletClient, { args: { l1Token, l2Token, to, amount, minGasLimit, extraData = '0x' }, - l1StandardBridgeAddress, + l1StandardBridge, ...rest }: WriteDepositERC20Parameters< TChain, @@ -39,18 +38,18 @@ export async function writeDepositERC20< TChainOverride >, ): Promise { - return writeOpStackL1(client, { - address: l1StandardBridgeAddress, + return writeContract(client, { + address: resolveAddress(l1StandardBridge), abi: ABI, contract: CONTRACT, functionName: FUNCTION, args: [l1Token, l2Token, to, amount, minGasLimit, extraData], ...rest, - } as unknown as WriteOpStackL1Parameters< + } as unknown as WriteContractParameters< + typeof ABI, + typeof FUNCTION, TChain, TAccount, - TChainOverride, - typeof ABI, - typeof FUNCTION + TChainOverride >) } diff --git a/src/actions/wallet/L1/writeDepositETH.test.ts b/src/actions/wallet/L1/writeDepositETH.test.ts index 9c74cf45..974a0643 100644 --- a/src/actions/wallet/L1/writeDepositETH.test.ts +++ b/src/actions/wallet/L1/writeDepositETH.test.ts @@ -4,7 +4,7 @@ import { mine } from 'viem/actions' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import type { DepositETHParameters, TransactionDepositedEvent } from '../../../index.js' import { writeDepositETH } from './writeDepositETH.js' @@ -17,7 +17,7 @@ test('default', async () => { data: '0x', }, value: 1n, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }), ).toBeDefined() @@ -33,7 +33,7 @@ test('correctly deposits ETH', async () => { const hash = await writeDepositETH(walletClient, { args, value, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) diff --git a/src/actions/wallet/L1/writeDepositETH.ts b/src/actions/wallet/L1/writeDepositETH.ts index 5ea24b17..2b8a3d28 100644 --- a/src/actions/wallet/L1/writeDepositETH.ts +++ b/src/actions/wallet/L1/writeDepositETH.ts @@ -1,5 +1,6 @@ import type { Account, Chain, Transport, WalletClient, WriteContractReturnType } from 'viem' -import { ABI, CONTRACT, type DepositETHParameters, FUNCTION } from '../../../types/depositETH.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' +import { type DepositETHParameters } from '../../../types/depositETH.js' import type { L1WriteActionBaseType } from '../../../types/l1Actions.js' import { writeDepositTransaction, type WriteDepositTransactionParameters } from './writeDepositTransaction.js' @@ -7,15 +8,13 @@ export type WriteDepositETHParameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: DepositETHParameters } + & { args: DepositETHParameters; portal: RawOrContractAddress<_chainId> } & L1WriteActionBaseType< TChain, TAccount, - TChainOverride, - typeof ABI, - typeof CONTRACT, - typeof FUNCTION + TChainOverride > /** @@ -31,7 +30,7 @@ export async function writeDepositETH< client: WalletClient, { args: { to, gasLimit, data }, - optimismPortalAddress, + portal, value, ...rest }: WriteDepositETHParameters< @@ -42,7 +41,7 @@ export async function writeDepositETH< ): Promise { return writeDepositTransaction(client, { args: { to, value, gasLimit: BigInt(gasLimit), data }, - optimismPortalAddress, + portal: resolveAddress(portal), value, ...rest, } as unknown as WriteDepositTransactionParameters< diff --git a/src/actions/wallet/L1/writeDepositTransaction.test.ts b/src/actions/wallet/L1/writeDepositTransaction.test.ts index 8ae6cc67..f985c1d6 100644 --- a/src/actions/wallet/L1/writeDepositTransaction.test.ts +++ b/src/actions/wallet/L1/writeDepositTransaction.test.ts @@ -3,10 +3,9 @@ import { type Address, decodeEventLog, encodeFunctionData, encodePacked } from ' import { estimateGas, mine } from 'viem/actions' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' -import { publicClient, rollupPublicClient, rollupWalletClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { publicClient, rollupPublicClient, testClient, walletClient } from '../../../_test/utils.js' +import { baseAddresses } from '../../../chains/index.js' import { type TransactionDepositedEvent } from '../../../types/depositTransaction.js' -import type { OpStackChain } from '../../../types/opStackChain.js' import { type DepositTransactionParameters, writeDepositTransaction } from './writeDepositTransaction.js' test('default', async () => { @@ -20,7 +19,7 @@ test('default', async () => { isCreation: false, }, value: 0n, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }), ).toBeDefined() @@ -47,7 +46,7 @@ test('sends transaction to correct infered address', async () => { const hash = await writeDepositTransaction(walletClient, { args, value: 1n, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) @@ -55,7 +54,7 @@ test('sends transaction to correct infered address', async () => { const r = await publicClient.getTransactionReceipt({ hash }) expect(r.to).toEqual( - base.opStackConfig.l1.contracts.optimismPortal.address.toLowerCase(), + baseAddresses.portal.address.toLowerCase(), ) }) @@ -68,7 +67,7 @@ test('sends transaction to correct explicit address', async () => { gasLimit: 25000n, }, value: 1n, - optimismPortalAddress: portal, + portal: portal, account: accounts[0].address, }) @@ -89,7 +88,7 @@ test('creates correct deposit transaction', async () => { const hash = await writeDepositTransaction(walletClient, { args, value: args.value!, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) @@ -124,7 +123,7 @@ test('correctly passes arugments', async () => { const hash = await writeDepositTransaction(walletClient, { args, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, value: 2n, }) @@ -150,7 +149,7 @@ test('uses defaults for data, isCreation, and value', async () => { const hash = await writeDepositTransaction(walletClient, { args, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, value: 0n, }) @@ -167,7 +166,7 @@ test('uses defaults for data, isCreation, and value', async () => { ) }) -test('errors if l2Chain and optimismPortalAddress both not passed', async () => { +test('errors if portal not passed', async () => { expect(() => // @ts-expect-error writeDepositTransaction(walletClient, { @@ -178,55 +177,5 @@ test('errors if l2Chain and optimismPortalAddress both not passed', async () => value: 0n, account: accounts[0].address, }) - ).rejects.toThrowError('Must provide either l2Chain or optimismPortalAddress') -}) - -test('errors if chain.id does not match l1.chainId', async () => { - const baseAlt = { - ...base, - opStackConfig: { - l1: { - ...base.opStackConfig.l1, - chainId: 2, - }, - }, - } as const satisfies OpStackChain - - expect(() => - writeDepositTransaction(walletClient, { - args: { - to: '0x0c54fccd2e384b4bb6f2e405bf5cbc15a017aafb', - gasLimit: 25000n, - }, - value: 0n, - // @ts-expect-error - l2Chain: baseAlt, - account: accounts[0].address, - }) - ).rejects.toThrowError('Chain ID "1" does not match expected L1 chain ID "2"') -}) - -test('works if override chain id matches l1.id', async () => { - const baseAlt = { - ...base, - opStackConfig: { - l1: { - ...base.opStackConfig.l1, - chainId: 8453, - }, - }, - } as const satisfies OpStackChain - - expect( - await writeDepositTransaction(walletClient, { - args: { - to: '0x0c54fccd2e384b4bb6f2e405bf5cbc15a017aafb', - gasLimit: 25000n, - }, - value: 0n, - l2Chain: baseAlt, - chain: rollupWalletClient.chain, - account: accounts[0].address, - }), - ).toBeDefined() + ).rejects.toThrowError('Invalid address') }) diff --git a/src/actions/wallet/L1/writeDepositTransaction.ts b/src/actions/wallet/L1/writeDepositTransaction.ts index 542d49bd..0159599d 100644 --- a/src/actions/wallet/L1/writeDepositTransaction.ts +++ b/src/actions/wallet/L1/writeDepositTransaction.ts @@ -1,8 +1,18 @@ import { optimismPortalABI } from '@eth-optimism/contracts-ts' -import type { Account, Address, Chain, Hex, Transport, WalletClient, WriteContractReturnType } from 'viem' +import type { + Account, + Address, + Chain, + Hex, + Transport, + WalletClient, + WriteContractParameters, + WriteContractReturnType, +} from 'viem' +import { writeContract } from 'viem/actions' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import type { L1WriteActionBaseType } from '../../../types/l1Actions.js' import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { writeOpStackL1, type WriteOpStackL1Parameters } from './writeOpStackL1.js' const ABI = optimismPortalABI const CONTRACT = OpStackL1Contract.OptimismPortal @@ -20,15 +30,13 @@ export type WriteDepositTransactionParameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: DepositTransactionParameters } + & { args: DepositTransactionParameters; portal: RawOrContractAddress<_chainId> } & L1WriteActionBaseType< TChain, TAccount, - TChainOverride, - typeof ABI, - typeof CONTRACT, - typeof FUNCTION + TChainOverride > /** @@ -54,7 +62,7 @@ export async function writeDepositTransaction< client: WalletClient, { args: { to, value = 0n, gasLimit, isCreation = false, data = '0x' }, - optimismPortalAddress, + portal, ...rest }: WriteDepositTransactionParameters< TChain, @@ -62,18 +70,18 @@ export async function writeDepositTransaction< TChainOverride >, ): Promise { - return writeOpStackL1(client, { - address: optimismPortalAddress, + return writeContract(client, { + address: resolveAddress(portal), abi: ABI, contract: CONTRACT, functionName: FUNCTION, args: [to, value, gasLimit, isCreation, data], ...rest, - } as unknown as WriteOpStackL1Parameters< + } as unknown as WriteContractParameters< + typeof ABI, + typeof FUNCTION, TChain, TAccount, - TChainOverride, - typeof ABI, - typeof FUNCTION + TChainOverride >) } diff --git a/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.test.ts b/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.test.ts index 78e87ae0..82a8acba 100644 --- a/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.test.ts +++ b/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.test.ts @@ -2,12 +2,13 @@ import { mine } from 'viem/actions' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { type FinalizeWithdrawalTransactionParameters, writeFinalizeWithdrawalTranasction, } from './writeFinalizeWithdrawalTransaction.js' +// From https://etherscan.io/tx/0x33b540f3ae33049ecb19c83a62fe15ad41dc38ccce4cf0eaf92c55431031f1b5 test('succesfully submits finalizeWithdrawalTransaction', async () => { const withdrawal: FinalizeWithdrawalTransactionParameters = { nonce: 1766847064778384329583297500742918515827483896875618958121606201292641795n, @@ -19,7 +20,7 @@ test('succesfully submits finalizeWithdrawalTransaction', async () => { } const hash = await writeFinalizeWithdrawalTranasction(walletClient, { - l2Chain: base, + ...baseAddresses, withdrawal, account: accounts[0].address, }) diff --git a/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.ts b/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.ts index f5b614cc..02ae1927 100644 --- a/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.ts +++ b/src/actions/wallet/L1/writeFinalizeWithdrawalTransaction.ts @@ -1,9 +1,11 @@ import { optimismPortalABI } from '@eth-optimism/contracts-ts' -import type { Account, Chain, Transport, WalletClient, WriteContractReturnType } from 'viem' +import type { Account, Chain, Transport, WalletClient, WriteContractParameters, WriteContractReturnType } from 'viem' +import { writeContract } from 'viem/actions' +import type { _ } from 'vitest/dist/reporters-cb94c88b.js' import type { MessagePassedEvent } from '../../../index.js' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import type { L1WriteActionBaseType } from '../../../types/l1Actions.js' import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { writeOpStackL1, type WriteOpStackL1Parameters } from './writeOpStackL1.js' export const ABI = optimismPortalABI export const CONTRACT = OpStackL1Contract.OptimismPortal @@ -15,15 +17,13 @@ export type WriteFinalizeWithdrawalTransactionParameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { withdrawal: FinalizeWithdrawalTransactionParameters } + & { withdrawal: FinalizeWithdrawalTransactionParameters; portal: RawOrContractAddress<_chainId> } & L1WriteActionBaseType< TChain, TAccount, - TChainOverride, - typeof ABI, - typeof CONTRACT, - typeof FUNCTION + TChainOverride > /** @@ -41,7 +41,7 @@ export async function writeFinalizeWithdrawalTranasction< client: WalletClient, { withdrawal, - optimismPortalAddress, + portal, ...rest }: WriteFinalizeWithdrawalTransactionParameters< TChain, @@ -49,18 +49,18 @@ export async function writeFinalizeWithdrawalTranasction< TChainOverride >, ): Promise { - return writeOpStackL1(client, { - address: optimismPortalAddress, + return writeContract(client, { + address: resolveAddress(portal), abi: ABI, contract: CONTRACT, functionName: FUNCTION, args: [withdrawal], ...rest, - } as unknown as WriteOpStackL1Parameters< + } as unknown as WriteContractParameters< + typeof ABI, + typeof FUNCTION, TChain, TAccount, - TChainOverride, - typeof ABI, - typeof FUNCTION + TChainOverride >) } diff --git a/src/actions/wallet/L1/writeOpStackL1.ts b/src/actions/wallet/L1/writeOpStackL1.ts deleted file mode 100644 index fb4c9681..00000000 --- a/src/actions/wallet/L1/writeOpStackL1.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { - Abi, - Account, - Address, - Chain, - Transport, - WalletClient, - WriteContractParameters, - WriteContractReturnType, -} from 'viem' -import { writeContract } from 'viem/actions' -import type { GetL2Chain, ResolveChain } from '../../../types/l1Actions.js' -import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { - resolveL1OpStackContractAddress, - type ResolveL1OpStackContractAddressParameters, -} from '../../../utils/resolveL1OpStackContractAddress.js' - -export type WriteOpStackL1Parameters< - TChain extends Chain | undefined = Chain, - TAccount extends Account | undefined = Account | undefined, - TChainOverride extends Chain | undefined = Chain | undefined, - TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, -> = - & { contract: OpStackL1Contract; chain: TChain | TChainOverride } - & ({ - l2Chain: GetL2Chain> - address?: never - } | { - l2Chain?: never - address: Address - }) - & Omit< - WriteContractParameters< - TAbi, - TFunctionName, - TChain, - TAccount, - TChainOverride - >, - 'address' | 'chain' - > - -export function writeOpStackL1< - TChain extends Chain | undefined, - TAccount extends Account | undefined, - TChainOverride extends Chain | undefined = undefined, - const TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, ->( - client: WalletClient, - { - l2Chain, - contract, - address, - chain = client.chain, - ...rest - }: WriteOpStackL1Parameters, -): Promise { - const resolvedAddress = resolveL1OpStackContractAddress( - { l2Chain, chain, contract, address } as ResolveL1OpStackContractAddressParameters, - ) - return writeContract(client, { - address: resolvedAddress, - ...rest, - } as unknown as WriteContractParameters< - TAbi, - TFunctionName, - TChain, - TAccount, - TChainOverride - >) -} diff --git a/src/actions/wallet/L1/writeProveWithdrawalTransaction.test.ts b/src/actions/wallet/L1/writeProveWithdrawalTransaction.test.ts index db803f58..973ad2ca 100644 --- a/src/actions/wallet/L1/writeProveWithdrawalTransaction.test.ts +++ b/src/actions/wallet/L1/writeProveWithdrawalTransaction.test.ts @@ -2,7 +2,7 @@ import { mine } from 'viem/actions' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/base.js' +import { baseAddresses } from '../../../chains/base.js' import { type ProveWithdrawalTransactionParameters, writeProveWithdrawalTransaction, @@ -38,7 +38,7 @@ const args: ProveWithdrawalTransactionParameters = { test('succesfuly submits a proveWithdrawalTranasction', async () => { const hash = await writeProveWithdrawalTransaction(walletClient, { args, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) await mine(testClient, { blocks: 1 }) diff --git a/src/actions/wallet/L1/writeProveWithdrawalTransaction.ts b/src/actions/wallet/L1/writeProveWithdrawalTransaction.ts index 89b2f80e..7acc4550 100644 --- a/src/actions/wallet/L1/writeProveWithdrawalTransaction.ts +++ b/src/actions/wallet/L1/writeProveWithdrawalTransaction.ts @@ -1,9 +1,10 @@ import { optimismPortalABI } from '@eth-optimism/contracts-ts' -import type { Account, Chain, Transport, WalletClient, WriteContractReturnType } from 'viem' +import type { Account, Chain, Transport, WalletClient, WriteContractParameters, WriteContractReturnType } from 'viem' +import { writeContract } from 'viem/actions' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import type { L1WriteActionBaseType } from '../../../types/l1Actions.js' import { OpStackL1Contract } from '../../../types/opStackContracts.js' import type { GetProveWithdrawalTransactionArgsReturnType } from '../../index.js' -import { writeOpStackL1, type WriteOpStackL1Parameters } from './writeOpStackL1.js' export const ABI = optimismPortalABI export const CONTRACT = OpStackL1Contract.OptimismPortal @@ -15,15 +16,13 @@ export type WriteProveWithdrawalTransactionParameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: ProveWithdrawalTransactionParameters } + & { args: ProveWithdrawalTransactionParameters; portal: RawOrContractAddress<_chainId> } & L1WriteActionBaseType< TChain, TAccount, - TChainOverride, - typeof ABI, - typeof CONTRACT, - typeof FUNCTION + TChainOverride > /** @@ -41,7 +40,7 @@ export async function writeProveWithdrawalTransaction< client: WalletClient, { args: { withdrawalTransaction, outputRootProof, withdrawalProof, L2OutputIndex }, - optimismPortalAddress, + portal, ...rest }: WriteProveWithdrawalTransactionParameters< TChain, @@ -49,18 +48,18 @@ export async function writeProveWithdrawalTransaction< TChainOverride >, ): Promise { - return writeOpStackL1(client, { - address: optimismPortalAddress, + return writeContract(client, { + address: resolveAddress(portal), abi: ABI, contract: CONTRACT, functionName: FUNCTION, args: [withdrawalTransaction, L2OutputIndex, outputRootProof, withdrawalProof], ...rest, - } as unknown as WriteOpStackL1Parameters< + } as unknown as WriteContractParameters< + typeof ABI, + typeof FUNCTION, TChain, TAccount, - TChainOverride, - typeof ABI, - typeof FUNCTION + TChainOverride >) } diff --git a/src/actions/wallet/L1/writeSendMessage.test.ts b/src/actions/wallet/L1/writeSendMessage.test.ts index ece913a5..0d9e00ca 100644 --- a/src/actions/wallet/L1/writeSendMessage.test.ts +++ b/src/actions/wallet/L1/writeSendMessage.test.ts @@ -4,7 +4,7 @@ import { mine } from 'viem/actions' import { expect, test } from 'vitest' import { accounts } from '../../../_test/constants.js' import { publicClient, testClient, walletClient } from '../../../_test/utils.js' -import { base } from '../../../chains/index.js' +import { baseAddresses } from '../../../chains/index.js' import { writeSendMessage } from './writeSendMessage.js' test('can successfully call sendsMessage', async () => { @@ -15,7 +15,7 @@ test('can successfully call sendsMessage', async () => { const hash = await writeSendMessage(walletClient, { args, value: 0n, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) @@ -48,7 +48,7 @@ test('passes correct calldata to sendMessage', async () => { const hash = await writeSendMessage(walletClient, { args, value: 0n, - l2Chain: base, + ...baseAddresses, account: accounts[0].address, }) diff --git a/src/actions/wallet/L1/writeSendMessage.ts b/src/actions/wallet/L1/writeSendMessage.ts index a73df9cd..9319e742 100644 --- a/src/actions/wallet/L1/writeSendMessage.ts +++ b/src/actions/wallet/L1/writeSendMessage.ts @@ -1,8 +1,18 @@ import { l1CrossDomainMessengerABI } from '@eth-optimism/contracts-ts' -import type { Account, Address, Chain, Hex, Transport, WalletClient, WriteContractReturnType } from 'viem' +import type { + Account, + Address, + Chain, + Hex, + Transport, + WalletClient, + WriteContractParameters, + WriteContractReturnType, +} from 'viem' +import { writeContract } from 'viem/actions' +import { type RawOrContractAddress, resolveAddress } from '../../../types/addresses.js' import type { L1WriteActionBaseType } from '../../../types/l1Actions.js' import { OpStackL1Contract } from '../../../types/opStackContracts.js' -import { writeOpStackL1, type WriteOpStackL1Parameters } from './writeOpStackL1.js' const ABI = l1CrossDomainMessengerABI const CONTRACT = OpStackL1Contract.L1CrossDomainMessenger @@ -18,15 +28,13 @@ export type WriteSendMessageParameters< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, + _chainId = TChain extends Chain ? TChain['id'] : number, > = - & { args: SendMessageParameters } + & { args: SendMessageParameters; l1CrossDomainMessenger: RawOrContractAddress<_chainId> } & L1WriteActionBaseType< TChain, TAccount, - TChainOverride, - typeof ABI, - typeof CONTRACT, - typeof FUNCTION + TChainOverride > /** @@ -44,7 +52,7 @@ export async function writeSendMessage< client: WalletClient, { args: { target, minGasLimit, message = '0x' }, - l1CrossDomainMessengerAddress, + l1CrossDomainMessenger, ...rest }: WriteSendMessageParameters< TChain, @@ -52,18 +60,18 @@ export async function writeSendMessage< TChainOverride >, ): Promise { - return writeOpStackL1(client, { - address: l1CrossDomainMessengerAddress, + return writeContract(client, { + address: resolveAddress(l1CrossDomainMessenger), abi: ABI, contract: CONTRACT, functionName: FUNCTION, args: [target, message, minGasLimit], ...rest, - } as unknown as WriteOpStackL1Parameters< + } as unknown as WriteContractParameters< + typeof ABI, + typeof FUNCTION, TChain, TAccount, - TChainOverride, - typeof ABI, - typeof FUNCTION + TChainOverride >) } diff --git a/src/actions/wallet/L2/writeOpStackL2.ts b/src/actions/wallet/L2/writeOpStackL2.ts deleted file mode 100644 index fba4b130..00000000 --- a/src/actions/wallet/L2/writeOpStackL2.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { - Abi, - Account, - Chain, - Transport, - WalletClient, - WriteContractParameters, - WriteContractReturnType, -} from 'viem' -import { writeContract } from 'viem/actions' -import { opStackL2ChainContracts, OpStackL2Contract } from '../../../types/opStackContracts.js' - -export type WriteOpStackL2Parameters< - TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, - TChain extends Chain | undefined = Chain, - TAccount extends Account | undefined = Account | undefined, - TChainOverride extends Chain | undefined = Chain | undefined, -> = - & { contract: OpStackL2Contract } - & Omit< - WriteContractParameters< - TAbi, - TFunctionName, - TChain, - TAccount, - TChainOverride - >, - 'address' - > - -export function writeOpStackL2< - TChain extends Chain | undefined, - TAccount extends Account | undefined, - TChainOverride extends Chain | undefined = undefined, - const TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, ->( - client: WalletClient, - { - contract, - ...rest - }: WriteOpStackL2Parameters, -): Promise { - return writeContract(client, { - // TODO(Wilson): consider pulling this from chain.contracts - // so that it will have a better error if they are not on an L2 chain - address: opStackL2ChainContracts[contract].address, - ...rest, - } as unknown as WriteContractParameters< - TAbi, - TFunctionName, - TChain, - TAccount, - TChainOverride - >) -} diff --git a/src/actions/wallet/L2/writeWithdrawERC20.ts b/src/actions/wallet/L2/writeWithdrawERC20.ts index b30523de..bf3b97f5 100644 --- a/src/actions/wallet/L2/writeWithdrawERC20.ts +++ b/src/actions/wallet/L2/writeWithdrawERC20.ts @@ -1,8 +1,8 @@ -import type { Account, Chain, Transport, WalletClient, WriteContractReturnType } from 'viem' +import type { Account, Chain, Transport, WalletClient, WriteContractParameters, WriteContractReturnType } from 'viem' +import { writeContract } from 'viem/actions' import type { L2WriteContractParameters } from '../../../types/l2Actions.js' -import { OpStackL2Contract } from '../../../types/opStackContracts.js' +import { opStackL2ChainContracts, OpStackL2Contract } from '../../../types/opStackContracts.js' import { ABI, FUNCTION, type WithdrawToParameters } from '../../../types/withdrawTo.js' -import { writeOpStackL2, type WriteOpStackL2Parameters } from './writeOpStackL2.js' export type WriteWithdrawERC20Parameters< TChain extends Chain | undefined = Chain, @@ -24,13 +24,13 @@ export async function writeWithdrawERC20< TAccount, TChainOverride >): Promise { - return writeOpStackL2(client, { + return writeContract(client, { abi: ABI, functionName: FUNCTION, args: [l2Token, to, amount, minGasLimit, extraData], - contract: OpStackL2Contract.L2StandardBridge, + address: opStackL2ChainContracts[OpStackL2Contract.L2StandardBridge].address, ...rest, - } as unknown as WriteOpStackL2Parameters< + } as unknown as WriteContractParameters< typeof ABI, typeof FUNCTION, TChain, diff --git a/src/chains/base.ts b/src/chains/base.ts index fc9e9433..84e7b61b 100644 --- a/src/chains/base.ts +++ b/src/chains/base.ts @@ -1,38 +1,29 @@ -import { base as viemBase, mainnet } from 'viem/chains' -import type { OpStackChain } from '../types/opStackChain.js' -import { opStackL2ChainContracts } from '../types/opStackContracts.js' +import { type Addresses } from '../types/addresses.js' -export const base: OpStackChain & { opStackConfig: { l1: { chainId: typeof mainnet['id'] } } } = { - ...viemBase, - contracts: { - ...viemBase.contracts, - ...opStackL2ChainContracts, +export const baseAddresses: Addresses<1> = { + portal: { + address: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e', + chainId: 1, + blockCreated: 17482143, }, - opStackConfig: { - l1: { - chainId: 1, - contracts: { - l1CrossDomainMessenger: { - address: '0x866E82a600A1414e583f7F13623F1aC5d58b0Afa', - blockCreated: 17482143, - }, - l1Erc721Bridge: { - address: '0x608d94945A64503E642E6370Ec598e519a2C1E53', - blockCreated: 17482143, - }, - l1StandardBridge: { - address: '0x3154Cf16ccdb4C6d922629664174b904d80F2C35', - blockCreated: 17482143, - }, - l2OutputOracle: { - address: '0x56315b90c40730925ec5485cf004d835058518A0', - blockCreated: 17482143, - }, - optimismPortal: { - address: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e', - blockCreated: 17482143, - }, - }, - }, + l2OutputOracle: { + address: '0x56315b90c40730925ec5485cf004d835058518A0', + chainId: 1, + blockCreated: 17482143, }, -} as const satisfies OpStackChain + l1StandardBridge: { + address: '0x3154Cf16ccdb4C6d922629664174b904d80F2C35', + chainId: 1, + blockCreated: 17482143, + }, + l1CrossDomainMessenger: { + address: '0x866E82a600A1414e583f7F13623F1aC5d58b0Afa', + chainId: 1, + blockCreated: 17482143, + }, + l1Erc721Bridge: { + address: '0x608d94945A64503E642E6370Ec598e519a2C1E53', + chainId: 1, + blockCreated: 17482143, + }, +} as const diff --git a/src/chains/baseGoerli.ts b/src/chains/baseGoerli.ts index 3ae3fda8..7b09bd6e 100644 --- a/src/chains/baseGoerli.ts +++ b/src/chains/baseGoerli.ts @@ -1,33 +1,24 @@ -import { baseGoerli as viemChain, goerli } from 'viem/chains' -import type { OpStackChain } from '../types/opStackChain.js' -import { opStackL2ChainContracts } from '../types/opStackContracts.js' +import type { Addresses } from '../types/addresses.js' -export const baseGoerli: OpStackChain & { opStackConfig: { l1: { chainId: typeof goerli['id'] } } } = { - ...viemChain, - contracts: { - ...viemChain.contracts, - ...opStackL2ChainContracts, +export const baseGoerliAddresses: Addresses<5> = { + portal: { + address: '0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA', + chainId: 5, }, - opStackConfig: { - l1: { - chainId: 5, - contracts: { - l1CrossDomainMessenger: { - address: '0x8e5693140eA606bcEB98761d9beB1BC87383706D', - }, - l1Erc721Bridge: { - address: '0x5E0c967457347D5175bF82E8CCCC6480FCD7e568', - }, - l1StandardBridge: { - address: '0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a', - }, - l2OutputOracle: { - address: '0x2A35891ff30313CcFa6CE88dcf3858bb075A2298', - }, - optimismPortal: { - address: '0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA', - }, - }, - }, + l2OutputOracle: { + address: '0x2A35891ff30313CcFa6CE88dcf3858bb075A2298', + chainId: 5, }, -} as const satisfies OpStackChain + l1StandardBridge: { + address: '0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a', + chainId: 5, + }, + l1CrossDomainMessenger: { + address: '0x8e5693140eA606bcEB98761d9beB1BC87383706D', + chainId: 5, + }, + l1Erc721Bridge: { + address: '0x5E0c967457347D5175bF82E8CCCC6480FCD7e568', + chainId: 5, + }, +} as const diff --git a/src/chains/index.ts b/src/chains/index.ts index 4bc5e737..6ba5a4ef 100644 --- a/src/chains/index.ts +++ b/src/chains/index.ts @@ -1,6 +1,6 @@ -export { base } from './base.js' -export { baseGoerli } from './baseGoerli.js' -export { optimism } from './optimism.js' -export { optimismGoerli } from './optimismGoerli.js' -export { zora } from './zora.js' -export { zoraGoerli } from './zoraGoerli.js' +export { baseAddresses } from './base.js' +export { baseGoerliAddresses } from './baseGoerli.js' +export { optimismAddresses } from './optimism.js' +export { optimismGoerliAddresses } from './optimismGoerli.js' +export { zoraAddresses } from './zora.js' +export { zoraGoerliAddresses } from './zoraGoerli.js' diff --git a/src/chains/optimism.ts b/src/chains/optimism.ts index f20b6229..0698fe90 100644 --- a/src/chains/optimism.ts +++ b/src/chains/optimism.ts @@ -1,38 +1,29 @@ -import { mainnet, optimism as viemOptimism } from 'viem/chains' -import type { OpStackChain } from '../types/opStackChain.js' -import { opStackL2ChainContracts } from '../types/opStackContracts.js' +import type { Addresses } from '../types/addresses.js' -export const optimism: OpStackChain & { opStackConfig: { l1: { chainId: typeof mainnet['id'] } } } = { - ...viemOptimism, - contracts: { - ...viemOptimism.contracts, - ...opStackL2ChainContracts, +export const optimismAddresses: Addresses<1> = { + portal: { + address: '0xbEb5Fc579115071764c7423A4f12eDde41f106Ed', + chainId: 1, + blockCreated: 17365802, }, - opStackConfig: { - l1: { - chainId: 1, - contracts: { - l1CrossDomainMessenger: { - address: '0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1', - blockCreated: 12686757, - }, - l1Erc721Bridge: { - address: '0x5a7749f83b81B301cAb5f48EB8516B986DAef23D', - blockCreated: 15677422, - }, - l1StandardBridge: { - address: '0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1', - blockCreated: 12686786, - }, - l2OutputOracle: { - address: '0xdfe97868233d1aa22e815a266982f2cf17685a27', - blockCreated: 17365801, - }, - optimismPortal: { - address: '0xbEb5Fc579115071764c7423A4f12eDde41f106Ed', - blockCreated: 17365802, - }, - }, - }, + l2OutputOracle: { + address: '0xdfe97868233d1aa22e815a266982f2cf17685a27', + chainId: 1, + blockCreated: 17365801, }, -} as const satisfies OpStackChain + l1StandardBridge: { + address: '0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1', + chainId: 1, + blockCreated: 12686786, + }, + l1CrossDomainMessenger: { + address: '0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1', + chainId: 1, + blockCreated: 12686757, + }, + l1Erc721Bridge: { + address: '0x5a7749f83b81B301cAb5f48EB8516B986DAef23D', + chainId: 1, + blockCreated: 15677422, + }, +} as const diff --git a/src/chains/optimismGoerli.ts b/src/chains/optimismGoerli.ts index bc637f6c..eecf71df 100644 --- a/src/chains/optimismGoerli.ts +++ b/src/chains/optimismGoerli.ts @@ -1,34 +1,24 @@ -import { goerli, optimismGoerli as viemOptimismGoerli } from 'viem/chains' -import type { OpStackChain } from '../types/opStackChain.js' -import { opStackL2ChainContracts } from '../types/opStackContracts.js' +import type { Addresses } from '../types/addresses.js' -export const optimismGoerli: OpStackChain & { opStackConfig: { l1: { chainId: typeof goerli['id'] } } } = { - ...viemOptimismGoerli, - contracts: { - ...viemOptimismGoerli.contracts, - ...opStackL2ChainContracts, +export const optimismGoerliAddresses: Addresses<5> = { + portal: { + address: '0x9e760aBd847E48A56b4a348Cba56Ae7267FeCE80', + chainId: 5, }, - opStackConfig: { - l1: { - chainId: 5, - contracts: { - l1Erc721Bridge: { - address: '0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9', - blockCreated: 7682740, - }, - l1CrossDomainMessenger: { - address: '0x9D1dACf9d9299D17EFFE1aAd559c06bb3Fbf9BC4', - }, - l1StandardBridge: { - address: '0x636Af16bf2f682dD3109e60102b8E1A089FedAa8', - }, - l2OutputOracle: { - address: '0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0', - }, - optimismPortal: { - address: '0x9e760aBd847E48A56b4a348Cba56Ae7267FeCE80', - }, - }, - }, + l2OutputOracle: { + address: '0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0', + chainId: 5, }, -} as const satisfies OpStackChain + l1StandardBridge: { + address: '0x636Af16bf2f682dD3109e60102b8E1A089FedAa8', + chainId: 5, + }, + l1CrossDomainMessenger: { + address: '0x9D1dACf9d9299D17EFFE1aAd559c06bb3Fbf9BC4', + chainId: 5, + }, + l1Erc721Bridge: { + address: '0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9', + chainId: 5, + }, +} as const diff --git a/src/chains/zora.ts b/src/chains/zora.ts index fceeee72..514f8a29 100644 --- a/src/chains/zora.ts +++ b/src/chains/zora.ts @@ -1,40 +1,29 @@ -import { mainnet, zora as viemZora } from 'viem/chains' -import type { OpStackChain } from '../types/opStackChain.js' -import { opStackL2ChainContracts } from '../types/opStackContracts.js' +import type { Addresses } from '../types/addresses.js' -export const zora: OpStackChain & { - opStackConfig: { l1: { chainId: (typeof mainnet)['id'] } } -} = { - ...viemZora, - contracts: { - ...viemZora.contracts, - ...opStackL2ChainContracts, +export const zoraAddresses: Addresses<1> = { + portal: { + address: '0x1a0ad011913A150f69f6A19DF447A0CfD9551054', + chainId: 1, + blockCreated: 17473938, }, - opStackConfig: { - l1: { - chainId: 1, - contracts: { - l1CrossDomainMessenger: { - address: '0x363B4B1ADa52E50353f746999bd9E94395190d2C', - blockCreated: 17473943, - }, - l1Erc721Bridge: { - address: '0x83A4521A3573Ca87f3a971B169C5A0E1d34481c3', - blockCreated: 17473940, - }, - l1StandardBridge: { - address: '0xbF6acaF315477b15D638bf4d91eA48FA79b58335', - blockCreated: 17473944, - }, - l2OutputOracle: { - address: '0x9E6204F750cD866b299594e2aC9eA824E2e5f95c', - blockCreated: 17473936, - }, - optimismPortal: { - address: '0x1a0ad011913A150f69f6A19DF447A0CfD9551054', - blockCreated: 17473938, - }, - }, - }, + l2OutputOracle: { + address: '0x9E6204F750cD866b299594e2aC9eA824E2e5f95c', + chainId: 1, + blockCreated: 17473936, }, -} as const satisfies OpStackChain + l1StandardBridge: { + address: '0xbF6acaF315477b15D638bf4d91eA48FA79b58335', + chainId: 1, + blockCreated: 17473944, + }, + l1CrossDomainMessenger: { + address: '0x363B4B1ADa52E50353f746999bd9E94395190d2C', + chainId: 1, + blockCreated: 17473943, + }, + l1Erc721Bridge: { + address: '0x83A4521A3573Ca87f3a971B169C5A0E1d34481c3', + chainId: 1, + blockCreated: 17473940, + }, +} as const diff --git a/src/chains/zoraGoerli.ts b/src/chains/zoraGoerli.ts index 361d3023..871f4b8e 100644 --- a/src/chains/zoraGoerli.ts +++ b/src/chains/zoraGoerli.ts @@ -1,40 +1,29 @@ -import { goerli, zoraTestnet as viemZoraTestnet } from 'viem/chains' -import type { OpStackChain } from '../types/opStackChain.js' -import { opStackL2ChainContracts } from '../types/opStackContracts.js' +import type { Addresses } from '../types/addresses.js' -export const zoraGoerli: OpStackChain & { - opStackConfig: { l1: { chainId: (typeof goerli)['id'] } } -} = { - ...viemZoraTestnet, - contracts: { - ...viemZoraTestnet.contracts, - ...opStackL2ChainContracts, +export const zoraGoerliAddresses: Addresses<5> = { + portal: { + address: '0xDb9F51790365e7dc196e7D072728df39Be958ACe', + chainId: 5, + blockCreated: 8942392, }, - opStackConfig: { - l1: { - chainId: 5, - contracts: { - l1CrossDomainMessenger: { - address: '0x9779A9D2f3B66A4F4d27cB99Ab6cC1266b3Ca9af', - blockCreated: 8942397, - }, - l1Erc721Bridge: { - address: '0x57C1C6b596ce90C0e010c358DD4Aa052404bB70F', - blockCreated: 8942394, - }, - l1StandardBridge: { - address: '0x39CCDe9769d52d61189AB799d91665A11b5f3464', - blockCreated: 8942398, - }, - l2OutputOracle: { - address: '0xdD292C9eEd00f6A32Ff5245d0BCd7f2a15f24e00', - blockCreated: 8942390, - }, - optimismPortal: { - address: '0xDb9F51790365e7dc196e7D072728df39Be958ACe', - blockCreated: 8942392, - }, - }, - }, + l2OutputOracle: { + address: '0xdD292C9eEd00f6A32Ff5245d0BCd7f2a15f24e00', + chainId: 5, + blockCreated: 8942390, }, -} as const satisfies OpStackChain + l1StandardBridge: { + address: '0x39CCDe9769d52d61189AB799d91665A11b5f3464', + chainId: 5, + blockCreated: 8942398, + }, + l1CrossDomainMessenger: { + address: '0x9779A9D2f3B66A4F4d27cB99Ab6cC1266b3Ca9af', + chainId: 5, + blockCreated: 8942397, + }, + l1Erc721Bridge: { + address: '0x57C1C6b596ce90C0e010c358DD4Aa052404bB70F', + chainId: 5, + blockCreated: 8942394, + }, +} as const diff --git a/src/decorators/publicL1OpStackActions.ts b/src/decorators/publicL1OpStackActions.ts index 328c4982..9ccc4864 100644 --- a/src/decorators/publicL1OpStackActions.ts +++ b/src/decorators/publicL1OpStackActions.ts @@ -1,4 +1,4 @@ -import type { Abi, Chain, PublicClient, ReadContractReturnType, Transport } from 'viem' +import type { Chain, PublicClient, Transport } from 'viem' import { getL2HashesForDepositTx, type GetL2HashesForDepositTxParamters, @@ -21,7 +21,6 @@ import { readFinalizedWithdrawals, type ReadFinalizedWithdrawalsParameters, } from '../actions/public/L1/readFinalizedWithdrawals.js' -import { readOpStackL1, type ReadOpStackL1Parameters } from '../actions/public/L1/readOpStackL1.js' import { readProvenWithdrawals, type ReadProvenWithdrawalsParameters, @@ -73,10 +72,6 @@ export type PublicL1OpStackActions< getSecondsToFinalizable: (args: GetSecondsToFinalizableParameters) => Promise readProvenWithdrawals: (args: ReadProvenWithdrawalsParameters) => Promise readFinalizedWithdrawals: (args: ReadFinalizedWithdrawalsParameters) => Promise - readOpStackL1: < - const TAbi extends Abi | readonly unknown[], - TFunctionName extends string, - >(args: ReadOpStackL1Parameters) => Promise> } export function publicL1OpStackActions< @@ -95,6 +90,5 @@ export function publicL1OpStackActions< getSecondsToFinalizable: (args) => getSecondsToFinalizable(client, args), readProvenWithdrawals: (args) => readProvenWithdrawals(client, args), readFinalizedWithdrawals: (args) => readFinalizedWithdrawals(client, args), - readOpStackL1: (args) => readOpStackL1(client, args), } } diff --git a/src/errors/action.ts b/src/errors/action.ts deleted file mode 100644 index b4aee759..00000000 --- a/src/errors/action.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Chain } from 'viem' -import { BaseError } from 'viem' -import type { OpStackChain } from '../types/opStackChain.js' - -export class L1ChainMismatchError extends BaseError { - override name = 'L1ChainMismatchError' - constructor( - { chainId, opChainL1ChainId }: { - chainId: Chain['id'] | undefined - opChainL1ChainId: OpStackChain['opStackConfig']['l1']['chainId'] - }, - ) { - super( - `Chain ID "${chainId}" does not match expected L1 chain ID "${opChainL1ChainId}"`, - ) - } -} - -export class L2ChainOrAddressError extends BaseError { - override name = 'L2ChainOrAddressError' - constructor({ contract }: { contract: string }) { - super( - `Must provide either l2Chain or ${contract}Address"`, - ) - } -} diff --git a/src/index.ts b/src/index.ts index db598424..bb1f34c0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,6 @@ export type { GasPriceOracleParameters, OracleTransactionParameters, } from './types/gasPriceOracle.js' -export type { OpStackChain, OpStackConfig } from './types/opStackChain.js' export { OpStackL1Contract, type OpStackL2ChainContracts, diff --git a/src/types/addresses.ts b/src/types/addresses.ts new file mode 100644 index 00000000..3a44ac8a --- /dev/null +++ b/src/types/addresses.ts @@ -0,0 +1,17 @@ +import { type Address } from 'viem' + +export type ContractAddress = { address: Address; chainId: chainId; blockCreated?: number } +export type Addresses = { + portal: ContractAddress + l2OutputOracle: ContractAddress + l1StandardBridge: ContractAddress + l1CrossDomainMessenger: ContractAddress + l1Erc721Bridge: ContractAddress +} + +export type RawOrContractAddress = Address | ContractAddress + +export function resolveAddress(address: RawOrContractAddress): `0x${string}` { + if (typeof address !== 'string' && !address?.address) throw new Error('Invalid address') + return typeof address === 'string' ? address : address.address +} diff --git a/src/types/l1Actions.ts b/src/types/l1Actions.ts index 7dff38ac..fef14e12 100644 --- a/src/types/l1Actions.ts +++ b/src/types/l1Actions.ts @@ -1,68 +1,24 @@ -import type { Abi, Account, Address, Chain, SimulateContractParameters, WriteContractParameters } from 'viem' -import type { OpStackChain } from './opStackChain.js' -import type { OpStackL1Contract } from './opStackContracts.js' - -export type ResolveChain< - TChain extends Chain | undefined, - TChainOverride extends Chain | undefined = undefined, -> = TChainOverride extends Chain ? TChainOverride : TChain - -export type GetL2Chain = TChain extends Chain - ? OpStackChain & { opStackConfig: { l1: { chainId: TChain['id'] } } } - : never - -export type L1ActionBaseType< - TL2Chain extends OpStackChain, - TContract extends OpStackL1Contract, -> = - | ({ - l2Chain: TL2Chain - } & { [k in `${TContract}Address`]?: never }) - | ({ - l2Chain?: never - } & { [k in `${TContract}Address`]: Address }) +import type { Abi, Account, Chain, SendTransactionParameters, SimulateContractParameters } from 'viem' export type L1WriteActionBaseType< TChain extends Chain | undefined = Chain, TAccount extends Account | undefined = Account | undefined, TChainOverride extends Chain | undefined = Chain | undefined, - TAbi extends Abi | readonly unknown[] = Abi, - TContract extends OpStackL1Contract = OpStackL1Contract, - TFunctioName extends string = string, -> = - & GetChain - & L1ActionBaseType>, TContract> - & Omit< - WriteContractParameters< - TAbi, - TFunctioName, - TChain, - TAccount, - TChainOverride - >, - 'abi' | 'functionName' | 'args' | 'address' | 'chain' - > -type GetChain< - TChain extends Chain | undefined, - TChainOverride extends Chain | undefined = undefined, -> = TChain extends Chain ? { chain?: TChainOverride | null } - : { chain: TChainOverride | null } +> = Omit< + SendTransactionParameters< + TChain, + TAccount, + TChainOverride + >, + 'chain' +> export type L1SimulateActionBaseType< TChain extends Chain | undefined = Chain, TChainOverride extends Chain | undefined = Chain | undefined, TAbi extends Abi | readonly unknown[] = Abi, - TContract extends OpStackL1Contract = OpStackL1Contract, TFunctioName extends string = string, - _resolvedChain = ResolveChain, - _l2 extends - | (_resolvedChain extends Chain ? OpStackChain & { opStackConfig: { l1: { chainId: _resolvedChain['id'] } } } - : never) - | never = never, -> = - & GetChain - & L1ActionBaseType>, TContract> - & Omit< - SimulateContractParameters, - 'abi' | 'functionName' | 'args' | 'address' - > +> = Omit< + SimulateContractParameters, + 'abi' | 'functionName' | 'args' | 'address' +> diff --git a/src/types/opStackChain.ts b/src/types/opStackChain.ts deleted file mode 100644 index 6b18649a..00000000 --- a/src/types/opStackChain.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { type Chain, type ChainContract } from 'viem' -import { OpStackL1Contract, type OpStackL2ChainContracts } from './opStackContracts.js' - -export type OpStackChain = Chain & { - contracts: OpStackL2ChainContracts - opStackConfig: OpStackConfig -} - -export type OpStackConfig = { - l1: { - chainId: number - contracts: { - [key in OpStackL1Contract]: ChainContract - } - } -} diff --git a/src/types/opStackContracts.ts b/src/types/opStackContracts.ts index 81559482..fcaeeb36 100644 --- a/src/types/opStackContracts.ts +++ b/src/types/opStackContracts.ts @@ -5,7 +5,7 @@ export enum OpStackL1Contract { L1Erc721Bridge = 'l1Erc721Bridge', L1StandardBridge = 'l1StandardBridge', L2OutputOracle = 'l2OutputOracle', - OptimismPortal = 'optimismPortal', + OptimismPortal = 'portal', } export enum OpStackL2Contract { diff --git a/src/utils/getDepositTransaction.test.ts b/src/utils/getDepositTransaction.test.ts index adfa1aee..5f5024ea 100644 --- a/src/utils/getDepositTransaction.test.ts +++ b/src/utils/getDepositTransaction.test.ts @@ -5,7 +5,7 @@ import { getTransactionReceipt } from 'viem/actions' import { expect, test } from 'vitest' import { ethersProvider } from '../_test/bench.js' import { publicClient } from '../_test/utils.js' -import { optimism } from '../chains/optimism.js' +import { optimismAddresses } from '../chains/optimism.js' import { SourceHashDomain } from '../types/depositTransaction.js' import { getDepositTransaction } from './getDepositTransaction.js' import { getSourceHash } from './getSourceHash.js' @@ -16,7 +16,7 @@ import { getTransactionDepositedEvents } from './getTransactionDepositedEvents.j // if debugging again in the future. test('derives same values as op-ethereum/core-utils', async () => { const contract = new ethers.Contract( - optimism.opStackConfig.l1.contracts.optimismPortal.address, + optimismAddresses.portal.address, optimismPortalABI, ethersProvider, ) diff --git a/src/utils/getL2HashFromL1DepositInfo.bench.ts b/src/utils/getL2HashFromL1DepositInfo.bench.ts index 4d0ae669..b88b9b89 100644 --- a/src/utils/getL2HashFromL1DepositInfo.bench.ts +++ b/src/utils/getL2HashFromL1DepositInfo.bench.ts @@ -5,7 +5,7 @@ import { getTransactionReceipt } from 'viem/actions' import { bench, describe } from 'vitest' import { ethersProvider } from '../_test/bench.js' import { publicClient } from '../_test/utils.js' -import { base } from '../chains/index.js' +import { baseAddresses } from '../chains/index.js' import { getL2HashFromL1DepositInfo } from './getL2HashFromL1DepositInfo.js' import { getTransactionDepositedEvents } from './getTransactionDepositedEvents.js' @@ -23,7 +23,7 @@ describe('Obtain L2 hash from already fetched event', async () => { }) const contract = new ethers.Contract( - base.opStackConfig.l1.contracts.optimismPortal.address, + baseAddresses.portal.address, optimismPortalABI, ethersProvider, ) diff --git a/src/utils/resolveL1OpStackContractAddress.test.ts b/src/utils/resolveL1OpStackContractAddress.test.ts deleted file mode 100644 index eb5abdb4..00000000 --- a/src/utils/resolveL1OpStackContractAddress.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { Chain } from 'viem' -import { expect, test } from 'vitest' -import { publicClient } from '../_test/utils.js' -import { base } from '../chains/base.js' -import { OpStackL1Contract } from '../types/opStackContracts.js' -import { resolveL1OpStackContractAddress } from './resolveL1OpStackContractAddress.js' - -test('resolves Base OptimismPortal contract address', async () => { - const resolvedPortalAddress = await resolveL1OpStackContractAddress( - { - l2Chain: base, - chain: publicClient.chain, - contract: OpStackL1Contract.OptimismPortal, - }, - ) - - expect(resolvedPortalAddress).toEqual('0x49048044D57e1C92A77f79988d21Fa8fAF74E97e') -}) - -test('returns address if provided', async () => { - const resolvedAddress = resolveL1OpStackContractAddress( - { - l2Chain: undefined, - chain: publicClient.chain, - contract: OpStackL1Contract.OptimismPortal, - address: '0x0000000000000000000000000000000000000001', - }, - ) - - expect(resolvedAddress).toEqual('0x0000000000000000000000000000000000000001') -}) - -test('raises error if chain undefined', async () => { - await expect(async () => - resolveL1OpStackContractAddress( - // @ts-expect-error - { - l2Chain: undefined, - chain: publicClient.chain, - contract: OpStackL1Contract.OptimismPortal, - }, - ) - ).rejects.toThrowError('Must provide either l2Chain or optimismPortalAddress') -}) - -test('raises error if L1 mismatch', async () => { - // Create a mock of publicClient with the modified chain ID - const mockClient = { ...publicClient, chain: { id: 0 } as Chain } - - await expect(async () => - resolveL1OpStackContractAddress( - { - l2Chain: base, - chain: mockClient.chain, - contract: OpStackL1Contract.OptimismPortal, - }, - ) - ).rejects.toThrowError('Chain ID "0" does not match expected L1 chain ID "1"') -}) diff --git a/src/utils/resolveL1OpStackContractAddress.ts b/src/utils/resolveL1OpStackContractAddress.ts deleted file mode 100644 index 8f70b224..00000000 --- a/src/utils/resolveL1OpStackContractAddress.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { Address, Chain } from 'viem' -import { L1ChainMismatchError, L2ChainOrAddressError } from '../errors/action.js' -import type { GetL2Chain } from '../types/l1Actions.js' -import type { OpStackL1Contract } from '../types/opStackContracts.js' - -export type ResolveL1OpStackContractAddressParameters< - TChain extends Chain | undefined = Chain, - TChainOverride extends Chain | undefined = Chain | undefined, -> = - & { contract: OpStackL1Contract; chain: TChain | TChainOverride } - & ({ - l2Chain: GetL2Chain - address?: never - } | { - l2Chain?: never - address: Address - }) - -export function resolveL1OpStackContractAddress< - TChain extends Chain | undefined, - TChainOverride extends Chain | undefined = undefined, ->( - { l2Chain, chain, contract, address }: ResolveL1OpStackContractAddressParameters, -) { - if (l2Chain && l2Chain.opStackConfig.l1.chainId !== chain?.id) { - throw new L1ChainMismatchError({ chainId: chain?.id, opChainL1ChainId: l2Chain.opStackConfig.l1.chainId }) - } - if (!address && (!l2Chain || !l2Chain.opStackConfig.l1.contracts[contract])) { - throw new L2ChainOrAddressError({ contract }) - } - return address ?? l2Chain.opStackConfig.l1.contracts[contract].address -} diff --git a/vitest.config.ts b/vitest.config.ts index bb648109..586c162c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -16,10 +16,10 @@ export default defineConfig({ // maxThreads: 1, // minThreads: 1, coverage: { - lines: 97.47, - statements: 97.47, - functions: 90.47, - branches: 91.46, + lines: 97.54, + statements: 97.54, + functions: 90, + branches: 93.82, thresholdAutoUpdate: true, reporter: ['text', 'json-summary', 'json'], exclude: [