From cb52bf751cbcf46cb874eef29bcc98889724bc27 Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 14 Nov 2024 15:32:50 +0000 Subject: [PATCH 1/3] WIP --- src/experimental/arbitrumDeposit/actions.ts | 90 ------------------- .../arbitrumDeposit/depositEth.ts | 32 +++++++ .../arbitrumDeposit/publicActions.ts | 16 ++++ .../arbitrumDeposit/sendDepositEth.ts | 22 +++++ .../arbitrumDeposit/walletActions.ts | 16 ++++ 5 files changed, 86 insertions(+), 90 deletions(-) delete mode 100644 src/experimental/arbitrumDeposit/actions.ts create mode 100644 src/experimental/arbitrumDeposit/depositEth.ts create mode 100644 src/experimental/arbitrumDeposit/publicActions.ts create mode 100644 src/experimental/arbitrumDeposit/sendDepositEth.ts create mode 100644 src/experimental/arbitrumDeposit/walletActions.ts diff --git a/src/experimental/arbitrumDeposit/actions.ts b/src/experimental/arbitrumDeposit/actions.ts deleted file mode 100644 index d87d3cfc8..000000000 --- a/src/experimental/arbitrumDeposit/actions.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - type PublicClient, - type WalletClient, - type Client, - encodeFunctionData, - Account, - Address, - parseTransaction, - serializeTransaction -} from 'viem' -import { localEthChain } from '../chains' -import { inboxAbi } from './abis/inbox' - -export type ArbitrumDepositActions = { - depositEth: (args: { - amount: bigint; - account: Account | Address; - walletClient: WalletClient; - }) => Promise<`0x${string}`> -} - -type ArbitrumChainConfig = { - ethBridge: { - inbox: `0x${string}` - } -} - -export function arbitrumDepositActions(childChain: ArbitrumChainConfig) { - return (parentPublicClient: TClient): ArbitrumDepositActions => { - const getDepositRequest = async ({ - amount, - account - }: { - amount: bigint - account: Account | Address - }) => { - const from = typeof account === 'string' ? account : account.address - - return { - to: childChain.ethBridge.inbox, - value: amount, - data: encodeFunctionData({ - abi: inboxAbi, - functionName: 'depositEth', - args: [] - }), - from - } - } - - return { - async depositEth({ amount, account, walletClient }) { - const request = await getDepositRequest({ - amount, - account - }) - - const gasPrice = await parentPublicClient.getGasPrice() - - const nonce = await parentPublicClient.getTransactionCount({ - address: typeof account === 'string' ? account as `0x${string}` : account.address, - blockTag: 'latest' - }) - - const signedTx = await walletClient.signTransaction({ - ...request, - account, - chain: localEthChain, - gas: BigInt('130000'), - maxFeePerGas: gasPrice, - maxPriorityFeePerGas: gasPrice, - nonce - }) - - // Parse and serialize with L2 chain ID - const parsedTx = parseTransaction((signedTx as any).raw) - const serializedTx = serializeTransaction({ - ...parsedTx, - }) - - // Send to L2 - const hash = await parentPublicClient.sendRawTransaction({ - serializedTransaction: serializedTx - }) - - return hash - } - } - } -} \ No newline at end of file diff --git a/src/experimental/arbitrumDeposit/depositEth.ts b/src/experimental/arbitrumDeposit/depositEth.ts new file mode 100644 index 000000000..32910f1df --- /dev/null +++ b/src/experimental/arbitrumDeposit/depositEth.ts @@ -0,0 +1,32 @@ +import { Account, Address, encodeFunctionData, WalletClient } from 'viem' +import { inboxAbi } from './abis/inbox' +import { localEthChain } from '../chains' +import { ArbitrumNetwork } from '../../lib/dataEntities/networks' + +export type DepositEthParams = { + amount: bigint + account: Account | Address + gasPrice: bigint + to: ArbitrumNetwork +} +export async function depositEth( + walletClient: WalletClient, + { amount, account, gasPrice, to }: DepositEthParams +) { + const signedTx = await walletClient.signTransaction({ + to: to.ethBridge.inbox as Address, + value: amount, + data: encodeFunctionData({ + abi: inboxAbi, + functionName: 'depositEth', + }), + from: typeof account === 'string' ? account : account.address, + account, + chain: localEthChain, + gas: BigInt('130000'), + maxFeePerGas: gasPrice, + maxPriorityFeePerGas: gasPrice, + }) + + return signedTx +} diff --git a/src/experimental/arbitrumDeposit/publicActions.ts b/src/experimental/arbitrumDeposit/publicActions.ts new file mode 100644 index 000000000..6b5b957b0 --- /dev/null +++ b/src/experimental/arbitrumDeposit/publicActions.ts @@ -0,0 +1,16 @@ +import { PublicClient } from 'viem' +import { depositEth, SendDepositEthParams } from './sendDepositEth' + +export type ArbitrumPublicActions = { + sendDepositEth: (args: SendDepositEthParams) => Promise<`0x${string}`> +} + +export function arbitrumPublicActions() { + return ( + publicClient: TClient + ): ArbitrumPublicActions => { + return { + sendDepositEth: args => depositEth(publicClient, args), + } + } +} diff --git a/src/experimental/arbitrumDeposit/sendDepositEth.ts b/src/experimental/arbitrumDeposit/sendDepositEth.ts new file mode 100644 index 000000000..207a76d45 --- /dev/null +++ b/src/experimental/arbitrumDeposit/sendDepositEth.ts @@ -0,0 +1,22 @@ +import { parseTransaction, PublicClient, serializeTransaction } from 'viem' + +export type SendDepositEthParams = { + signedTx: any +} +export async function depositEth( + publicClient: PublicClient, + { signedTx }: SendDepositEthParams +) { + // Parse and serialize with L2 chain ID + const parsedTx = parseTransaction(signedTx.raw) + const serializedTx = serializeTransaction({ + ...parsedTx, + }) + + // Send to L2 + const hash = await publicClient.sendRawTransaction({ + serializedTransaction: serializedTx, + }) + + return hash +} diff --git a/src/experimental/arbitrumDeposit/walletActions.ts b/src/experimental/arbitrumDeposit/walletActions.ts new file mode 100644 index 000000000..f0bce6c42 --- /dev/null +++ b/src/experimental/arbitrumDeposit/walletActions.ts @@ -0,0 +1,16 @@ +import { type WalletClient } from 'viem' +import { depositEth, DepositEthParams } from './depositEth' + +export type ArbitrumWalletActions = { + depositEth: (args: DepositEthParams) => Promise<`0x${string}`> +} + +export function arbitrumWalletActions() { + return ( + walletClient: TClient + ): ArbitrumWalletActions => { + return { + depositEth: args => depositEth(walletClient, args), + } + } +} From 93fed51e573a1a87b2b9662702ae94528b19cde9 Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 14 Nov 2024 15:34:08 +0000 Subject: [PATCH 2/3] WIP --- src/experimental/arbitrumDeposit/publicActions.ts | 4 ++-- src/experimental/arbitrumDeposit/sendDepositEth.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/experimental/arbitrumDeposit/publicActions.ts b/src/experimental/arbitrumDeposit/publicActions.ts index 6b5b957b0..96497504a 100644 --- a/src/experimental/arbitrumDeposit/publicActions.ts +++ b/src/experimental/arbitrumDeposit/publicActions.ts @@ -1,5 +1,5 @@ import { PublicClient } from 'viem' -import { depositEth, SendDepositEthParams } from './sendDepositEth' +import { sendDepositEth, SendDepositEthParams } from './sendDepositEth' export type ArbitrumPublicActions = { sendDepositEth: (args: SendDepositEthParams) => Promise<`0x${string}`> @@ -10,7 +10,7 @@ export function arbitrumPublicActions() { publicClient: TClient ): ArbitrumPublicActions => { return { - sendDepositEth: args => depositEth(publicClient, args), + sendDepositEth: args => sendDepositEth(publicClient, args), } } } diff --git a/src/experimental/arbitrumDeposit/sendDepositEth.ts b/src/experimental/arbitrumDeposit/sendDepositEth.ts index 207a76d45..823f67a6a 100644 --- a/src/experimental/arbitrumDeposit/sendDepositEth.ts +++ b/src/experimental/arbitrumDeposit/sendDepositEth.ts @@ -3,7 +3,7 @@ import { parseTransaction, PublicClient, serializeTransaction } from 'viem' export type SendDepositEthParams = { signedTx: any } -export async function depositEth( +export async function sendDepositEth( publicClient: PublicClient, { signedTx }: SendDepositEthParams ) { From a7394e8e07231a96a6b1160564281e352255f06c Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 15 Nov 2024 18:44:57 +0000 Subject: [PATCH 3/3] WIP --- .../arbitrumDeposit/abis/inbox.ts | 20 +++--- .../prepareDepositEthTransaction.ts | 23 +++++++ src/experimental/createArbitrumClient.ts | 62 +++++++++++++++++++ 3 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 src/experimental/arbitrumDeposit/prepareDepositEthTransaction.ts create mode 100644 src/experimental/createArbitrumClient.ts diff --git a/src/experimental/arbitrumDeposit/abis/inbox.ts b/src/experimental/arbitrumDeposit/abis/inbox.ts index 38bb10f85..c2ec7acac 100644 --- a/src/experimental/arbitrumDeposit/abis/inbox.ts +++ b/src/experimental/arbitrumDeposit/abis/inbox.ts @@ -4,7 +4,7 @@ export const inboxAbi = [ name: 'depositEth', outputs: [{ type: 'uint256' }], stateMutability: 'payable', - type: 'function' + type: 'function', }, { inputs: [ @@ -15,28 +15,26 @@ export const inboxAbi = [ { name: 'callValueRefundAddress', type: 'address' }, { name: 'gasLimit', type: 'uint256' }, { name: 'maxFeePerGas', type: 'uint256' }, - { name: 'data', type: 'bytes' } + { name: 'data', type: 'bytes' }, ], name: 'createRetryableTicket', outputs: [{ type: 'uint256' }], stateMutability: 'payable', - type: 'function' + type: 'function', }, { anonymous: false, inputs: [ { indexed: false, name: 'messageNum', type: 'uint256' }, - { indexed: false, name: 'data', type: 'bytes' } + { indexed: false, name: 'data', type: 'bytes' }, ], name: 'InboxMessageDelivered', - type: 'event' + type: 'event', }, { anonymous: false, - inputs: [ - { indexed: false, name: 'messageNum', type: 'uint256' } - ], + inputs: [{ indexed: false, name: 'messageNum', type: 'uint256' }], name: 'InboxMessageDeliveredFromOrigin', - type: 'event' - } -] as const \ No newline at end of file + type: 'event', + }, +] as const diff --git a/src/experimental/arbitrumDeposit/prepareDepositEthTransaction.ts b/src/experimental/arbitrumDeposit/prepareDepositEthTransaction.ts new file mode 100644 index 000000000..5acabbe4f --- /dev/null +++ b/src/experimental/arbitrumDeposit/prepareDepositEthTransaction.ts @@ -0,0 +1,23 @@ +import { Account, Address, encodeFunctionData, PublicClient } from 'viem' +import { inboxAbi } from './abis/inbox' + +export type PrepareDepositEthTransaction = { + amount: bigint + account: Account + inbox: Address +} +export async function prepareDepositEthTransaction( + publicClient: PublicClient, + { amount, account, inbox }: PrepareDepositEthTransaction +) { + return publicClient.prepareTransactionRequest({ + chain: publicClient.chain, + to: inbox, + data: encodeFunctionData({ + abi: inboxAbi, + functionName: 'depositEth', + }), + value: amount, + account, + }) +} diff --git a/src/experimental/createArbitrumClient.ts b/src/experimental/createArbitrumClient.ts new file mode 100644 index 000000000..5e3264d22 --- /dev/null +++ b/src/experimental/createArbitrumClient.ts @@ -0,0 +1,62 @@ +import { Address, PublicClient, WalletClient } from 'viem' +import { arbitrum, arbitrumNova, arbitrumSepolia } from 'viem/chains' +import { prepareDepositEthTransaction } from './arbitrumDeposit/prepareDepositEthTransaction' + +function getInboxFromChainId( + chainId: + | typeof arbitrum.id + | typeof arbitrumNova.id + | typeof arbitrumSepolia.id +) { + return { + [arbitrum.id]: '0x...', + [arbitrumNova.id]: '0x...', + [arbitrumSepolia.id]: '0x...', + }[chainId] +} + +export async function createArbitrumClient({ + parentChainPublicClient, + parentChainWalletClient, + childChainPublicClient, + childChainWalletClient, +}: { + parentChainPublicClient: PublicClient + parentChainWalletClient: WalletClient + childChainPublicClient: PublicClient + childChainWalletClient: WalletClient +}): Promise<{ + depositEth: (amount: bigint) => void +}> { + return { + async depositEth(amount: bigint) { + const tx = await prepareDepositEthTransaction(parentChainPublicClient, { + amount, + account: parentChainWalletClient.account!, + inbox: getInboxFromChainId( + childChainWalletClient.chain?.id! + ) as Address, + }) + const hash = await parentChainPublicClient.sendRawTransaction({ + serializedTransaction: await parentChainWalletClient.signTransaction( + tx + ), + }) + + // Await on childChainPublicClient for the transaction + return hash + }, + } +} + +/** + * const { depositEth } = createArbitrumClient({ + * parentChainPublicClient, + * parentChainWalletClient, + * childChainPublicClient, + * childChainWalletClient, + * }) + * + * depositEth({ amount: 150000n }) + * + */