FRE-600: Fix code review blockers

- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-25 00:08:01 -04:00
parent 65b552bb08
commit 7c684a42cc
48450 changed files with 5679671 additions and 383 deletions

2175
node_modules/viem/op-stack/abis.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
import type { Address } from 'abitype'
import {
type ParseAccountErrorType,
parseAccount,
} from '../../accounts/utils/parseAccount.js'
import {
type PrepareTransactionRequestErrorType,
type PrepareTransactionRequestParameters,
prepareTransactionRequest,
} from '../../actions/wallet/prepareTransactionRequest.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
Account,
DeriveAccount,
GetAccountParameter,
} from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hex } from '../../types/misc.js'
import type { Prettify, UnionOmit } from '../../types/utils.js'
import type { DepositTransactionParameters } from './depositTransaction.js'
export type BuildDepositTransactionParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
accountOverride extends Account | Address | undefined =
| Account
| Address
| undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetAccountParameter<account, accountOverride, false> &
GetChainParameter<chain, chainOverride> & {
/** Gas limit for transaction execution on the L2. */
gas?: bigint | undefined
/** Value in wei to mint (deposit) on the L2. Debited from the caller's L1 balance. */
mint?: bigint | undefined
/** Value in wei sent with this transaction on the L2. Debited from the caller's L2 balance. */
value?: bigint | undefined
} & (
| {
/** Encoded contract method & arguments. */
data?: Hex | undefined
/** Whether or not this is a contract deployment transaction. */
isCreation?: false | undefined
/** L2 Transaction recipient. */
to?: Address | undefined
}
| {
/** Contract deployment bytecode. Required for contract deployment transactions. */
data: Hex
/** Whether or not this is a contract deployment transaction. */
isCreation: true
/** L2 Transaction recipient. Cannot exist for contract deployment transactions. */
to?: undefined
}
)
export type BuildDepositTransactionReturnType<
account extends Account | undefined = Account | undefined,
accountOverride extends Account | Address | undefined =
| Account
| Address
| undefined,
> = Prettify<
UnionOmit<DepositTransactionParameters<Chain, account, Chain>, 'account'> & {
account: DeriveAccount<account, accountOverride>
}
>
export type BuildDepositTransactionErrorType =
| ParseAccountErrorType
| PrepareTransactionRequestErrorType
| ErrorType
/**
* Prepares parameters for a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) to be initiated on an L1.
*
* - Docs: https://viem.sh/op-stack/actions/buildDepositTransaction
*
* @param client - Client to use
* @param parameters - {@link BuildDepositTransactionParameters}
* @returns Parameters for `depositTransaction`. {@link DepositTransactionReturnType}
*
* @example
* import { createWalletClient, http, parseEther } from 'viem'
* import { base } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
* import { buildDepositTransaction } from 'viem/wallet'
*
* const client = createWalletClient({
* chain: base,
* transport: http(),
* }).extend(publicActionsL2())
*
* const args = await buildDepositTransaction(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function buildDepositTransaction<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
accountOverride extends Account | Address | undefined = undefined,
>(
client: Client<Transport, chain, account>,
args: BuildDepositTransactionParameters<
chain,
account,
chainOverride,
accountOverride
>,
): Promise<BuildDepositTransactionReturnType<account, accountOverride>> {
const {
account: account_,
chain = client.chain,
gas,
data,
isCreation,
mint,
to,
value,
} = args
const account = account_ ? parseAccount(account_) : undefined
const request = await prepareTransactionRequest(client, {
account: mint ? undefined : account,
chain,
gas,
data,
parameters: ['gas'],
to,
value,
} as PrepareTransactionRequestParameters)
return {
account,
request: {
data: request.data,
gas: request.gas,
mint,
isCreation,
to: request.to,
value: request.value,
},
targetChain: chain,
} as unknown as BuildDepositTransactionReturnType<account, accountOverride>
}

View File

@@ -0,0 +1,118 @@
import type { Address } from 'abitype'
import {
type ParseAccountErrorType,
parseAccount,
} from '../../accounts/utils/parseAccount.js'
import {
type PrepareTransactionRequestErrorType,
type PrepareTransactionRequestParameters,
prepareTransactionRequest,
} from '../../actions/wallet/prepareTransactionRequest.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type { Chain, GetChainParameter } from '../../types/chain.js'
import type { Hex } from '../../types/misc.js'
import type { Prettify, UnionOmit } from '../../types/utils.js'
import type { InitiateWithdrawalParameters } from './initiateWithdrawal.js'
export type BuildInitiateWithdrawalParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
accountOverride extends Account | Address | undefined =
| Account
| Address
| undefined,
> = GetAccountParameter<account, accountOverride, false> &
GetChainParameter<chain, chainOverride> & {
/** Encoded contract method & arguments. */
data?: Hex | undefined
/** Gas limit for transaction execution on the L1. */
gas?: bigint | undefined
/** L1 Transaction recipient. */
to: Address
/** Value in wei to withdrawal to the L1. Debited from the caller's L2 balance. */
value?: bigint | undefined
}
export type BuildInitiateWithdrawalReturnType<
account extends Account | undefined = Account | undefined,
accountOverride extends Account | Address | undefined =
| Account
| Address
| undefined,
> = Prettify<
UnionOmit<InitiateWithdrawalParameters<Chain, account, Chain>, 'account'> &
GetAccountParameter<account, accountOverride>
>
export type BuildInitiateWithdrawalErrorType =
| ParseAccountErrorType
| PrepareTransactionRequestErrorType
| ErrorType
/**
* Prepares parameters for a [withdrawal](https://community.optimism.io/docs/protocol/withdrawal-flow/#withdrawal-initiating-transaction) from an L2 to the L1.
*
* - Docs: https://viem.sh/op-stack/actions/buildInitiateWithdrawal
*
* @param client - Client to use
* @param parameters - {@link BuildInitiateWithdrawalParameters}
* @returns Parameters for `depositTransaction`. {@link DepositTransactionReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { mainnet } from 'viem/chains'
* import { buildInitiateWithdrawal } from 'viem/wallet'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const args = await buildInitiateWithdrawal(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function buildInitiateWithdrawal<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
accountOverride extends Account | Address | undefined = undefined,
>(
client: Client<Transport, chain, account>,
args: BuildInitiateWithdrawalParameters<
chain,
account,
chainOverride,
accountOverride
>,
): Promise<BuildInitiateWithdrawalReturnType<account, accountOverride>> {
const { account: account_, chain = client.chain, gas, data, to, value } = args
const account = account_ ? parseAccount(account_) : undefined
const request = await prepareTransactionRequest(client, {
account: null,
chain,
gas,
data,
parameters: ['gas'],
to,
value,
} as PrepareTransactionRequestParameters)
return {
account,
request: {
data: request.data,
gas: request.gas,
to: request.to,
value: request.value,
},
} as BuildInitiateWithdrawalReturnType<account, accountOverride>
}

View File

@@ -0,0 +1,181 @@
import type { Address } from 'abitype'
import {
type GetBlockErrorType,
getBlock,
} from '../../actions/public/getBlock.js'
import {
type GetProofErrorType,
getProof,
} from '../../actions/public/getProof.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
Account,
DeriveAccount,
GetAccountParameter,
} from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hex } from '../../types/misc.js'
import type { OneOf, Prettify } from '../../types/utils.js'
import { fromRlp } from '../../utils/encoding/fromRlp.js'
import { toRlp } from '../../utils/encoding/toRlp.js'
import { keccak256 } from '../../utils/hash/keccak256.js'
import { contracts } from '../contracts.js'
import type { Withdrawal } from '../types/withdrawal.js'
import {
type GetWithdrawalHashStorageSlotErrorType,
getWithdrawalHashStorageSlot,
} from '../utils/getWithdrawalHashStorageSlot.js'
import type { GetGameReturnType } from './getGame.js'
import type { GetL2OutputReturnType } from './getL2Output.js'
import type { ProveWithdrawalParameters } from './proveWithdrawal.js'
const outputRootProofVersion =
'0x0000000000000000000000000000000000000000000000000000000000000000' as const
export type BuildProveWithdrawalParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
accountOverride extends Account | Address | undefined =
| Account
| Address
| undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetAccountParameter<account, accountOverride, false> &
GetChainParameter<chain, chainOverride> & {
withdrawal: Withdrawal
} & OneOf<{ output: GetL2OutputReturnType } | { game: GetGameReturnType }>
export type BuildProveWithdrawalReturnType<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
accountOverride extends Account | Address | undefined =
| Account
| Address
| undefined,
> = Prettify<
Pick<
ProveWithdrawalParameters,
'l2OutputIndex' | 'outputRootProof' | 'withdrawalProof' | 'withdrawal'
> & {
account: DeriveAccount<account, accountOverride>
targetChain: DeriveChain<chain, chainOverride>
}
>
export type BuildProveWithdrawalErrorType =
| GetBlockErrorType
| GetProofErrorType
| GetWithdrawalHashStorageSlotErrorType
| ErrorType
/**
* Builds the transaction that proves a withdrawal was initiated on an L2. Used in the Withdrawal flow.
*
* - Docs: https://viem.sh/op-stack/actions/buildProveWithdrawal
*
* @param client - Client to use
* @param parameters - {@link BuildProveWithdrawalParameters}
* @returns The prove withdraw transaction request. {@link BuildProveWithdrawalReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { optimism } from 'viem/chains'
* import { buildProveWithdrawal } from 'viem/op-stack'
*
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const args = await buildProveWithdrawal(publicClientL2, {
* output: { ... },
* withdrawal: { ... },
* })
*/
export async function buildProveWithdrawal<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
accountOverride extends Account | Address | undefined = undefined,
>(
client: Client<Transport, chain, account>,
args: BuildProveWithdrawalParameters<
chain,
account,
chainOverride,
accountOverride
>,
): Promise<
BuildProveWithdrawalReturnType<chain, account, chainOverride, accountOverride>
> {
const { account, chain = client.chain, game, output, withdrawal } = args
const { withdrawalHash } = withdrawal
const { l2BlockNumber } = game ?? output
const slot = getWithdrawalHashStorageSlot({ withdrawalHash })
const [proof, block] = await Promise.all([
getProof(client, {
address: contracts.l2ToL1MessagePasser.address,
storageKeys: [slot],
blockNumber: l2BlockNumber,
}),
getBlock(client, {
blockNumber: l2BlockNumber,
}),
])
return {
account,
l2OutputIndex: game?.index ?? output?.outputIndex,
outputRootProof: {
latestBlockhash: block.hash,
messagePasserStorageRoot: proof.storageHash,
stateRoot: block.stateRoot,
version: outputRootProofVersion,
},
targetChain: chain,
withdrawalProof: maybeAddProofNode(
keccak256(slot),
proof.storageProof[0].proof,
),
withdrawal,
} as unknown as BuildProveWithdrawalReturnType<
chain,
account,
chainOverride,
accountOverride
>
}
/** @internal */
export function maybeAddProofNode(key: string, proof: readonly Hex[]) {
const lastProofRlp = proof[proof.length - 1]
const lastProof = fromRlp(lastProofRlp)
if (lastProof.length !== 17) return proof
const modifiedProof = [...proof]
for (const item of lastProof) {
// Find any nodes located inside of the branch node.
if (!Array.isArray(item)) continue
// Check if the key inside the node matches the key we're looking for. We remove the first
// two characters (0x) and then we remove one more character (the first nibble) since this
// is the identifier for the type of node we're looking at. In this case we don't actually
// care what type of node it is because a branch node would only ever be the final proof
// element if (1) it includes the leaf node we're looking for or (2) it stores the value
// within itself. If (1) then this logic will work, if (2) then this won't find anything
// and we won't append any proof elements, which is exactly what we would want.
const suffix = item[0].slice(3)
if (typeof suffix !== 'string' || !key.endsWith(suffix)) continue
modifiedProof.push(toRlp(item))
}
return modifiedProof
}

View File

@@ -0,0 +1,165 @@
import type { Address } from 'abitype'
import {
type WriteContractErrorType,
type WriteContractParameters,
writeContract,
} from '../../actions/wallet/writeContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import { zeroAddress } from '../../constants/address.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hash } from '../../types/misc.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { portalAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { DepositRequest } from '../types/deposit.js'
import type { EstimateDepositTransactionGasErrorType } from './estimateDepositTransactionGas.js'
export type DepositTransactionParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'portal'> & {
/** L2 transaction request. */
request: DepositRequest
/**
* Gas limit for transaction execution on the L1.
* `null` to skip gas estimation & defer calculation to signer.
*/
gas?: bigint | null | undefined
}
export type DepositTransactionReturnType = Hash
export type DepositTransactionErrorType =
| EstimateDepositTransactionGasErrorType
| WriteContractErrorType
| ErrorType
/**
* Initiates a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) on an L1, which executes a transaction on L2.
*
* Internally performs a contract write to the [`depositTransaction` function](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L1/OptimismPortal.sol#L378)
* on the [Optimism Portal contract](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L1/OptimismPortal.sol).
*
* - Docs: https://viem.sh/op-stack/actions/depositTransaction
*
* @param client - Client to use
* @param parameters - {@link DepositTransactionParameters}
* @returns The L1 transaction hash. {@link DepositTransactionReturnType}
*
* @example
* import { createWalletClient, custom, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { depositTransaction } from 'viem/op-stack'
*
* const client = createWalletClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* })
*
* const hash = await depositTransaction(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* targetChain: base,
* })
*
* @example
* // Account Hoisting
* import { createWalletClient, http } from 'viem'
* import { privateKeyToAccount } from 'viem/accounts'
* import { base, mainnet } from 'viem/chains'
* import { depositTransaction } from 'viem/op-stack'
*
* const client = createWalletClient({
* account: privateKeyToAccount('0x…'),
* chain: mainnet,
* transport: http(),
* })
*
* const hash = await depositTransaction(client, {
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* targetChain: base,
* })
*/
export async function depositTransaction<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: DepositTransactionParameters<chain, account, chainOverride>,
) {
const {
account,
chain = client.chain,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
request: {
data = '0x',
gas: l2Gas,
isCreation = false,
mint,
to = '0x',
value,
},
targetChain,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
return writeContract(client, {
account: account!,
abi: portalAbi,
address: portalAddress,
chain,
functionName: 'depositTransaction',
args: [
isCreation ? zeroAddress : to,
value ?? mint ?? 0n,
l2Gas,
isCreation,
data,
],
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
value: mint,
gas: gas ?? undefined,
} satisfies WriteContractParameters as any)
}

View File

@@ -0,0 +1,142 @@
import type { Abi } from 'abitype'
import type { Account } from '../../accounts/types.js'
import {
type ParseAccountErrorType,
parseAccount,
} from '../../accounts/utils/parseAccount.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { BaseError } from '../../errors/base.js'
import type { Chain } from '../../types/chain.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
ContractFunctionParameters,
GetValue,
} from '../../types/contract.js'
import type { UnionOmit } from '../../types/utils.js'
import {
type EncodeFunctionDataErrorType,
type EncodeFunctionDataParameters,
encodeFunctionData,
} from '../../utils/abi/encodeFunctionData.js'
import {
type GetContractErrorReturnType,
getContractError,
} from '../../utils/errors/getContractError.js'
import {
type EstimateL1FeeErrorType,
type EstimateL1FeeParameters,
estimateL1Fee,
} from './estimateL1Fee.js'
export type EstimateContractL1FeeParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends ContractFunctionName<
abi,
'nonpayable' | 'payable'
> = ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<
abi,
'nonpayable' | 'payable',
functionName
> = ContractFunctionArgs<abi, 'nonpayable' | 'payable', functionName>,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = ContractFunctionParameters<
abi,
'nonpayable' | 'payable',
functionName,
args
> &
UnionOmit<
EstimateL1FeeParameters<chain, account, chainOverride>,
'data' | 'to' | 'value'
> &
GetValue<
abi,
functionName,
EstimateL1FeeParameters<
chain,
account,
chainOverride
> extends EstimateL1FeeParameters
? EstimateL1FeeParameters<chain, account, chainOverride>['value']
: EstimateL1FeeParameters['value']
>
export type EstimateContractL1FeeReturnType = bigint
export type EstimateContractL1FeeErrorType = GetContractErrorReturnType<
EncodeFunctionDataErrorType | EstimateL1FeeErrorType | ParseAccountErrorType
>
/**
* Estimates the L1 data fee required to execute an L2 contract write.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractL1FeeParameters}
* @returns The gas estimate (in wei). {@link EstimateContractL1FeeReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateContractL1Fee } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const l1Fee = await estimateContractL1Fee(client, {
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
export async function estimateContractL1Fee<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chain extends Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateContractL1FeeParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
): Promise<EstimateContractL1FeeReturnType> {
const { abi, address, args, functionName, ...request } =
parameters as EstimateContractL1FeeParameters
const data = encodeFunctionData({
abi,
args,
functionName,
} as EncodeFunctionDataParameters)
try {
const fee = await estimateL1Fee(client, {
data,
to: address,
...request,
} as unknown as EstimateL1FeeParameters)
return fee
} catch (error) {
const account = request.account ? parseAccount(request.account) : undefined
throw getContractError(error as BaseError, {
abi,
address,
args,
docsPath: '/docs/chains/op-stack/estimateContractL1Fee',
functionName,
sender: account?.address,
})
}
}

View File

@@ -0,0 +1,142 @@
import type { Abi } from 'abitype'
import type { Account } from '../../accounts/types.js'
import {
type ParseAccountErrorType,
parseAccount,
} from '../../accounts/utils/parseAccount.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { BaseError } from '../../errors/base.js'
import type { Chain } from '../../types/chain.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
ContractFunctionParameters,
GetValue,
} from '../../types/contract.js'
import type { UnionOmit } from '../../types/utils.js'
import {
type EncodeFunctionDataErrorType,
type EncodeFunctionDataParameters,
encodeFunctionData,
} from '../../utils/abi/encodeFunctionData.js'
import {
type GetContractErrorReturnType,
getContractError,
} from '../../utils/errors/getContractError.js'
import {
type EstimateL1GasErrorType,
type EstimateL1GasParameters,
estimateL1Gas,
} from './estimateL1Gas.js'
export type EstimateContractL1GasParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends ContractFunctionName<
abi,
'nonpayable' | 'payable'
> = ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<
abi,
'nonpayable' | 'payable',
functionName
> = ContractFunctionArgs<abi, 'nonpayable' | 'payable', functionName>,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = ContractFunctionParameters<
abi,
'nonpayable' | 'payable',
functionName,
args
> &
UnionOmit<
EstimateL1GasParameters<chain, account, chainOverride>,
'data' | 'to' | 'value'
> &
GetValue<
abi,
functionName,
EstimateL1GasParameters<
chain,
account,
chainOverride
> extends EstimateL1GasParameters
? EstimateL1GasParameters<chain, account, chainOverride>['value']
: EstimateL1GasParameters['value']
>
export type EstimateContractL1GasReturnType = bigint
export type EstimateContractL1GasErrorType = GetContractErrorReturnType<
EncodeFunctionDataErrorType | EstimateL1GasErrorType | ParseAccountErrorType
>
/**
* Estimates the L1 data gas required to successfully execute a contract write function call.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractL1GasParameters}
* @returns The gas estimate (in wei). {@link EstimateContractL1GasReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateContractL1Gas } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const l1Gas = await estimateContractL1Gas(client, {
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
export async function estimateContractL1Gas<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chain extends Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateContractL1GasParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
): Promise<EstimateContractL1GasReturnType> {
const { abi, address, args, functionName, ...request } =
parameters as EstimateContractL1GasParameters
const data = encodeFunctionData({
abi,
args,
functionName,
} as EncodeFunctionDataParameters)
try {
const gas = await estimateL1Gas(client, {
data,
to: address,
...request,
} as unknown as EstimateL1GasParameters)
return gas
} catch (error) {
const account = request.account ? parseAccount(request.account) : undefined
throw getContractError(error as BaseError, {
abi,
address,
args,
docsPath: '/docs/chains/op-stack/estimateContractL1Gas',
functionName,
sender: account?.address,
})
}
}

View File

@@ -0,0 +1,144 @@
import type { Abi } from 'abitype'
import type { Account } from '../../accounts/types.js'
import {
type ParseAccountErrorType,
parseAccount,
} from '../../accounts/utils/parseAccount.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { BaseError } from '../../errors/base.js'
import type { Chain } from '../../types/chain.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
ContractFunctionParameters,
GetValue,
} from '../../types/contract.js'
import type { UnionOmit } from '../../types/utils.js'
import {
type EncodeFunctionDataErrorType,
type EncodeFunctionDataParameters,
encodeFunctionData,
} from '../../utils/abi/encodeFunctionData.js'
import {
type GetContractErrorReturnType,
getContractError,
} from '../../utils/errors/getContractError.js'
import {
type EstimateTotalFeeErrorType,
type EstimateTotalFeeParameters,
estimateTotalFee,
} from './estimateTotalFee.js'
export type EstimateContractTotalFeeParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends ContractFunctionName<
abi,
'nonpayable' | 'payable'
> = ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<
abi,
'nonpayable' | 'payable',
functionName
> = ContractFunctionArgs<abi, 'nonpayable' | 'payable', functionName>,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = ContractFunctionParameters<
abi,
'nonpayable' | 'payable',
functionName,
args
> &
UnionOmit<
EstimateTotalFeeParameters<chain, account, chainOverride>,
'data' | 'to' | 'value'
> &
GetValue<
abi,
functionName,
EstimateTotalFeeParameters<
chain,
account,
chainOverride
> extends EstimateTotalFeeParameters
? EstimateTotalFeeParameters<chain, account, chainOverride>['value']
: EstimateTotalFeeParameters['value']
>
export type EstimateContractTotalFeeReturnType = bigint
export type EstimateContractTotalFeeErrorType = GetContractErrorReturnType<
| EncodeFunctionDataErrorType
| EstimateTotalFeeErrorType
| ParseAccountErrorType
>
/**
* Estimates the L1 data fee + L2 fee to execute an L2 contract write.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractTotalFeeParameters}
* @returns The gas estimate (in wei). {@link EstimateContractTotalFeeReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateContractTotalFee } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const totalFee = await estimateContractTotalFee(client, {
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
export async function estimateContractTotalFee<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chain extends Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateContractTotalFeeParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
): Promise<EstimateContractTotalFeeReturnType> {
const { abi, address, args, functionName, ...request } =
parameters as EstimateContractTotalFeeParameters
const data = encodeFunctionData({
abi,
args,
functionName,
} as EncodeFunctionDataParameters)
try {
const fee = await estimateTotalFee(client, {
data,
to: address,
...request,
} as unknown as EstimateTotalFeeParameters)
return fee
} catch (error) {
const account = request.account ? parseAccount(request.account) : undefined
throw getContractError(error as BaseError, {
abi,
address,
args,
docsPath: '/docs/chains/op-stack/estimateTotalFee',
functionName,
sender: account?.address,
})
}
}

View File

@@ -0,0 +1,144 @@
import type { Abi } from 'abitype'
import type { Account } from '../../accounts/types.js'
import {
type ParseAccountErrorType,
parseAccount,
} from '../../accounts/utils/parseAccount.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { BaseError } from '../../errors/base.js'
import type { Chain } from '../../types/chain.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
ContractFunctionParameters,
GetValue,
} from '../../types/contract.js'
import type { UnionOmit } from '../../types/utils.js'
import {
type EncodeFunctionDataErrorType,
type EncodeFunctionDataParameters,
encodeFunctionData,
} from '../../utils/abi/encodeFunctionData.js'
import {
type GetContractErrorReturnType,
getContractError,
} from '../../utils/errors/getContractError.js'
import {
type EstimateTotalGasErrorType,
type EstimateTotalGasParameters,
estimateTotalGas,
} from './estimateTotalGas.js'
export type EstimateContractTotalGasParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends ContractFunctionName<
abi,
'nonpayable' | 'payable'
> = ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<
abi,
'nonpayable' | 'payable',
functionName
> = ContractFunctionArgs<abi, 'nonpayable' | 'payable', functionName>,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = ContractFunctionParameters<
abi,
'nonpayable' | 'payable',
functionName,
args
> &
UnionOmit<
EstimateTotalGasParameters<chain, account, chainOverride>,
'data' | 'to' | 'value'
> &
GetValue<
abi,
functionName,
EstimateTotalGasParameters<
chain,
account,
chainOverride
> extends EstimateTotalGasParameters
? EstimateTotalGasParameters<chain, account, chainOverride>['value']
: EstimateTotalGasParameters['value']
>
export type EstimateContractTotalGasReturnType = bigint
export type EstimateContractTotalGasErrorType = GetContractErrorReturnType<
| EncodeFunctionDataErrorType
| EstimateTotalGasErrorType
| ParseAccountErrorType
>
/**
* Estimates the L1 data gas + L2 gas required to successfully execute a contract write function call.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractTotalGasParameters}
* @returns The gas estimate (in wei). {@link EstimateContractTotalGasReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateContractTotalGas } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const totalGas = await estimateContractTotalGas(client, {
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
export async function estimateContractTotalGas<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chain extends Chain | undefined,
account extends Account | undefined = undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateContractTotalGasParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
): Promise<EstimateContractTotalGasReturnType> {
const { abi, address, args, functionName, ...request } =
parameters as EstimateContractTotalGasParameters
const data = encodeFunctionData({
abi,
args,
functionName,
} as EncodeFunctionDataParameters)
try {
const gas = await estimateTotalGas(client, {
data,
to: address,
...request,
} as unknown as EstimateTotalGasParameters)
return gas
} catch (error) {
const account = request.account ? parseAccount(request.account) : undefined
throw getContractError(error as BaseError, {
abi,
address,
args,
docsPath: '/docs/chains/op-stack/estimateTotalGas',
functionName,
sender: account?.address,
})
}
}

View File

@@ -0,0 +1,149 @@
import type { Address } from 'abitype'
import {
type EstimateContractGasErrorType,
type EstimateContractGasParameters,
estimateContractGas,
} from '../../actions/public/estimateContractGas.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import { zeroAddress } from '../../constants/address.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { portalAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { DepositRequest } from '../types/deposit.js'
export type EstimateDepositTransactionGasParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
///
derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<derivedChain, 'portal'> & {
/** L2 transaction request. */
request: DepositRequest
/** Gas limit for transaction execution on the L1. */
gas?: bigint | undefined
}
export type EstimateDepositTransactionGasReturnType = bigint
export type EstimateDepositTransactionGasErrorType =
| EstimateContractGasErrorType
| ErrorType
/**
* Estimates gas required to initiate a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) on an L1, which executes a transaction on L2.
*
* - Docs: https://viem.sh/op-stack/actions/estimateDepositTransactionGas
*
* @param client - Client to use
* @param parameters - {@link EstimateDepositTransactionGasParameters}
* @returns The L1 transaction hash. {@link EstimateDepositTransactionGasReturnType}
*
* @example
* import { createPublicClient, custom, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { estimateDepositTransactionGas } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* })
*
* const gas = await estimateDepositTransactionGas(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* args: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* targetChain: base,
* })
*/
export async function estimateDepositTransactionGas<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateDepositTransactionGasParameters<
chain,
account,
chainOverride
>,
) {
const {
account,
chain = client.chain,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
request: {
data = '0x',
gas: l2Gas,
isCreation = false,
mint,
to = '0x',
value,
},
targetChain,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const params = {
account,
abi: portalAbi,
address: portalAddress,
functionName: 'depositTransaction',
args: [
isCreation ? zeroAddress : to,
value ?? mint ?? 0n,
l2Gas,
isCreation,
data,
],
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
value: mint,
// TODO: Not sure `chain` is necessary since it's not used downstream
// in `estimateContractGas` or `estimateGas`
// @ts-expect-error
chain,
} satisfies EstimateContractGasParameters<
typeof portalAbi,
'depositTransaction'
>
return estimateContractGas(client, params as any)
}

View File

@@ -0,0 +1,137 @@
import type { Address } from 'abitype'
import {
type EstimateContractGasErrorType,
type EstimateContractGasParameters,
estimateContractGas,
} from '../../actions/public/estimateContractGas.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { portal2Abi, portalAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { Withdrawal } from '../types/withdrawal.js'
export type EstimateFinalizeWithdrawalGasParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'portal'> & {
/** Gas limit for transaction execution on the L2. */
gas?: bigint | undefined
/**
* Finalize against a specific proof submitter.
* If unspecified, the sending account is the default.
*/
proofSubmitter?: Address | null | undefined
withdrawal: Withdrawal
}
export type EstimateFinalizeWithdrawalGasReturnType = bigint
export type EstimateFinalizeWithdrawalGasErrorType =
| EstimateContractGasErrorType
| ErrorType
/**
* Estimates gas required to finalize a withdrawal that occurred on an L2.
*
* - Docs: https://viem.sh/op-stack/actions/estimateFinalizeWithdrawalGas
*
* @param client - Client to use
* @param parameters - {@link EstimateFinalizeWithdrawalGasParameters}
* @returns Estimated gas. {@link EstimateFinalizeWithdrawalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { estimateFinalizeWithdrawalGas } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const gas = await estimateFinalizeWithdrawalGas(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* targetChain: optimism,
* withdrawal: { ... },
* })
*/
export async function estimateFinalizeWithdrawalGas<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateFinalizeWithdrawalGasParameters<
chain,
account,
chainOverride
>,
) {
const {
account,
chain = client.chain,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
proofSubmitter,
targetChain,
withdrawal,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const [functionName, args, abi] = proofSubmitter
? [
'finalizeWithdrawalTransactionExternalProof',
[withdrawal, proofSubmitter],
portal2Abi,
]
: ['finalizeWithdrawalTransaction', [withdrawal], portalAbi]
const params = {
account,
abi,
address: portalAddress,
functionName,
args,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
// TODO: Not sure `chain` is necessary since it's not used downstream
// in `estimateContractGas` or `estimateGas`
// @ts-expect-error
chain,
} satisfies EstimateContractGasParameters
return estimateContractGas(client, params as any)
}

View File

@@ -0,0 +1,125 @@
import type { Address } from 'abitype'
import {
type EstimateContractGasErrorType,
type EstimateContractGasParameters,
estimateContractGas,
} from '../../actions/public/estimateContractGas.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { l2ToL1MessagePasserAbi } from '../abis.js'
import { contracts } from '../contracts.js'
import type { WithdrawalRequest } from '../types/withdrawal.js'
export type EstimateInitiateWithdrawalGasParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> & {
/** Gas limit for transaction execution on the L2. */
gas?: bigint | undefined
/**
* Withdrawal request.
* Supplied to the L2ToL1MessagePasser `initiateWithdrawal` method.
*/
request: WithdrawalRequest
}
export type EstimateInitiateWithdrawalGasReturnType = bigint
export type EstimateInitiateWithdrawalGasErrorType =
| EstimateContractGasErrorType
| ErrorType
/**
* Estimates gas required to initiate a [withdrawal](https://community.optimism.io/docs/protocol/withdrawal-flow/#withdrawal-initiating-transaction) on an L2 to the L1.
*
* - Docs: https://viem.sh/op-stack/actions/estimateInitiateWithdrawalGas
*
* @param client - Client to use
* @param parameters - {@link EstimateInitiateWithdrawalGasParameters}
* @returns Estimated gas. {@link EstimateInitiateWithdrawalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { estimateInitiateWithdrawalGas } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const gas = await estimateInitiateWithdrawalGas(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* })
*/
export async function estimateInitiateWithdrawalGas<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateInitiateWithdrawalGasParameters<
chain,
account,
chainOverride
>,
) {
const {
account,
chain = client.chain,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
request: { data = '0x', gas: l1Gas, to, value },
} = parameters
const params = {
account,
abi: l2ToL1MessagePasserAbi,
address: contracts.l2ToL1MessagePasser.address,
functionName: 'initiateWithdrawal',
args: [to, l1Gas, data],
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
value,
// TODO: Not sure `chain` is necessary since it's not used downstream
// in `estimateContractGas` or `estimateGas`
// @ts-expect-error
chain,
} satisfies EstimateContractGasParameters<
typeof l2ToL1MessagePasserAbi,
'initiateWithdrawal'
>
return estimateContractGas(client, params as any)
}

112
node_modules/viem/op-stack/actions/estimateL1Fee.ts generated vendored Normal file
View File

@@ -0,0 +1,112 @@
import type { Address } from 'abitype'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type { Chain, GetChainParameter } from '../../types/chain.js'
import type {
TransactionRequestEIP1559,
TransactionSerializable,
} from '../../types/transaction.js'
import type { RequestErrorType } from '../../utils/buildRequest.js'
import { getChainContractAddress } from '../../utils/chain/getChainContractAddress.js'
import type { HexToNumberErrorType } from '../../utils/encoding/fromHex.js'
import {
type SerializeTransactionErrorType,
serializeTransaction,
} from '../../utils/transaction/serializeTransaction.js'
import { parseGwei } from '../../utils/unit/parseGwei.js'
import { gasPriceOracleAbi } from '../abis.js'
import { contracts } from '../contracts.js'
export type EstimateL1FeeParameters<
TChain extends Chain | undefined = Chain | undefined,
TAccount extends Account | undefined = Account | undefined,
TChainOverride extends Chain | undefined = undefined,
> = Omit<TransactionRequestEIP1559, 'from'> &
GetAccountParameter<TAccount> &
GetChainParameter<TChain, TChainOverride> & {
/** Gas price oracle address. */
gasPriceOracleAddress?: Address | undefined
}
export type EstimateL1FeeReturnType = bigint
export type EstimateL1FeeErrorType =
| RequestErrorType
| SerializeTransactionErrorType
| HexToNumberErrorType
| ReadContractErrorType
| ErrorType
/**
* Estimates the L1 data fee required to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateL1FeeParameters}
* @returns The fee (in wei). {@link EstimateL1FeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateL1Fee } from 'viem/chains/optimism'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const l1Fee = await estimateL1Fee(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function estimateL1Fee<
TChain extends Chain | undefined,
TAccount extends Account | undefined,
TChainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, TChain, TAccount>,
args: EstimateL1FeeParameters<TChain, TAccount, TChainOverride>,
): Promise<EstimateL1FeeReturnType> {
const {
chain = client.chain,
gasPriceOracleAddress: gasPriceOracleAddress_,
} = args
const gasPriceOracleAddress = (() => {
if (gasPriceOracleAddress_) return gasPriceOracleAddress_
if (chain)
return getChainContractAddress({
chain,
contract: 'gasPriceOracle',
})
return contracts.gasPriceOracle.address
})()
const transaction = serializeTransaction({
...args,
chainId: chain?.id ?? 1,
type: 'eip1559',
// Set upper-limit-ish stub values. Shouldn't affect the estimate too much as we are
// tweaking dust bytes here (as opposed to long `data` bytes).
// See: https://github.com/ethereum-optimism/optimism/blob/54d02df55523c9e1b4b38ed082c12a42087323a0/packages/contracts-bedrock/src/L2/GasPriceOracle.sol#L242-L248.
gas: args.data ? 300_000n : 21_000n,
maxFeePerGas: parseGwei('5'),
maxPriorityFeePerGas: parseGwei('1'),
nonce: 1,
} as TransactionSerializable)
return readContract(client, {
abi: gasPriceOracleAbi,
address: gasPriceOracleAddress,
functionName: 'getL1Fee',
args: [transaction as any],
})
}

112
node_modules/viem/op-stack/actions/estimateL1Gas.ts generated vendored Normal file
View File

@@ -0,0 +1,112 @@
import type { Address } from 'abitype'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type { Chain, GetChainParameter } from '../../types/chain.js'
import type {
TransactionRequestEIP1559,
TransactionSerializable,
} from '../../types/transaction.js'
import type { RequestErrorType } from '../../utils/buildRequest.js'
import { getChainContractAddress } from '../../utils/chain/getChainContractAddress.js'
import type { HexToNumberErrorType } from '../../utils/encoding/fromHex.js'
import {
type SerializeTransactionErrorType,
serializeTransaction,
} from '../../utils/transaction/serializeTransaction.js'
import { parseGwei } from '../../utils/unit/parseGwei.js'
import { gasPriceOracleAbi } from '../abis.js'
import { contracts } from '../contracts.js'
export type EstimateL1GasParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = Omit<TransactionRequestEIP1559, 'from'> &
GetAccountParameter<account> &
GetChainParameter<chain, chainOverride> & {
/** Gas price oracle address. */
gasPriceOracleAddress?: Address | undefined
}
export type EstimateL1GasReturnType = bigint
export type EstimateL1GasErrorType =
| RequestErrorType
| SerializeTransactionErrorType
| HexToNumberErrorType
| ReadContractErrorType
| ErrorType
/**
* Estimates the L1 data gas required to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateL1GasParameters}
* @returns The gas estimate. {@link EstimateL1GasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateL1Gas } from 'viem/chains/optimism'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const l1Gas = await estimateL1Gas(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function estimateL1Gas<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
args: EstimateL1GasParameters<chain, account, chainOverride>,
): Promise<EstimateL1GasReturnType> {
const {
chain = client.chain,
gasPriceOracleAddress: gasPriceOracleAddress_,
} = args
const gasPriceOracleAddress = (() => {
if (gasPriceOracleAddress_) return gasPriceOracleAddress_
if (chain)
return getChainContractAddress({
chain,
contract: 'gasPriceOracle',
})
return contracts.gasPriceOracle.address
})()
const transaction = serializeTransaction({
...args,
chainId: chain?.id ?? 1,
type: 'eip1559',
// Set upper-limit-ish stub values. Shouldn't affect the estimate too much as we are
// tweaking dust bytes here (as opposed to long `data` bytes).
// See: https://github.com/ethereum-optimism/optimism/blob/54d02df55523c9e1b4b38ed082c12a42087323a0/packages/contracts-bedrock/src/L2/GasPriceOracle.sol#L242-L248.
gas: args.data ? 300_000n : 21_000n,
maxFeePerGas: parseGwei('5'),
maxPriorityFeePerGas: parseGwei('1'),
nonce: 1,
} as TransactionSerializable)
return readContract(client, {
abi: gasPriceOracleAbi,
address: gasPriceOracleAddress,
functionName: 'getL1GasUsed',
args: [transaction as any],
})
}

View File

@@ -0,0 +1,119 @@
import type { Address } from 'abitype'
import {
type EstimateGasErrorType,
type EstimateGasParameters,
estimateGas,
} from '../../actions/public/estimateGas.js'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type { Chain, GetChainParameter } from '../../types/chain.js'
import type { TransactionRequestEIP1559 } from '../../types/transaction.js'
import type { RequestErrorType } from '../../utils/buildRequest.js'
import { getChainContractAddress } from '../../utils/chain/getChainContractAddress.js'
import type { HexToNumberErrorType } from '../../utils/encoding/fromHex.js'
import { l1BlockAbi } from '../abis.js'
import { contracts } from '../contracts.js'
export type EstimateOperatorFeeParameters<
TChain extends Chain | undefined = Chain | undefined,
TAccount extends Account | undefined = Account | undefined,
TChainOverride extends Chain | undefined = undefined,
> = Omit<TransactionRequestEIP1559, 'from'> &
GetAccountParameter<TAccount> &
GetChainParameter<TChain, TChainOverride> & {
/** L1 block attributes contract address. */
l1BlockAddress?: Address | undefined
}
export type EstimateOperatorFeeReturnType = bigint
export type EstimateOperatorFeeErrorType =
| RequestErrorType
| EstimateGasErrorType
| HexToNumberErrorType
| ReadContractErrorType
| ErrorType
/**
* Estimates the operator fee required to execute an L2 transaction.
*
* Operator fees are part of the Isthmus upgrade and allow OP Stack operators
* to recover costs related to Alt-DA, ZK proving, or custom gas tokens.
* Returns 0 for pre-Isthmus chains or when operator fee functions don't exist.
*
* @param client - Client to use
* @param parameters - {@link EstimateOperatorFeeParameters}
* @returns The operator fee (in wei). {@link EstimateOperatorFeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateOperatorFee } from 'viem/chains/optimism'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const operatorFee = await estimateOperatorFee(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function estimateOperatorFee<
TChain extends Chain | undefined,
TAccount extends Account | undefined,
TChainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, TChain, TAccount>,
args: EstimateOperatorFeeParameters<TChain, TAccount, TChainOverride>,
): Promise<EstimateOperatorFeeReturnType> {
const { chain = client.chain, l1BlockAddress: l1BlockAddress_ } = args
const l1BlockAddress = (() => {
if (l1BlockAddress_) return l1BlockAddress_
if (chain?.contracts?.l1Block)
return getChainContractAddress({
chain,
contract: 'l1Block',
})
return contracts.l1Block.address
})()
// Try to get operator fee parameters. If any of these calls fail,
// it means this is a pre-Isthmus chain and operator fees don't apply
try {
// Get operator fee parameters first to fail fast if not supported
const [operatorFeeScalar, operatorFeeConstant] = await Promise.all([
readContract(client, {
abi: l1BlockAbi,
address: l1BlockAddress,
functionName: 'operatorFeeScalar',
}),
readContract(client, {
abi: l1BlockAbi,
address: l1BlockAddress,
functionName: 'operatorFeeConstant',
}),
])
// Estimate gas for the actual transaction
const gasUsed = await estimateGas(client, args as EstimateGasParameters)
// Calculate operator fee: saturatingAdd(saturatingMul(gasUsed, scalar) / 1e6, constant)
// Using saturating arithmetic to prevent overflow
const scaledFee = (gasUsed * BigInt(operatorFeeScalar)) / 1_000_000n
return scaledFee + BigInt(operatorFeeConstant)
} catch {
// If any call fails, this is likely a pre-Isthmus chain or the contract
// doesn't support these functions. Return 0 for operator fee.
return 0n
}
}

View File

@@ -0,0 +1,146 @@
import type { Address } from 'abitype'
import {
type EstimateContractGasErrorType,
type EstimateContractGasParameters,
estimateContractGas,
} from '../../actions/public/estimateContractGas.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hex } from '../../types/misc.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { portalAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
export type EstimateProveWithdrawalGasParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'portal'> & {
/** Gas limit for transaction execution on the L2. */
gas?: bigint | undefined
l2OutputIndex: bigint
outputRootProof: {
version: Hex
stateRoot: Hex
messagePasserStorageRoot: Hex
latestBlockhash: Hex
}
withdrawalProof: readonly Hex[]
withdrawal: {
data: Hex
gasLimit: bigint
nonce: bigint
sender: Address
target: Address
value: bigint
}
}
export type EstimateProveWithdrawalGasReturnType = bigint
export type EstimateProveWithdrawalGasErrorType =
| EstimateContractGasErrorType
| ErrorType
/**
* Estimates gas required to prove a withdrawal that occurred on an L2.
*
* - Docs: https://viem.sh/op-stack/actions/estimateProveWithdrawalGas
*
* @param client - Client to use
* @param parameters - {@link EstimateProveWithdrawalGasParameters}
* @returns Estimated gas. {@link EstimateProveWithdrawalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { estimateProveWithdrawalGas } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const gas = await estimateProveWithdrawalGas(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* l2OutputIndex: 4529n,
* outputRootProof: { ... },
* targetChain: optimism,
* withdrawalProof: [ ... ],
* withdrawal: { ... },
* })
*/
export async function estimateProveWithdrawalGas<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: EstimateProveWithdrawalGasParameters<
chain,
account,
chainOverride
>,
) {
const {
account,
chain = client.chain,
gas,
l2OutputIndex,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
outputRootProof,
targetChain,
withdrawalProof,
withdrawal,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const params = {
account,
abi: portalAbi,
address: portalAddress,
functionName: 'proveWithdrawalTransaction',
args: [withdrawal, l2OutputIndex, outputRootProof, withdrawalProof],
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
// TODO: Not sure `chain` is necessary since it's not used downstream
// in `estimateContractGas` or `estimateGas`
// @ts-expect-error
chain,
} satisfies EstimateContractGasParameters<
typeof portalAbi,
'proveWithdrawalTransaction'
>
return estimateContractGas(client, params as any)
}

94
node_modules/viem/op-stack/actions/estimateTotalFee.ts generated vendored Normal file
View File

@@ -0,0 +1,94 @@
import {
type EstimateGasErrorType,
type EstimateGasParameters,
estimateGas,
} from '../../actions/public/estimateGas.js'
import {
type GetGasPriceErrorType,
getGasPrice,
} from '../../actions/public/getGasPrice.js'
import {
type PrepareTransactionRequestErrorType,
type PrepareTransactionRequestParameters,
prepareTransactionRequest,
} from '../../actions/wallet/prepareTransactionRequest.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import type { RequestErrorType } from '../../utils/buildRequest.js'
import {
type EstimateL1FeeErrorType,
type EstimateL1FeeParameters,
estimateL1Fee,
} from './estimateL1Fee.js'
import {
type EstimateOperatorFeeErrorType,
type EstimateOperatorFeeParameters,
estimateOperatorFee,
} from './estimateOperatorFee.js'
export type EstimateTotalFeeParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = EstimateL1FeeParameters<chain, account, chainOverride> &
EstimateOperatorFeeParameters<chain, account, chainOverride>
export type EstimateTotalFeeReturnType = bigint
export type EstimateTotalFeeErrorType =
| RequestErrorType
| PrepareTransactionRequestErrorType
| EstimateL1FeeErrorType
| EstimateOperatorFeeErrorType
| EstimateGasErrorType
| GetGasPriceErrorType
| ErrorType
/**
* Estimates the L1 data fee + L2 fee + operator fee to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateTotalFeeParameters}
* @returns The fee (in wei). {@link EstimateTotalFeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateTotalFee } from 'viem/chains/optimism'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const totalGas = await estimateTotalFee(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function estimateTotalFee<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
args: EstimateTotalFeeParameters<chain, account, chainOverride>,
): Promise<EstimateTotalFeeReturnType> {
// Populate transaction with required fields to accurately estimate gas.
const request = await prepareTransactionRequest(
client,
args as PrepareTransactionRequestParameters,
)
const [l1Fee, operatorFee, l2Gas, l2GasPrice] = await Promise.all([
estimateL1Fee(client, request as EstimateL1FeeParameters),
estimateOperatorFee(client, request as EstimateOperatorFeeParameters),
estimateGas(client, request as EstimateGasParameters),
getGasPrice(client),
])
return l1Fee + operatorFee + l2Gas * l2GasPrice
}

70
node_modules/viem/op-stack/actions/estimateTotalGas.ts generated vendored Normal file
View File

@@ -0,0 +1,70 @@
import {
type EstimateGasErrorType,
type EstimateGasParameters,
estimateGas,
} from '../../actions/public/estimateGas.js'
import type { PrepareTransactionRequestErrorType } from '../../actions/wallet/prepareTransactionRequest.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import type { RequestErrorType } from '../../utils/buildRequest.js'
import {
type EstimateL1GasErrorType,
type EstimateL1GasParameters,
estimateL1Gas,
} from './estimateL1Gas.js'
export type EstimateTotalGasParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = EstimateL1GasParameters<chain, account, chainOverride>
export type EstimateTotalGasReturnType = bigint
export type EstimateTotalGasErrorType =
| RequestErrorType
| PrepareTransactionRequestErrorType
| EstimateL1GasErrorType
| EstimateGasErrorType
| ErrorType
/**
* Estimates the amount of L1 data gas + L2 gas required to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateTotalGasParameters}
* @returns The gas estimate. {@link EstimateTotalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { estimateTotalGas } from 'viem/chains/optimism'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const totalGas = await estimateTotalGas(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
export async function estimateTotalGas<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
args: EstimateTotalGasParameters<chain, account, chainOverride>,
): Promise<EstimateTotalGasReturnType> {
const [l1Gas, l2Gas] = await Promise.all([
estimateL1Gas(client, args as EstimateL1GasParameters),
estimateGas(client, args as EstimateGasParameters),
])
return l1Gas + l2Gas
}

View File

@@ -0,0 +1,133 @@
import type { Address } from 'abitype'
import {
type WriteContractErrorType,
type WriteContractParameters,
writeContract,
} from '../../actions/wallet/writeContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hash } from '../../types/misc.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { portal2Abi, portalAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { Withdrawal } from '../types/withdrawal.js'
import type { EstimateFinalizeWithdrawalGasErrorType } from './estimateFinalizeWithdrawalGas.js'
export type FinalizeWithdrawalParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'portal'> & {
/**
* Gas limit for transaction execution on the L1.
* `null` to skip gas estimation & defer calculation to signer.
*/
gas?: bigint | null | undefined
/**
* Finalize against a provided proof submitter.
* If unspecified, the sending account is the default.
*/
proofSubmitter?: Address | null | undefined
withdrawal: Withdrawal
}
export type FinalizeWithdrawalReturnType = Hash
export type FinalizeWithdrawalErrorType =
| EstimateFinalizeWithdrawalGasErrorType
| WriteContractErrorType
| ErrorType
/**
* Finalizes a withdrawal that occurred on an L2. Used in the Withdrawal flow.
*
* - Docs: https://viem.sh/op-stack/actions/finalizeWithdrawal
*
* @param client - Client to use
* @param parameters - {@link FinalizeWithdrawalParameters}
* @returns The finalize transaction hash. {@link FinalizeWithdrawalReturnType}
*
* @example
* import { createWalletClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { finalizeWithdrawal } from 'viem/op-stack'
*
* const walletClientL1 = createWalletClient({
* chain: mainnet,
* transport: http(),
* })
*
* const request = await finalizeWithdrawal(walletClientL1, {
* targetChain: optimism,
* withdrawal: { ... },
* })
*/
export async function finalizeWithdrawal<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: FinalizeWithdrawalParameters<chain, account, chainOverride>,
): Promise<FinalizeWithdrawalReturnType> {
const {
account,
chain = client.chain,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
proofSubmitter,
targetChain,
withdrawal,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const [functionName, args, abi] = proofSubmitter
? [
'finalizeWithdrawalTransactionExternalProof',
[withdrawal, proofSubmitter],
portal2Abi,
]
: ['finalizeWithdrawalTransaction', [withdrawal], portalAbi]
return writeContract(client, {
account: account!,
abi,
address: portalAddress,
chain,
functionName,
args,
gas: gas ?? undefined,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
} satisfies WriteContractParameters as any)
}

99
node_modules/viem/op-stack/actions/getGame.ts generated vendored Normal file
View File

@@ -0,0 +1,99 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import {
GameNotFoundError,
type GameNotFoundErrorType,
} from '../errors/withdrawal.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { Game } from '../types/withdrawal.js'
import { type GetGamesErrorType, getGames } from './getGames.js'
export type GetGameParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<
_derivedChain,
'portal' | 'disputeGameFactory'
> & {
/**
* The minimum block number of the dispute game.
*/
l2BlockNumber: bigint
/**
* Limit of games to extract.
* @default 100
*/
limit?: number | undefined
/**
* Strategy for extracting a dispute game.
*
* - `latest` - Returns the latest dispute game.
* - `random` - Returns a random dispute game.
*/
strategy?: 'latest' | 'random'
}
export type GetGameReturnType = Game & {
l2BlockNumber: bigint
}
export type GetGameErrorType =
| GetGamesErrorType
| GameNotFoundErrorType
| ErrorType
/**
* Retrieves a valid dispute game on an L2 that occurred after a provided L2 block number.
*
* - Docs: https://viem.sh/op-stack/actions/getGame
*
* @param client - Client to use
* @param parameters - {@link GetGameParameters}
* @returns A valid dispute game. {@link GetGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { getGame } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const game = await getGame(publicClientL1, {
* l2BlockNumber: 69420n,
* targetChain: optimism
* })
*/
export async function getGame<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetGameParameters<chain, chainOverride>,
): Promise<GetGameReturnType> {
const { l2BlockNumber, strategy = 'latest' } = parameters
const latestGames = await getGames(client, parameters)
const games = latestGames.filter((game) => game.l2BlockNumber > l2BlockNumber)
const game = (() => {
if (strategy === 'random')
return games[Math.floor(Math.random() * games.length)]
return games[0]
})()
if (!game) throw new GameNotFoundError()
return game
}

146
node_modules/viem/op-stack/actions/getGames.ts generated vendored Normal file
View File

@@ -0,0 +1,146 @@
import type { Address } from 'abitype'
import {
type MulticallErrorType,
multicall,
} from '../../actions/public/multicall.js'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import { disputeGameAbi, disputeGameFactoryAbi, portal2Abi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { Game } from '../types/withdrawal.js'
export type GetGamesParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<
_derivedChain,
'portal' | 'disputeGameFactory'
> & {
/**
* Filter by minimum block number of the dispute games.
*/
l2BlockNumber?: bigint | undefined
/**
* Limit of games to extract.
* @default 100
*/
limit?: number | undefined
}
export type GetGamesReturnType = (Game & {
l2BlockNumber: bigint
})[]
export type GetGamesErrorType =
| ReadContractErrorType
| MulticallErrorType
| ErrorType
/**
* Retrieves dispute games for an L2.
*
* - Docs: https://viem.sh/op-stack/actions/getGame
*
* @param client - Client to use
* @param parameters - {@link GetGameParameters}
* @returns Dispute games. {@link GetGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { getGames } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const games = await getGames(publicClientL1, {
* targetChain: optimism
* })
*/
export async function getGames<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetGamesParameters<chain, chainOverride>,
): Promise<GetGamesReturnType> {
const {
chain = client.chain,
l2BlockNumber,
limit = 100,
targetChain,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const disputeGameFactoryAddress = (() => {
if (parameters.disputeGameFactoryAddress)
return parameters.disputeGameFactoryAddress
if (chain)
return targetChain!.contracts.disputeGameFactory[chain.id].address
return Object.values(targetChain!.contracts.disputeGameFactory)[0].address
})()
const [gameCount, gameType] = await Promise.all([
readContract(client, {
abi: disputeGameFactoryAbi,
functionName: 'gameCount',
args: [],
address: disputeGameFactoryAddress,
}),
readContract(client, {
abi: portal2Abi,
functionName: 'respectedGameType',
address: portalAddress,
}),
])
const rawGames = (await readContract(client, {
abi: disputeGameFactoryAbi,
functionName: 'findLatestGames',
address: disputeGameFactoryAddress,
args: [
gameType,
BigInt(Math.max(0, Number(gameCount - 1n))),
BigInt(Math.min(limit, Number(gameCount))),
],
})) as Game[]
const l2SequenceNumbers = await multicall(client, {
allowFailure: false,
contracts: rawGames.map((game) => ({
abi: disputeGameAbi,
address: `0x${game.metadata.slice(26)}` as Address,
functionName: 'l2SequenceNumber' as const,
})),
})
const games = rawGames
.map((game, i) => {
const blockNumber = l2SequenceNumbers[i] as bigint
return !l2BlockNumber || blockNumber > l2BlockNumber
? { ...game, l2BlockNumber: blockNumber }
: null
})
.filter(Boolean) as GetGamesReturnType
return games
}

81
node_modules/viem/op-stack/actions/getL1BaseFee.ts generated vendored Normal file
View File

@@ -0,0 +1,81 @@
import type { Address } from 'abitype'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { PrepareTransactionRequestErrorType } from '../../actions/wallet/prepareTransactionRequest.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Chain, GetChainParameter } from '../../types/chain.js'
import type { RequestErrorType } from '../../utils/buildRequest.js'
import { getChainContractAddress } from '../../utils/chain/getChainContractAddress.js'
import type { HexToNumberErrorType } from '../../utils/encoding/fromHex.js'
import { gasPriceOracleAbi } from '../abis.js'
import { contracts } from '../contracts.js'
export type GetL1BaseFeeParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = undefined,
> = GetChainParameter<chain, chainOverride> & {
/** Gas price oracle address. */
gasPriceOracleAddress?: Address | undefined
}
export type GetL1BaseFeeReturnType = bigint
export type GetL1BaseFeeErrorType =
| RequestErrorType
| PrepareTransactionRequestErrorType
| HexToNumberErrorType
| ReadContractErrorType
| ErrorType
/**
* get the L1 base fee
*
* @param client - Client to use
* @param parameters - {@link GetL1BaseFeeParameters}
* @returns The basefee (in wei). {@link GetL1BaseFeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { getL1BaseFee } from 'viem/chains/optimism'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* })
* const l1BaseFee = await getL1BaseFee(client)
*/
export async function getL1BaseFee<
chain extends Chain | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain>,
args?: GetL1BaseFeeParameters<chain, chainOverride> | undefined,
): Promise<GetL1BaseFeeReturnType> {
const {
chain = client.chain,
gasPriceOracleAddress: gasPriceOracleAddress_,
} = args || {}
const gasPriceOracleAddress = (() => {
if (gasPriceOracleAddress_) return gasPriceOracleAddress_
if (chain)
return getChainContractAddress({
chain,
contract: 'gasPriceOracle',
})
return contracts.gasPriceOracle.address
})()
return readContract(client, {
abi: gasPriceOracleAbi,
address: gasPriceOracleAddress,
functionName: 'l1BaseFee',
})
}

130
node_modules/viem/op-stack/actions/getL2Output.ts generated vendored Normal file
View File

@@ -0,0 +1,130 @@
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hex } from '../../types/misc.js'
import type { OneOf } from '../../types/utils.js'
import { l2OutputOracleAbi } from '../abis.js'
import type { TargetChain } from '../types/chain.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import { type GetGameParameters, getGame } from './getGame.js'
import {
type GetPortalVersionParameters,
getPortalVersion,
} from './getPortalVersion.js'
export type GetL2OutputParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
OneOf<
| GetContractAddressParameter<_derivedChain, 'l2OutputOracle'>
| (GetContractAddressParameter<
_derivedChain,
'portal' | 'disputeGameFactory'
> & {
/**
* Limit of games to extract.
* @default 100
*/
limit?: number | undefined
})
> & {
l2BlockNumber: bigint
}
export type GetL2OutputReturnType = {
outputIndex: bigint
outputRoot: Hex
timestamp: bigint
l2BlockNumber: bigint
}
export type GetL2OutputErrorType = ReadContractErrorType | ErrorType
/**
* Retrieves the first L2 output proposal that occurred after a provided block number.
*
* - Docs: https://viem.sh/op-stack/actions/getL2Output
*
* @param client - Client to use
* @param parameters - {@link GetL2OutputParameters}
* @returns The L2 output. {@link GetL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { getL2Output } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const output = await getL2Output(publicClientL1, {
* l2BlockNumber: 69420n,
* targetChain: optimism
* })
*/
export async function getL2Output<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetL2OutputParameters<chain, chainOverride>,
): Promise<GetL2OutputReturnType> {
const { chain = client.chain, l2BlockNumber, targetChain } = parameters
const version = await getPortalVersion(
client,
parameters as GetPortalVersionParameters,
)
if (version.major >= 3) {
const game = await getGame(client, parameters as GetGameParameters)
return {
l2BlockNumber: game.l2BlockNumber,
outputIndex: game.index,
outputRoot: game.rootClaim,
timestamp: game.timestamp,
}
}
const l2OutputOracleAddress = (() => {
if (parameters.l2OutputOracleAddress)
return parameters.l2OutputOracleAddress
if (chain)
return (targetChain as unknown as TargetChain)!.contracts.l2OutputOracle[
chain.id
].address
return (
Object.values(
(targetChain as unknown as TargetChain)!.contracts.l2OutputOracle,
) as any
)[0].address
})()
const outputIndex = await readContract(client, {
address: l2OutputOracleAddress,
abi: l2OutputOracleAbi,
functionName: 'getL2OutputIndexAfter',
args: [l2BlockNumber],
})
const output = await readContract(client, {
address: l2OutputOracleAddress,
abi: l2OutputOracleAbi,
functionName: 'getL2Output',
args: [outputIndex],
})
return { outputIndex, ...output }
}

87
node_modules/viem/op-stack/actions/getPortalVersion.ts generated vendored Normal file
View File

@@ -0,0 +1,87 @@
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import { withCache } from '../../utils/promise/withCache.js'
import { portal2Abi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
export type GetPortalVersionParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'portal'>
export type GetPortalVersionReturnType = {
major: number
minor: number
patch: number
}
export type GetPortalVersionErrorType = ReadContractErrorType | ErrorType
/**
* Retrieves the current version of the Portal contract.
*
* - Docs: https://viem.sh/op-stack/actions/getPortalVersion
*
* @param client - Client to use
* @param parameters - {@link GetPortalVersionParameters}
* @returns The version object.
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
* import { getPortalVersion } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const version = await getPortalVersion(publicClientL1, {
* targetChain: optimism,
* })
*
* if (version.major > 3)
* console.log('Fault proofs are enabled on this version of optimism')
* console.log('Fault proofs are not enabled on this version of optimism')
*/
export async function getPortalVersion<
chain extends Chain | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain>,
parameters: GetPortalVersionParameters<chain, chainOverride>,
) {
const { chain = client.chain, targetChain } = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const version = await withCache(
() =>
readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'version',
}),
{ cacheKey: ['portalVersion', portalAddress].join('.'), cacheTime: 300 },
)
const [major, minor, patch] = version.split('.').map(Number)
return { major, minor, patch }
}

175
node_modules/viem/op-stack/actions/getTimeToFinalize.ts generated vendored Normal file
View File

@@ -0,0 +1,175 @@
import {
type MulticallErrorType,
multicall,
} from '../../actions/public/multicall.js'
import { readContract } from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import { BaseError } from '../../errors/base.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hash } from '../../types/misc.js'
import { l2OutputOracleAbi, portal2Abi, portalAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import { getPortalVersion } from './getPortalVersion.js'
export type GetTimeToFinalizeParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'l2OutputOracle' | 'portal'> & {
withdrawalHash: Hash
}
export type GetTimeToFinalizeReturnType = {
/** The finalization period (in seconds). */
period: number
/** Seconds until the withdrawal can be finalized. */
seconds: number
/** Timestamp of when the withdrawal can be finalized. */
timestamp: number
}
export type GetTimeToFinalizeErrorType = MulticallErrorType | ErrorType
const buffer = 10
/**
* Returns the time until the withdrawal transaction can be finalized. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToFinalize
*
* @param client - Client to use
* @param parameters - {@link GetTimeToFinalizeParameters}
* @returns Time until finalize. {@link GetTimeToFinalizeReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { getTimeToFinalize } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({
* hash: '0x9a2f4283636ddeb9ac32382961b22c177c9e86dd3b283735c154f897b1a7ff4a',
* })
*
* const [withdrawal] = getWithdrawals(receipt)
*
* const { seconds } = await getTimeToFinalize(publicClientL1, {
* withdrawalHash: withdrawal.withdrawalHash,
* targetChain: optimism
* })
*/
export async function getTimeToFinalize<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetTimeToFinalizeParameters<chain, chainOverride>,
): Promise<GetTimeToFinalizeReturnType> {
const { chain = client.chain, withdrawalHash, targetChain } = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
const portalVersion = await getPortalVersion(client, { portalAddress })
// Legacy
if (portalVersion.major < 3) {
const l2OutputOracleAddress = (() => {
if (parameters.l2OutputOracleAddress)
return parameters.l2OutputOracleAddress
if (chain) return targetChain!.contracts.l2OutputOracle[chain.id].address
return Object.values(targetChain!.contracts.l2OutputOracle)[0].address
})()
const [[_outputRoot, proveTimestamp, _l2OutputIndex], period] =
await multicall(client, {
allowFailure: false,
contracts: [
{
abi: portalAbi,
address: portalAddress,
functionName: 'provenWithdrawals',
args: [withdrawalHash],
},
{
abi: l2OutputOracleAbi,
address: l2OutputOracleAddress,
functionName: 'FINALIZATION_PERIOD_SECONDS',
},
],
})
const secondsSinceProven = Date.now() / 1000 - Number(proveTimestamp)
const secondsToFinalize = Number(period) - secondsSinceProven
const seconds = Math.floor(
secondsToFinalize < 0 ? 0 : secondsToFinalize + buffer,
)
const timestamp = Date.now() + seconds * 1000
return { period: Number(period), seconds, timestamp }
}
const numProofSubmitters = await readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'numProofSubmitters',
args: [withdrawalHash],
}).catch(() => 1n)
const proofSubmitter = await readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'proofSubmitters',
args: [withdrawalHash, numProofSubmitters - 1n],
}).catch(() => undefined)
const [[_disputeGameProxy, proveTimestamp], proofMaturityDelaySeconds] =
await Promise.all([
proofSubmitter
? readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'provenWithdrawals',
args: [withdrawalHash, proofSubmitter],
})
: Promise.resolve(['0x', 0n]),
readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'proofMaturityDelaySeconds',
}),
])
if (proveTimestamp === 0n)
throw new BaseError('Withdrawal has not been proven on L1.')
const secondsSinceProven = Date.now() / 1000 - Number(proveTimestamp)
const secondsToFinalize =
Number(proofMaturityDelaySeconds) - secondsSinceProven
const seconds = Math.floor(
secondsToFinalize < 0n ? 0 : secondsToFinalize + buffer,
)
const timestamp = Date.now() + seconds * 1000
return { period: Number(proofMaturityDelaySeconds), seconds, timestamp }
}

157
node_modules/viem/op-stack/actions/getTimeToNextGame.ts generated vendored Normal file
View File

@@ -0,0 +1,157 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import { type GetGamesErrorType, getGames } from './getGames.js'
export type GetTimeToNextGameParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<
_derivedChain,
'portal' | 'disputeGameFactory'
> & {
/**
* The buffer to account for discrepancies between non-deterministic time intervals.
* @default 1.1
*/
intervalBuffer?: number | undefined
/**
* The minimum L2 block number of the next game.
*/
l2BlockNumber: bigint
}
export type GetTimeToNextGameReturnType = {
/** The estimated interval (in seconds) between L2 dispute games. */
interval: number
/**
* Estimated seconds until the next L2 dispute game.
* `0` if the next L2 dispute game has already been submitted.
*/
seconds: number
/**
* Estimated timestamp of the next L2 dispute game.
* `undefined` if the next L2 dispute game has already been submitted.
*/
timestamp?: number | undefined
}
export type GetTimeToNextGameErrorType = GetGamesErrorType | ErrorType
/**
* Returns the time until the next L2 dispute game (after the provided block number) is submitted.
* Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToNextGame
*
* @param client - Client to use
* @param parameters - {@link GetTimeToNextGameParameters}
* @returns The L2 transaction hash. {@link GetTimeToNextGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { getTimeToNextGame } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const { seconds } = await getTimeToNextGame(publicClientL1, {
* l2BlockNumber: 113405763n,
* targetChain: optimism
* })
*/
export async function getTimeToNextGame<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetTimeToNextGameParameters<chain, chainOverride>,
): Promise<GetTimeToNextGameReturnType> {
const { intervalBuffer = 1.1, l2BlockNumber } = parameters
const games = await getGames(client, {
...parameters,
l2BlockNumber: undefined,
limit: 10,
})
if (games.length === 0) {
return { interval: 0, seconds: 0, timestamp: undefined }
}
const deltas = games
.map(({ l2BlockNumber, timestamp }, index) => {
return index === games.length - 1
? null
: [
games[index + 1].timestamp - timestamp,
games[index + 1].l2BlockNumber - l2BlockNumber,
]
})
.filter(Boolean)
const interval =
deltas.length > 0
? Math.ceil(
(deltas as [bigint, bigint][]).reduce(
(a, [b]) => Number(a) - Number(b),
0,
) / deltas.length,
)
: 0
const blockInterval =
deltas.length > 0
? Math.ceil(
(deltas as [bigint, bigint][]).reduce(
(a, [_, b]) => Number(a) - Number(b),
0,
) / deltas.length,
)
: 0
const latestGame = games[0]
const latestGameTimestamp = Number(latestGame.timestamp) * 1000
const intervalWithBuffer = Math.ceil(interval * intervalBuffer)
const now = Date.now()
const seconds = (() => {
// If the current timestamp is lesser than the latest dispute game timestamp,
// then we assume that the dispute game has already been submitted.
if (now < latestGameTimestamp) return 0
// If the latest dispute game block is newer than the provided dispute game block number,
// then we assume that the dispute game has already been submitted.
if (latestGame.l2BlockNumber > l2BlockNumber) return 0
// If there is only a single game, no interval data
if (intervalWithBuffer === 0) return 0
const elapsedBlocks = Number(l2BlockNumber - latestGame.l2BlockNumber)
const elapsed = Math.ceil((now - latestGameTimestamp) / 1000)
const secondsToNextOutput =
intervalWithBuffer - (elapsed % intervalWithBuffer)
return elapsedBlocks < blockInterval
? secondsToNextOutput
: Math.floor(elapsedBlocks / Number(blockInterval)) * intervalWithBuffer +
secondsToNextOutput
})()
const timestamp = seconds > 0 ? now + seconds * 1000 : undefined
return { interval, seconds, timestamp }
}

View File

@@ -0,0 +1,162 @@
import {
type MulticallErrorType,
multicall,
} from '../../actions/public/multicall.js'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import { l2OutputOracleAbi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
export type GetTimeToNextL2OutputParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'l2OutputOracle'> & {
/**
* The buffer to account for discrepancies between non-deterministic time intervals.
* @default 1.1
*/
intervalBuffer?: number | undefined
l2BlockNumber: bigint
}
export type GetTimeToNextL2OutputReturnType = {
/** The interval (in seconds) between L2 outputs. */
interval: number
/**
* Seconds until the next L2 output.
* `0` if the next L2 output has already been submitted.
*/
seconds: number
/**
* Estimated timestamp of the next L2 output.
* `undefined` if the next L2 output has already been submitted.
*/
timestamp?: number | undefined
}
export type GetTimeToNextL2OutputErrorType =
| MulticallErrorType
| ReadContractErrorType
| ErrorType
/**
* Returns the time until the next L2 output (after the provided block number) is submitted. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToNextL2Output
*
* @param client - Client to use
* @param parameters - {@link GetTimeToNextL2OutputParameters}
* @returns The L2 transaction hash. {@link GetTimeToNextL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { getTimeToNextL2Output } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const { seconds } = await getTimeToNextL2Output(publicClientL1, {
* targetChain: optimism
* })
*/
export async function getTimeToNextL2Output<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetTimeToNextL2OutputParameters<chain, chainOverride>,
): Promise<GetTimeToNextL2OutputReturnType> {
const {
intervalBuffer = 1.1,
chain = client.chain,
l2BlockNumber,
targetChain,
} = parameters
const l2OutputOracleAddress = (() => {
if (parameters.l2OutputOracleAddress)
return parameters.l2OutputOracleAddress
if (chain) return targetChain!.contracts.l2OutputOracle[chain.id].address
return Object.values(targetChain!.contracts.l2OutputOracle)[0].address
})()
const [latestOutputIndex, blockTime, blockInterval] = await multicall(
client,
{
allowFailure: false,
contracts: [
{
abi: l2OutputOracleAbi,
address: l2OutputOracleAddress,
functionName: 'latestOutputIndex',
},
{
abi: l2OutputOracleAbi,
address: l2OutputOracleAddress,
functionName: 'L2_BLOCK_TIME',
},
{
abi: l2OutputOracleAbi,
address: l2OutputOracleAddress,
functionName: 'SUBMISSION_INTERVAL',
},
],
},
)
const latestOutput = await readContract(client, {
abi: l2OutputOracleAbi,
address: l2OutputOracleAddress,
functionName: 'getL2Output',
args: [latestOutputIndex],
})
const latestOutputTimestamp = Number(latestOutput.timestamp) * 1000
const interval = Number(blockInterval * blockTime)
const intervalWithBuffer = Math.ceil(interval * intervalBuffer)
const now = Date.now()
const seconds = (() => {
// If the current timestamp is lesser than the latest L2 output timestamp,
// then we assume that the L2 output has already been submitted.
if (now < latestOutputTimestamp) return 0
// If the latest L2 output block is newer than the provided L2 block number,
// then we assume that the L2 output has already been submitted.
if (latestOutput.l2BlockNumber > l2BlockNumber) return 0
const elapsedBlocks = Number(l2BlockNumber - latestOutput.l2BlockNumber)
const elapsed = Math.ceil((now - latestOutputTimestamp) / 1000)
const secondsToNextOutput =
intervalWithBuffer - (elapsed % intervalWithBuffer)
return elapsedBlocks < blockInterval
? secondsToNextOutput
: Math.floor(elapsedBlocks / Number(blockInterval)) * intervalWithBuffer +
secondsToNextOutput
})()
const timestamp = seconds > 0 ? now + seconds * 1000 : undefined
return { interval, seconds, timestamp }
}

119
node_modules/viem/op-stack/actions/getTimeToProve.ts generated vendored Normal file
View File

@@ -0,0 +1,119 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { TransactionReceipt } from '../../types/transaction.js'
import type { OneOf } from '../../types/utils.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import {
type GetPortalVersionErrorType,
type GetPortalVersionParameters,
getPortalVersion,
} from './getPortalVersion.js'
import {
type GetTimeToNextGameErrorType,
type GetTimeToNextGameParameters,
type GetTimeToNextGameReturnType,
getTimeToNextGame,
} from './getTimeToNextGame.js'
import {
type GetTimeToNextL2OutputErrorType,
type GetTimeToNextL2OutputParameters,
type GetTimeToNextL2OutputReturnType,
getTimeToNextL2Output,
} from './getTimeToNextL2Output.js'
export type GetTimeToProveParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
OneOf<
| GetContractAddressParameter<_derivedChain, 'l2OutputOracle'>
| GetContractAddressParameter<
_derivedChain,
'disputeGameFactory' | 'portal'
>
> & {
/**
* The buffer to account for discrepancies between non-deterministic time intervals.
* @default 1.1
*/
intervalBuffer?:
| GetTimeToNextL2OutputParameters['intervalBuffer']
| undefined
receipt: TransactionReceipt
}
export type GetTimeToProveReturnType =
| GetTimeToNextGameReturnType
| GetTimeToNextL2OutputReturnType
export type GetTimeToProveErrorType =
| GetPortalVersionErrorType
| GetTimeToNextGameErrorType
| GetTimeToNextL2OutputErrorType
| ErrorType
/**
* Returns the time until the withdrawal transaction is ready to prove. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToProve
*
* @param client - Client to use
* @param parameters - {@link GetTimeToNextL2OutputParameters}
* @returns Time until prove step is ready. {@link GetTimeToNextL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { getTimeToProve } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({ hash: '0x...' })
* const { period, seconds, timestamp } = await getTimeToProve(publicClientL1, {
* receipt,
* targetChain: optimism
* })
*/
export async function getTimeToProve<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetTimeToProveParameters<chain, chainOverride>,
): Promise<GetTimeToProveReturnType> {
const { receipt } = parameters
const portalVersion = await getPortalVersion(
client,
parameters as GetPortalVersionParameters,
)
// Legacy
if (portalVersion.major < 3)
return getTimeToNextL2Output(client, {
...parameters,
l2BlockNumber: receipt.blockNumber,
} as GetTimeToNextL2OutputParameters)
return getTimeToNextGame(client, {
...parameters,
l2BlockNumber: receipt.blockNumber,
} as GetTimeToNextGameParameters)
}

View File

@@ -0,0 +1,419 @@
import type { Address } from 'abitype'
import {
type ReadContractErrorType,
readContract,
} from '../../actions/public/readContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import { ContractFunctionRevertedError } from '../../errors/contract.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hash } from '../../types/misc.js'
import type { TransactionReceipt } from '../../types/transaction.js'
import type { OneOf } from '../../types/utils.js'
import { anchorStateRegistryAbi, portal2Abi, portalAbi } from '../abis.js'
import {
ReceiptContainsNoWithdrawalsError,
type ReceiptContainsNoWithdrawalsErrorType,
} from '../errors/withdrawal.js'
import type { TargetChain } from '../types/chain.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import {
type GetWithdrawalsErrorType,
getWithdrawals,
} from '../utils/getWithdrawals.js'
import {
type GetGameErrorType,
type GetGameParameters,
getGame,
} from './getGame.js'
import {
type GetL2OutputErrorType,
type GetL2OutputParameters,
getL2Output,
} from './getL2Output.js'
import {
type GetPortalVersionParameters,
getPortalVersion,
} from './getPortalVersion.js'
import {
type GetTimeToFinalizeErrorType,
type GetTimeToFinalizeParameters,
getTimeToFinalize,
} from './getTimeToFinalize.js'
export type GetWithdrawalStatusParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
OneOf<
| GetContractAddressParameter<_derivedChain, 'l2OutputOracle' | 'portal'>
| GetContractAddressParameter<
_derivedChain,
'disputeGameFactory' | 'portal'
>
> & {
/**
* Limit of games to extract to check withdrawal status.
* @default 100
*/
gameLimit?: number
} & OneOf<
| {
/**
* The relative index of the withdrawal in the transaction receipt logs.
* @default 0
*/
logIndex?: number
/**
* The transaction receipt of the withdrawal.
*/
receipt: TransactionReceipt
}
| {
/**
* The L2 block number of the withdrawal.
*/
l2BlockNumber: bigint
/**
* The sender of the withdrawal.
*/
sender: Address
/**
* The hash of the withdrawal.
*/
withdrawalHash: Hash
}
>
export type GetWithdrawalStatusReturnType =
| 'waiting-to-prove'
| 'ready-to-prove'
| 'waiting-to-finalize'
| 'ready-to-finalize'
| 'finalized'
export type GetWithdrawalStatusErrorType =
| GetL2OutputErrorType
| GetTimeToFinalizeErrorType
| GetWithdrawalsErrorType
| ReadContractErrorType
| ReceiptContainsNoWithdrawalsErrorType
| ErrorType
/**
* Returns the current status of a withdrawal. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getWithdrawalStatus
*
* @param client - Client to use
* @param parameters - {@link GetWithdrawalStatusParameters}
* @returns Status of the withdrawal. {@link GetWithdrawalStatusReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { getWithdrawalStatus } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({ hash: '0x...' })
* const status = await getWithdrawalStatus(publicClientL1, {
* receipt,
* targetChain: optimism
* })
*/
export async function getWithdrawalStatus<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: GetWithdrawalStatusParameters<chain, chainOverride>,
): Promise<GetWithdrawalStatusReturnType> {
const {
chain = client.chain,
gameLimit = 100,
receipt,
targetChain: targetChain_,
logIndex = 0,
} = parameters
const targetChain = targetChain_ as unknown as TargetChain
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain.contracts.portal[chain.id].address
return Object.values(targetChain.contracts.portal)[0].address
})()
const l2BlockNumber = receipt?.blockNumber ?? parameters.l2BlockNumber
const withdrawal = (() => {
if (receipt) {
const withdrawal = getWithdrawals({ logs: receipt.logs })[logIndex]
if (!withdrawal)
throw new ReceiptContainsNoWithdrawalsError({
hash: receipt.transactionHash,
})
return withdrawal
}
return {
sender: parameters.sender,
withdrawalHash: parameters.withdrawalHash,
}
})()
const portalVersion = await getPortalVersion(
client,
parameters as GetPortalVersionParameters,
)
// Legacy (Portal < v3)
if (portalVersion.major < 3) {
const [outputResult, proveResult, finalizedResult, timeToFinalizeResult] =
await Promise.allSettled([
getL2Output(client, {
...parameters,
l2BlockNumber,
} as GetL2OutputParameters),
readContract(client, {
abi: portalAbi,
address: portalAddress,
functionName: 'provenWithdrawals',
args: [withdrawal.withdrawalHash],
}),
readContract(client, {
abi: portalAbi,
address: portalAddress,
functionName: 'finalizedWithdrawals',
args: [withdrawal.withdrawalHash],
}),
getTimeToFinalize(client, {
...parameters,
withdrawalHash: withdrawal.withdrawalHash,
} as GetTimeToFinalizeParameters),
])
// If the L2 Output is not processed yet (ie. the actions throws), this means
// that the withdrawal is not ready to prove.
if (outputResult.status === 'rejected') {
const error = outputResult.reason as GetL2OutputErrorType
if (
error.cause instanceof ContractFunctionRevertedError &&
error.cause.data?.args?.[0] ===
'L2OutputOracle: cannot get output for a block that has not been proposed'
)
return 'waiting-to-prove'
throw error
}
if (proveResult.status === 'rejected') throw proveResult.reason
if (finalizedResult.status === 'rejected') throw finalizedResult.reason
if (timeToFinalizeResult.status === 'rejected')
throw timeToFinalizeResult.reason
const [_, proveTimestamp] = proveResult.value
if (!proveTimestamp) return 'ready-to-prove'
const finalized = finalizedResult.value
if (finalized) return 'finalized'
const { seconds } = timeToFinalizeResult.value
return seconds > 0 ? 'waiting-to-finalize' : 'ready-to-finalize'
}
const numProofSubmitters = await readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'numProofSubmitters',
args: [withdrawal.withdrawalHash],
}).catch(() => 1n)
const proofSubmitter = await readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'proofSubmitters',
args: [withdrawal.withdrawalHash, numProofSubmitters - 1n],
}).catch(() => withdrawal.sender)
const [
disputeGameResult,
provenWithdrawalsResult,
checkWithdrawalResult,
finalizedResult,
] = await Promise.allSettled([
getGame(client, {
...parameters,
l2BlockNumber,
limit: gameLimit,
} as GetGameParameters),
readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'provenWithdrawals',
args: [withdrawal.withdrawalHash, proofSubmitter],
}),
readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'checkWithdrawal',
args: [withdrawal.withdrawalHash, proofSubmitter],
}),
readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'finalizedWithdrawals',
args: [withdrawal.withdrawalHash],
}),
])
if (finalizedResult.status === 'fulfilled' && finalizedResult.value)
return 'finalized'
if (provenWithdrawalsResult.status === 'rejected')
throw provenWithdrawalsResult.reason
if (disputeGameResult.status === 'rejected') {
const error = disputeGameResult.reason as GetGameErrorType
if (error.name === 'GameNotFoundError') return 'waiting-to-prove'
throw disputeGameResult.reason
}
if (checkWithdrawalResult.status === 'rejected') {
const error = checkWithdrawalResult.reason as ReadContractErrorType
if (error.cause instanceof ContractFunctionRevertedError) {
// All potential error causes listed here, can either be the error string or the error name
// if custom error types are returned.
const errorCauses = {
'ready-to-prove': [
'OptimismPortal: invalid game type',
'OptimismPortal: withdrawal has not been proven yet',
'OptimismPortal: withdrawal has not been proven by proof submitter address yet',
'OptimismPortal: dispute game created before respected game type was updated',
'InvalidGameType',
'LegacyGame',
'Unproven',
// After U16
'OptimismPortal_Unproven',
'OptimismPortal_InvalidProofTimestamp',
],
'waiting-to-finalize': [
'OptimismPortal: proven withdrawal has not matured yet',
'OptimismPortal: output proposal has not been finalized yet',
'OptimismPortal: output proposal in air-gap',
],
}
// Pick out the error message and/or error name
// Return the status based on the error
const errors = [
error.cause.data?.errorName,
error.cause.data?.args?.[0] as string,
]
// After U16 we get a generic error message (OptimismPortal_InvalidRootClaim) because the
// OptimismPortal will call AnchorStateRegistry.isGameClaimValid which simply returns
// true/false. If we get this generic error, we need to figure out why the function returned
// false and return a proper status accordingly. We can also check these conditions when we
// get ProofNotOldEnough so users can be notified when their pending proof becomes invalid
// before it can be finalized.
if (
errors.includes('OptimismPortal_InvalidRootClaim') ||
errors.includes('OptimismPortal_ProofNotOldEnough')
) {
// Get the dispute game address from the proven withdrawal.
const disputeGameAddress = provenWithdrawalsResult.value[0] as Address
// Get the AnchorStateRegistry address from the portal.
const anchorStateRegistry = await readContract(client, {
abi: portal2Abi,
address: portalAddress,
functionName: 'anchorStateRegistry',
})
// Check if the game is proper, respected, and finalized.
const [
isGameProperResult,
isGameRespectedResult,
isGameFinalizedResult,
] = await Promise.allSettled([
readContract(client, {
abi: anchorStateRegistryAbi,
address: anchorStateRegistry,
functionName: 'isGameProper',
args: [disputeGameAddress],
}),
readContract(client, {
abi: anchorStateRegistryAbi,
address: anchorStateRegistry,
functionName: 'isGameRespected',
args: [disputeGameAddress],
}),
readContract(client, {
abi: anchorStateRegistryAbi,
address: anchorStateRegistry,
functionName: 'isGameFinalized',
args: [disputeGameAddress],
}),
])
// If any of the calls failed, throw the error.
if (isGameProperResult.status === 'rejected')
throw isGameProperResult.reason
if (isGameRespectedResult.status === 'rejected')
throw isGameRespectedResult.reason
if (isGameFinalizedResult.status === 'rejected')
throw isGameFinalizedResult.reason
// If the game isn't proper, the user needs to re-prove.
if (!isGameProperResult.value) {
return 'ready-to-prove'
}
// If the game isn't respected, the user needs to re-prove.
if (!isGameRespectedResult.value) {
return 'ready-to-prove'
}
// If the game isn't finalized, the user needs to wait to finalize.
if (!isGameFinalizedResult.value) {
return 'waiting-to-finalize'
}
// If the actual error was ProofNotOldEnough, then at this point the game is probably
// completely fine but the proof hasn't passed the waiting period. Otherwise, the only
// reason we'd be here is if the game resolved in favor of the challenger, which means the
// user needs to re-prove the withdrawal.
if (errors.includes('OptimismPortal_ProofNotOldEnough')) {
return 'waiting-to-finalize'
}
return 'ready-to-prove'
}
if (errorCauses['ready-to-prove'].some((cause) => errors.includes(cause)))
return 'ready-to-prove'
if (
errorCauses['waiting-to-finalize'].some((cause) =>
errors.includes(cause),
)
)
return 'waiting-to-finalize'
}
throw checkWithdrawalResult.reason
}
if (finalizedResult.status === 'rejected') throw finalizedResult.reason
return 'ready-to-finalize'
}

View File

@@ -0,0 +1,141 @@
import type { Address } from 'abitype'
import {
type WriteContractErrorType,
type WriteContractParameters,
writeContract,
} from '../../actions/wallet/writeContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hash } from '../../types/misc.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { l2ToL1MessagePasserAbi } from '../abis.js'
import { contracts } from '../contracts.js'
import type { WithdrawalRequest } from '../types/withdrawal.js'
import type { EstimateInitiateWithdrawalGasErrorType } from './estimateInitiateWithdrawalGas.js'
export type InitiateWithdrawalParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'data'
| 'from'
| 'gas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> & {
/**
* Gas limit for transaction execution on the L2.
* `null` to skip gas estimation & defer calculation to signer.
*/
gas?: bigint | null
/** Withdrawal request. Supplied to the L2ToL1MessagePasser `initiateWithdrawal` method. */
request: WithdrawalRequest
}
export type InitiateWithdrawalReturnType = Hash
export type InitiateWithdrawalErrorType =
| EstimateInitiateWithdrawalGasErrorType
| WriteContractErrorType
| ErrorType
/**
* Initiates a [withdrawal](https://community.optimism.io/docs/protocol/withdrawal-flow/#withdrawal-initiating-transaction) on an L2 to the L1.
*
* Internally performs a contract write to the [`initiateWithdrawal` function](https://github.com/ethereum-optimism/optimism/blob/283f0aa2e3358ced30ff7cbd4028c0c0c3faa140/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol#L73)
* on the [Optimism L2ToL1MessagePasser predeploy contract](https://github.com/ethereum-optimism/optimism/blob/283f0aa2e3358ced30ff7cbd4028c0c0c3faa140/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol).
*
* - Docs: https://viem.sh/op-stack/actions/initiateWithdrawal
*
* @param client - Client to use
* @param parameters - {@link InitiateWithdrawalParameters}
* @returns The L2 transaction hash. {@link InitiateWithdrawalReturnType}
*
* @example
* import { createWalletClient, custom, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { initiateWithdrawal } from 'viem/op-stack'
*
* const client = createWalletClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* })
*
* const hash = await initiateWithdrawal(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* args: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* })
*
* @example
* // Account Hoisting
* import { createWalletClient, http } from 'viem'
* import { privateKeyToAccount } from 'viem/accounts'
* import { base, mainnet } from 'viem/chains'
* import { initiateWithdrawal } from 'viem/op-stack'
*
* const client = createWalletClient({
* account: privateKeyToAccount('0x…'),
* chain: mainnet,
* transport: http(),
* })
*
* const hash = await initiateWithdrawal(client, {
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* })
*/
export async function initiateWithdrawal<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: InitiateWithdrawalParameters<chain, account, chainOverride>,
) {
const {
account,
chain = client.chain,
gas,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
request: { data = '0x', gas: l1Gas, to, value },
} = parameters
return writeContract(client, {
account: account!,
abi: l2ToL1MessagePasserAbi,
address: contracts.l2ToL1MessagePasser.address,
chain,
functionName: 'initiateWithdrawal',
args: [to, l1Gas, data],
gas: gas ?? undefined,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
value,
} satisfies WriteContractParameters as any)
}

142
node_modules/viem/op-stack/actions/proveWithdrawal.ts generated vendored Normal file
View File

@@ -0,0 +1,142 @@
import type { Address } from 'abitype'
import {
type WriteContractErrorType,
type WriteContractParameters,
writeContract,
} from '../../actions/wallet/writeContract.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account, GetAccountParameter } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { Hash, Hex } from '../../types/misc.js'
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
import type { FormattedTransactionRequest } from '../../utils/formatters/transactionRequest.js'
import { portal2Abi } from '../abis.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { EstimateProveWithdrawalGasErrorType } from './estimateProveWithdrawalGas.js'
export type ProveWithdrawalParameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = UnionEvaluate<
UnionOmit<
FormattedTransactionRequest<_derivedChain>,
| 'accessList'
| 'blobs'
| 'data'
| 'from'
| 'gas'
| 'maxFeePerBlobGas'
| 'gasPrice'
| 'to'
| 'type'
| 'value'
>
> &
GetAccountParameter<account, Account | Address> &
GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'portal'> & {
/**
* Gas limit for transaction execution on the L1.
* `null` to skip gas estimation & defer calculation to signer.
*/
gas?: bigint | null | undefined
l2OutputIndex: bigint
outputRootProof: {
version: Hex
stateRoot: Hex
messagePasserStorageRoot: Hex
latestBlockhash: Hex
}
withdrawalProof: readonly Hex[]
withdrawal: {
data: Hex
gasLimit: bigint
nonce: bigint
sender: Address
target: Address
value: bigint
}
}
export type ProveWithdrawalReturnType = Hash
export type ProveWithdrawalErrorType =
| EstimateProveWithdrawalGasErrorType
| WriteContractErrorType
| ErrorType
/**
* Proves a withdrawal that occurred on an L2. Used in the Withdrawal flow.
*
* - Docs: https://viem.sh/op-stack/actions/proveWithdrawal
*
* @param client - Client to use
* @param parameters - {@link ProveWithdrawalParameters}
* @returns The prove transaction hash. {@link ProveWithdrawalReturnType}
*
* @example
* import { createWalletClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { proveWithdrawal } from 'viem/op-stack'
*
* const walletClientL1 = createWalletClient({
* chain: mainnet,
* transport: http(),
* })
*
* const request = await proveWithdrawal(walletClientL1, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* l2OutputIndex: 4529n,
* outputRootProof: { ... },
* targetChain: optimism,
* withdrawalProof: [ ... ],
* withdrawal: { ... },
* })
*/
export async function proveWithdrawal<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: ProveWithdrawalParameters<chain, account, chainOverride>,
): Promise<ProveWithdrawalReturnType> {
const {
account,
chain = client.chain,
gas,
l2OutputIndex,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
outputRootProof,
targetChain,
withdrawalProof,
withdrawal,
} = parameters
const portalAddress = (() => {
if (parameters.portalAddress) return parameters.portalAddress
if (chain) return targetChain!.contracts.portal[chain.id].address
return Object.values(targetChain!.contracts.portal)[0].address
})()
return writeContract(client, {
account: account!,
abi: portal2Abi,
address: portalAddress,
chain,
functionName: 'proveWithdrawalTransaction',
args: [withdrawal, l2OutputIndex, outputRootProof, withdrawalProof],
gas: gas ?? undefined,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
} satisfies WriteContractParameters as any)
}

122
node_modules/viem/op-stack/actions/waitForNextGame.ts generated vendored Normal file
View File

@@ -0,0 +1,122 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import { poll } from '../../utils/poll.js'
import { GameNotFoundError } from '../errors/withdrawal.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import {
type GetGameErrorType,
type GetGameReturnType,
getGame,
} from './getGame.js'
import {
type GetTimeToNextGameErrorType,
type GetTimeToNextGameParameters,
getTimeToNextGame,
} from './getTimeToNextGame.js'
export type WaitForNextGameParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<
_derivedChain,
'portal' | 'disputeGameFactory'
> & {
/**
* Limit of games to extract.
* @default 100
*/
limit?: number | undefined
/**
* The buffer to account for discrepancies between non-deterministic time intervals.
* @default 1.1
*/
intervalBuffer?: GetTimeToNextGameParameters['intervalBuffer'] | undefined
l2BlockNumber: bigint
/**
* Polling frequency (in ms). Defaults to Client's pollingInterval config.
* @default client.pollingInterval
*/
pollingInterval?: number | undefined
}
export type WaitForNextGameReturnType = GetGameReturnType
export type WaitForNextGameErrorType =
| GetGameErrorType
| GetTimeToNextGameErrorType
| ErrorType
/**
* Waits for the next dispute game (after the provided block number) to be submitted.
*
* - Docs: https://viem.sh/op-stack/actions/waitForNextGame
*
* @param client - Client to use
* @param parameters - {@link WaitForNextGameParameters}
* @returns The L2 transaction hash. {@link WaitForNextGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { waitForNextGame } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const l2BlockNumber = await getBlockNumber(publicClientL2)
* await waitForNextGame(publicClientL1, {
* l2BlockNumber,
* targetChain: optimism
* })
*/
export async function waitForNextGame<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: WaitForNextGameParameters<chain, chainOverride>,
): Promise<WaitForNextGameReturnType> {
const { pollingInterval = client.pollingInterval } = parameters
const { seconds } = await getTimeToNextGame(client, parameters)
return new Promise((resolve, reject) => {
poll(
async ({ unpoll }) => {
try {
const game = await getGame(client, {
...parameters,
strategy: 'random',
})
unpoll()
resolve(game)
} catch (e) {
const error = e as GetGameErrorType
if (!(error instanceof GameNotFoundError)) {
unpoll()
reject(e)
}
}
},
{
interval: pollingInterval,
initialWaitTime: async () => seconds * 1000,
},
)
})
}

View File

@@ -0,0 +1,117 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import { ContractFunctionRevertedError } from '../../errors/contract.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import { poll } from '../../utils/poll.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import {
type GetL2OutputErrorType,
type GetL2OutputParameters,
type GetL2OutputReturnType,
getL2Output,
} from './getL2Output.js'
import {
type GetTimeToNextL2OutputErrorType,
type GetTimeToNextL2OutputParameters,
getTimeToNextL2Output,
} from './getTimeToNextL2Output.js'
export type WaitForNextL2OutputParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
GetContractAddressParameter<_derivedChain, 'l2OutputOracle'> & {
/**
* The buffer to account for discrepancies between non-deterministic time intervals.
* @default 1.1
*/
intervalBuffer?:
| GetTimeToNextL2OutputParameters['intervalBuffer']
| undefined
l2BlockNumber: bigint
/**
* Polling frequency (in ms). Defaults to Client's pollingInterval config.
* @default client.pollingInterval
*/
pollingInterval?: number | undefined
}
export type WaitForNextL2OutputReturnType = GetL2OutputReturnType
export type WaitForNextL2OutputErrorType =
| GetL2OutputErrorType
| GetTimeToNextL2OutputErrorType
| ErrorType
/**
* Waits for the next L2 output (after the provided block number) to be submitted.
*
* - Docs: https://viem.sh/op-stack/actions/waitForNextL2Output
*
* @param client - Client to use
* @param parameters - {@link WaitForNextL2OutputParameters}
* @returns The L2 transaction hash. {@link WaitForNextL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { waitForNextL2Output } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const l2BlockNumber = await getBlockNumber(publicClientL2)
* await waitForNextL2Output(publicClientL1, {
* l2BlockNumber,
* targetChain: optimism
* })
*/
export async function waitForNextL2Output<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: WaitForNextL2OutputParameters<chain, chainOverride>,
): Promise<WaitForNextL2OutputReturnType> {
const { pollingInterval = client.pollingInterval } = parameters
const { seconds } = await getTimeToNextL2Output(client, parameters)
return new Promise((resolve, reject) => {
poll(
async ({ unpoll }) => {
try {
const output = await getL2Output(
client,
parameters as GetL2OutputParameters,
)
unpoll()
resolve(output)
} catch (e) {
const error = e as GetL2OutputErrorType
if (!(error.cause instanceof ContractFunctionRevertedError)) {
unpoll()
reject(e)
}
}
},
{
interval: pollingInterval,
initialWaitTime: async () => seconds * 1000,
},
)
})
}

64
node_modules/viem/op-stack/actions/waitToFinalize.ts generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import { wait } from '../../utils/wait.js'
import {
type GetTimeToFinalizeErrorType,
type GetTimeToFinalizeParameters,
getTimeToFinalize,
} from './getTimeToFinalize.js'
export type WaitToFinalizeParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
> = GetTimeToFinalizeParameters<chain, chainOverride>
export type WaitToFinalizeReturnType = void
export type WaitToFinalizeErrorType = GetTimeToFinalizeErrorType | ErrorType
/**
* Waits until the withdrawal transaction can be finalized. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/waitToFinalize
*
* @param client - Client to use
* @param parameters - {@link WaitToFinalizeParameters}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { waitToFinalize } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({
* hash: '0x9a2f4283636ddeb9ac32382961b22c177c9e86dd3b283735c154f897b1a7ff4a',
* })
*
* const [withdrawal] = getWithdrawals(receipt)
*
* await waitToFinalize(publicClientL1, {
* withdrawalHash: withdrawal.withdrawalHash,
* targetChain: optimism
* })
*/
export async function waitToFinalize<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: WaitToFinalizeParameters<chain, chainOverride>,
): Promise<WaitToFinalizeReturnType> {
const { seconds } = await getTimeToFinalize(client, parameters)
await wait(seconds * 1000)
}

157
node_modules/viem/op-stack/actions/waitToProve.ts generated vendored Normal file
View File

@@ -0,0 +1,157 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type {
Chain,
DeriveChain,
GetChainParameter,
} from '../../types/chain.js'
import type { TransactionReceipt } from '../../types/transaction.js'
import type { OneOf } from '../../types/utils.js'
import { ReceiptContainsNoWithdrawalsError } from '../errors/withdrawal.js'
import type { GetContractAddressParameter } from '../types/contract.js'
import type { Withdrawal } from '../types/withdrawal.js'
import {
type GetWithdrawalsErrorType,
getWithdrawals,
} from '../utils/getWithdrawals.js'
import {
type GetPortalVersionParameters,
getPortalVersion,
} from './getPortalVersion.js'
import {
type WaitForNextGameParameters,
type WaitForNextGameReturnType,
waitForNextGame,
} from './waitForNextGame.js'
import {
type WaitForNextL2OutputErrorType,
type WaitForNextL2OutputParameters,
type WaitForNextL2OutputReturnType,
waitForNextL2Output,
} from './waitForNextL2Output.js'
export type WaitToProveParameters<
chain extends Chain | undefined = Chain | undefined,
chainOverride extends Chain | undefined = Chain | undefined,
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
> = GetChainParameter<chain, chainOverride> &
OneOf<
| GetContractAddressParameter<_derivedChain, 'l2OutputOracle'>
| GetContractAddressParameter<
_derivedChain,
'disputeGameFactory' | 'portal'
>
> & {
/**
* Limit of games to extract.
* @default 100
*/
gameLimit?: number | undefined
receipt: TransactionReceipt
/**
* Polling frequency (in ms). Defaults to Client's pollingInterval config.
* @default client.pollingInterval
*/
pollingInterval?: number | undefined
}
export type WaitToProveReturnType = {
game: WaitForNextGameReturnType
output: WaitForNextL2OutputReturnType
withdrawal: Withdrawal
}
export type WaitToProveErrorType =
| GetWithdrawalsErrorType
| WaitForNextL2OutputErrorType
| ErrorType
/**
* Waits until the L2 withdrawal transaction is ready to be proved. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/waitToProve
*
* @param client - Client to use
* @param parameters - {@link WaitToProveParameters}
* @returns The L2 output and withdrawal message. {@link WaitToProveReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { waitToProve } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({ hash: '0x...' })
* await waitToProve(publicClientL1, {
* receipt,
* targetChain: optimism
* })
*/
export async function waitToProve<
chain extends Chain | undefined,
account extends Account | undefined,
chainOverride extends Chain | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: WaitToProveParameters<chain, chainOverride>,
): Promise<WaitToProveReturnType> {
const { gameLimit, receipt } = parameters
const [withdrawal] = getWithdrawals(receipt)
if (!withdrawal)
throw new ReceiptContainsNoWithdrawalsError({
hash: receipt.transactionHash,
})
const portalVersion = await getPortalVersion(
client,
parameters as GetPortalVersionParameters,
)
// Legacy (Portal < v3)
if (portalVersion.major < 3) {
const output = await waitForNextL2Output(client, {
...parameters,
l2BlockNumber: receipt.blockNumber,
} as WaitForNextL2OutputParameters)
return {
game: {
extraData: '0x',
index: output.outputIndex,
l2BlockNumber: output.l2BlockNumber,
metadata: '0x',
rootClaim: output.outputRoot,
timestamp: output.timestamp,
},
output,
withdrawal,
}
}
const game = await waitForNextGame(client, {
...parameters,
limit: gameLimit,
l2BlockNumber: receipt.blockNumber,
} as WaitForNextGameParameters)
return {
game,
output: {
l2BlockNumber: game.l2BlockNumber,
outputIndex: game.index,
outputRoot: game.rootClaim,
timestamp: game.timestamp,
},
withdrawal,
}
}

10
node_modules/viem/op-stack/chainConfig.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import { contracts } from './contracts.js'
import { formatters } from './formatters.js'
import { serializers } from './serializers.js'
export const chainConfig = {
blockTime: 2_000,
contracts,
formatters,
serializers,
} as const

28
node_modules/viem/op-stack/chains.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
// biome-ignore lint/performance/noBarrelFile: entrypoint module
export { ancient8 } from '../chains/definitions/ancient8.js'
export { ancient8Sepolia } from '../chains/definitions/ancient8Sepolia.js'
export { base } from '../chains/definitions/base.js'
export { baseGoerli } from '../chains/definitions/baseGoerli.js'
export { baseSepolia } from '../chains/definitions/baseSepolia.js'
export { blast } from '../chains/definitions/blast.js'
export { fraxtal } from '../chains/definitions/fraxtal.js'
export { fraxtalTestnet } from '../chains/definitions/fraxtalTestnet.js'
export { inkSepolia } from '../chains/definitions/inkSepolia.js'
export { metalL2 } from '../chains/definitions/metalL2.js'
export { optimism } from '../chains/definitions/optimism.js'
export { optimismGoerli } from '../chains/definitions/optimismGoerli.js'
export { optimismSepolia } from '../chains/definitions/optimismSepolia.js'
export { pgn } from '../chains/definitions/pgn.js'
export { pgnTestnet } from '../chains/definitions/pgnTestnet.js'
export { shape } from '../chains/definitions/shape.js'
export { snax } from '../chains/definitions/snax.js'
export { snaxTestnet } from '../chains/definitions/snaxTestnet.js'
export { soneium } from '../chains/definitions/soneium.js'
export { soneiumMinato } from '../chains/definitions/soneiumMinato.js'
export { unichain } from '../chains/definitions/unichain.js'
export { unichainSepolia } from '../chains/definitions/unichainSepolia.js'
export { worldchain } from '../chains/definitions/worldchain.js'
export { worldchainSepolia } from '../chains/definitions/worldchainSepolia.js'
export { zora } from '../chains/definitions/zora.js'
export { zoraSepolia } from '../chains/definitions/zoraSepolia.js'
export { zoraTestnet } from '../chains/definitions/zoraTestnet.js'

18
node_modules/viem/op-stack/contracts.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
import type { Chain } from '../types/chain.js'
/**
* Predeploy contracts for OP Stack.
* @see https://github.com/ethereum-optimism/optimism/blob/develop/specs/predeploys.md
*/
export const contracts = {
gasPriceOracle: { address: '0x420000000000000000000000000000000000000F' },
l1Block: { address: '0x4200000000000000000000000000000000000015' },
l2CrossDomainMessenger: {
address: '0x4200000000000000000000000000000000000007',
},
l2Erc721Bridge: { address: '0x4200000000000000000000000000000000000014' },
l2StandardBridge: { address: '0x4200000000000000000000000000000000000010' },
l2ToL1MessagePasser: {
address: '0x4200000000000000000000000000000000000016',
},
} as const satisfies Chain['contracts']

693
node_modules/viem/op-stack/decorators/publicL1.ts generated vendored Normal file
View File

@@ -0,0 +1,693 @@
import type { Address } from 'abitype'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import {
type BuildInitiateWithdrawalParameters,
type BuildInitiateWithdrawalReturnType,
buildInitiateWithdrawal,
} from '../actions/buildInitiateWithdrawal.js'
import {
type EstimateDepositTransactionGasParameters,
type EstimateDepositTransactionGasReturnType,
estimateDepositTransactionGas,
} from '../actions/estimateDepositTransactionGas.js'
import {
type EstimateFinalizeWithdrawalGasParameters,
type EstimateFinalizeWithdrawalGasReturnType,
estimateFinalizeWithdrawalGas,
} from '../actions/estimateFinalizeWithdrawalGas.js'
import {
type EstimateProveWithdrawalGasParameters,
type EstimateProveWithdrawalGasReturnType,
estimateProveWithdrawalGas,
} from '../actions/estimateProveWithdrawalGas.js'
import {
type GetGameParameters,
type GetGameReturnType,
getGame,
} from '../actions/getGame.js'
import {
type GetGamesParameters,
type GetGamesReturnType,
getGames,
} from '../actions/getGames.js'
import {
type GetL2OutputParameters,
type GetL2OutputReturnType,
getL2Output,
} from '../actions/getL2Output.js'
import {
type GetPortalVersionParameters,
type GetPortalVersionReturnType,
getPortalVersion,
} from '../actions/getPortalVersion.js'
import {
type GetTimeToFinalizeParameters,
type GetTimeToFinalizeReturnType,
getTimeToFinalize,
} from '../actions/getTimeToFinalize.js'
import {
type GetTimeToNextGameParameters,
type GetTimeToNextGameReturnType,
getTimeToNextGame,
} from '../actions/getTimeToNextGame.js'
import {
type GetTimeToNextL2OutputParameters,
type GetTimeToNextL2OutputReturnType,
getTimeToNextL2Output,
} from '../actions/getTimeToNextL2Output.js'
import {
type GetTimeToProveParameters,
type GetTimeToProveReturnType,
getTimeToProve,
} from '../actions/getTimeToProve.js'
import {
type GetWithdrawalStatusParameters,
type GetWithdrawalStatusReturnType,
getWithdrawalStatus,
} from '../actions/getWithdrawalStatus.js'
import {
type WaitForNextGameParameters,
type WaitForNextGameReturnType,
waitForNextGame,
} from '../actions/waitForNextGame.js'
import {
type WaitForNextL2OutputParameters,
type WaitForNextL2OutputReturnType,
waitForNextL2Output,
} from '../actions/waitForNextL2Output.js'
import {
type WaitToFinalizeParameters,
type WaitToFinalizeReturnType,
waitToFinalize,
} from '../actions/waitToFinalize.js'
import {
type WaitToProveParameters,
type WaitToProveReturnType,
waitToProve,
} from '../actions/waitToProve.js'
export type PublicActionsL1<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = {
/**
* Prepares parameters for a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) to be initiated on an L1.
*
* - Docs: https://viem.sh/op-stack/actions/buildInitiateWithdrawal
*
* @param client - Client to use
* @param parameters - {@link BuildInitiateWithdrawalParameters}
* @returns Parameters for `depositTransaction`. {@link DepositTransactionReturnType}
*
* @example
* import { createWalletClient, http, parseEther } from 'viem'
* import { base } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const client = createWalletClient({
* chain: base,
* transport: http(),
* }).extend(publicActionsL1())
*
* const args = await client.buildInitiateWithdrawal({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
buildInitiateWithdrawal: <
chainOverride extends Chain | undefined = undefined,
accountOverride extends Account | Address | undefined = undefined,
>(
parameters: BuildInitiateWithdrawalParameters<
chain,
account,
chainOverride,
accountOverride
>,
) => Promise<BuildInitiateWithdrawalReturnType<account, accountOverride>>
/**
* Estimates gas required to initiate a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) on an L1, which executes a transaction on L2.
*
* - Docs: https://viem.sh/op-stack/actions/estimateDepositTransactionGas
*
* @param client - Client to use
* @param parameters - {@link EstimateDepositTransactionGasParameters}
* @returns The L1 transaction hash. {@link EstimateDepositTransactionGasReturnType}
*
* @example
* import { createPublicClient, custom, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* }).extend(publicActionsL1())
*
* const gas = await client.estimateDepositTransactionGas({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* args: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* targetChain: base,
* })
*/
estimateDepositTransactionGas: <
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateDepositTransactionGasParameters<
chain,
account,
chainOverride
>,
) => Promise<EstimateDepositTransactionGasReturnType>
/**
* Estimates gas required to prove a withdrawal that occurred on an L2.
*
* - Docs: https://viem.sh/op-stack/actions/estimateProveWithdrawalGas
*
* @param client - Client to use
* @param parameters - {@link EstimateProveWithdrawalGasParameters}
* @returns Estimated gas. {@link EstimateProveWithdrawalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
*
* const gas = await client.estimateProveWithdrawalGas({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* l2OutputIndex: 4529n,
* outputRootProof: { ... },
* targetChain: optimism,
* withdrawalProof: [ ... ],
* withdrawal: { ... },
* })
*/
estimateProveWithdrawalGas: <
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateProveWithdrawalGasParameters<
chain,
account,
chainOverride
>,
) => Promise<EstimateProveWithdrawalGasReturnType>
/**
* Estimates gas required to finalize a withdrawal that occurred on an L2.
*
* - Docs: https://viem.sh/op-stack/actions/estimateFinalizeWithdrawalGas
*
* @param client - Client to use
* @param parameters - {@link EstimateFinalizeWithdrawalGasParameters}
* @returns Estimated gas. {@link EstimateFinalizeWithdrawalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
*
* const gas = await client.estimateFinalizeWithdrawalGas({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* targetChain: optimism,
* withdrawal: { ... },
* })
*/
estimateFinalizeWithdrawalGas: <
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateFinalizeWithdrawalGasParameters<
chain,
account,
chainOverride
>,
) => Promise<EstimateFinalizeWithdrawalGasReturnType>
/**
* Retrieves a valid dispute game on an L2 that occurred after a provided L2 block number.
*
* - Docs: https://viem.sh/op-stack/actions/getGame
*
* @param client - Client to use
* @param parameters - {@link GetGameParameters}
* @returns A valid dispute game. {@link GetGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const game = await publicClientL1.getGame({
* l2BlockNumber: 69420n,
* targetChain: optimism
* })
*/
getGame: <chainOverride extends Chain | undefined = undefined>(
parameters: GetGameParameters<chain, chainOverride>,
) => Promise<GetGameReturnType>
/**
* Retrieves dispute games for an L2.
*
* - Docs: https://viem.sh/op-stack/actions/getGame
*
* @param client - Client to use
* @param parameters - {@link GetGameParameters}
* @returns Dispute games. {@link GetGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const games = await publicClientL1.getGames({
* targetChain: optimism
* })
*/
getGames: <chainOverride extends Chain | undefined = undefined>(
parameters: GetGamesParameters<chain, chainOverride>,
) => Promise<GetGamesReturnType>
/**
* Retrieves the first L2 output proposal that occurred after a provided block number. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getL2Output
*
* @param client - Client to use
* @param parameters - {@link GetL2OutputParameters}
* @returns The L2 output. {@link GetL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
*
* const output = await publicClientL1.getL2Output({
* l2BlockNumber: 69420n,
* targetChain: optimism
* })
*/
getL2Output: <chainOverride extends Chain | undefined = undefined>(
parameters: GetL2OutputParameters<chain, chainOverride>,
) => Promise<GetL2OutputReturnType>
/**
* Retrieves the current version of the Portal contract.
*
* - Docs: https://viem.sh/op-stack/actions/getPortalVersion
*
* @param client - Client to use
* @param parameters - {@link GetPortalVersionParameters}
* @returns The version object.
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const version = await publicClientL1.getPortalVersion({
* targetChain: optimism,
* })
*
* if (version.major > 3)
* console.log('Fault proofs are enabled on this version of optimism')
* console.log('Fault proofs are not enabled on this version of optimism')
*/
getPortalVersion: <chainOverride extends Chain | undefined = undefined>(
parameters: GetPortalVersionParameters<chain, chainOverride>,
) => Promise<GetPortalVersionReturnType>
/**
* Returns the time until the withdrawal transaction can be finalized. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToFinalize
*
* @param client - Client to use
* @param parameters - {@link GetTimeToFinalizeParameters}
* @returns Time until finalize. {@link GetTimeToFinalizeReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({
* hash: '0x9a2f4283636ddeb9ac32382961b22c177c9e86dd3b283735c154f897b1a7ff4a',
* })
*
* const [withdrawal] = getWithdrawals(receipt)
*
* const { seconds } = await publicClientL1.getTimeToFinalize({
* withdrawalHash: withdrawal.withdrawalHash,
* targetChain: optimism
* })
*/
getTimeToFinalize: <chainOverride extends Chain | undefined = undefined>(
parameters: GetTimeToFinalizeParameters<chain, chainOverride>,
) => Promise<GetTimeToFinalizeReturnType>
/**
* Returns the time until the next L2 dispute game (after the provided block number) is submitted.
* Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToNextGame
*
* @param client - Client to use
* @param parameters - {@link GetTimeToNextGameParameters}
* @returns The L2 transaction hash. {@link GetTimeToNextGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* const { seconds } = await publicClientL1.getTimeToNextGame({
* l2BlockNumber: 113405763n,
* targetChain: optimism
* })
*/
getTimeToNextGame: <chainOverride extends Chain | undefined = undefined>(
parameters: GetTimeToNextGameParameters<chain, chainOverride>,
) => Promise<GetTimeToNextGameReturnType>
/**
* Returns the time until the next L2 output (after a provided block number) is submitted. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToNextL2Output
*
* @param client - Client to use
* @param parameters - {@link GetTimeToNextL2OutputParameters}
* @returns The L2 transaction hash. {@link GetTimeToNextL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const l2BlockNumber = await publicClientL2.getBlockNumber()
* const { seconds } = await publicClientL1.getTimeToNextL2Output({
* l2BlockNumber,
* targetChain: optimism
* })
*/
getTimeToNextL2Output: <chainOverride extends Chain | undefined = undefined>(
parameters: GetTimeToNextL2OutputParameters<chain, chainOverride>,
) => Promise<GetTimeToNextL2OutputReturnType>
/**
* Returns the time until the withdrawal transaction can be finalized. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getTimeToFinalize
*
* @param client - Client to use
* @param parameters - {@link GetTimeToFinalizeParameters}
* @returns Time until finalize. {@link GetTimeToFinalizeReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({
* hash: '0x9a2f4283636ddeb9ac32382961b22c177c9e86dd3b283735c154f897b1a7ff4a',
* })
*
* const [withdrawal] = getWithdrawals(receipt)
*
* const { seconds } = await publicClientL1.getTimeToFinalize({
* withdrawalHash: withdrawal.withdrawalHash,
* targetChain: optimism
* })
*/
getTimeToProve: <chainOverride extends Chain | undefined = undefined>(
parameters: GetTimeToProveParameters<chain, chainOverride>,
) => Promise<GetTimeToProveReturnType>
/**
* Returns the current status of a withdrawal. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/getWithdrawalStatus
*
* @param client - Client to use
* @param parameters - {@link GetWithdrawalStatusParameters}
* @returns Status of the withdrawal. {@link GetWithdrawalStatusReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({ hash: '0x...' })
* const status = await publicClientL1.getWithdrawalStatus({
* receipt,
* targetChain: optimism
* })
*/
getWithdrawalStatus: <chainOverride extends Chain | undefined = undefined>(
parameters: GetWithdrawalStatusParameters<chain, chainOverride>,
) => Promise<GetWithdrawalStatusReturnType>
/**
* Waits for the next L2 output (after the provided block number) to be submitted.
*
* - Docs: https://viem.sh/op-stack/actions/waitForNextGame
*
* @param client - Client to use
* @param parameters - {@link WaitForNextGameParameters}
* @returns The L2 transaction hash. {@link WaitForNextGameReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { optimism } from 'viem/chains'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* })
*
* await publicClientL1.waitForNextGame({
* l2BlockNumber: 69420n,
* targetChain: optimism
* })
*/
waitForNextGame: <chainOverride extends Chain | undefined = undefined>(
parameters: WaitForNextGameParameters<chain, chainOverride>,
) => Promise<WaitForNextGameReturnType>
/**
* Waits for the next L2 output (after the provided block number) to be submitted.
*
* - Docs: https://viem.sh/op-stack/actions/waitForNextL2Output
*
* @param client - Client to use
* @param parameters - {@link WaitForNextL2OutputParameters}
* @returns The L2 transaction hash. {@link WaitForNextL2OutputReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const l2BlockNumber = await getBlockNumber(publicClientL2)
* await waitForNextL2Output(publicClientL1, {
* l2BlockNumber,
* targetChain: optimism
* })
*/
waitForNextL2Output: <chainOverride extends Chain | undefined = undefined>(
parameters: WaitForNextL2OutputParameters<chain, chainOverride>,
) => Promise<WaitForNextL2OutputReturnType>
/**
* Waits until the withdrawal transaction can be finalized. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/waitToFinalize
*
* @param client - Client to use
* @param parameters - {@link WaitToFinalizeParameters}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1)
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({
* hash: '0x9a2f4283636ddeb9ac32382961b22c177c9e86dd3b283735c154f897b1a7ff4a',
* })
*
* const [withdrawal] = getWithdrawals(receipt)
*
* await publicClientL1.waitToFinalize({
* withdrawalHash: withdrawal.withdrawalHash,
* targetChain: optimism
* })
*/
waitToFinalize: <chainOverride extends Chain | undefined = undefined>(
parameters: WaitToFinalizeParameters<chain, chainOverride>,
) => Promise<WaitToFinalizeReturnType>
/**
* Waits until the L2 withdrawal transaction is provable. Used for the [Withdrawal](/op-stack/guides/withdrawals) flow.
*
* - Docs: https://viem.sh/op-stack/actions/waitToProve
*
* @param client - Client to use
* @param parameters - {@link WaitToProveParameters}
* @returns The L2 output and withdrawal message. {@link WaitToProveReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { getBlockNumber } from 'viem/actions'
* import { mainnet, optimism } from 'viem/chains'
* import { publicActionsL1 } from 'viem/op-stack'
*
* const publicClientL1 = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1)
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* })
*
* const receipt = await publicClientL2.getTransactionReceipt({ hash: '0x...' })
* await publicClientL1.waitToProve({
* receipt,
* targetChain: optimism
* })
*/
waitToProve: <chainOverride extends Chain | undefined = undefined>(
parameters: WaitToProveParameters<chain, chainOverride>,
) => Promise<WaitToProveReturnType>
}
/**
* A suite of Public Actions for suited for development with Layer 2 (OP Stack) chains.
*
* - Docs: https://viem.sh/op-stack/client
*
* @example
* import { publicActionsL1 } from 'viem/op-stack'
* import { mainnet } from 'viem/chains'
* import { buildDepositTransaction } from 'viem/wallet'
*
* export const opStackPublicClientL1 = createWalletClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL1())
*/
export function publicActionsL1() {
return <
transport extends Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: Client<transport, chain, account>,
): PublicActionsL1<chain, account> => {
return {
buildInitiateWithdrawal: (args) => buildInitiateWithdrawal(client, args),
estimateDepositTransactionGas: (args) =>
estimateDepositTransactionGas(client, args),
estimateFinalizeWithdrawalGas: (args) =>
estimateFinalizeWithdrawalGas(client, args),
estimateProveWithdrawalGas: (args) =>
estimateProveWithdrawalGas(client, args),
getGame: (args) => getGame(client, args),
getGames: (args) => getGames(client, args),
getL2Output: (args) => getL2Output(client, args),
getPortalVersion: (args) => getPortalVersion(client, args),
getTimeToFinalize: (args) => getTimeToFinalize(client, args),
getTimeToNextGame: (args) => getTimeToNextGame(client, args),
getTimeToNextL2Output: (args) => getTimeToNextL2Output(client, args),
getTimeToProve: (args) => getTimeToProve(client, args),
getWithdrawalStatus: (args) => getWithdrawalStatus(client, args),
waitForNextGame: (args) => waitForNextGame(client, args),
waitForNextL2Output: (args) => waitForNextL2Output(client, args),
waitToFinalize: (args) => waitToFinalize(client, args),
waitToProve: (args) => waitToProve(client, args),
}
}
}

550
node_modules/viem/op-stack/decorators/publicL2.ts generated vendored Normal file
View File

@@ -0,0 +1,550 @@
import type { Abi, Address } from 'abitype'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
} from '../../types/contract.js'
import {
type BuildDepositTransactionParameters,
type BuildDepositTransactionReturnType,
buildDepositTransaction,
} from '../actions/buildDepositTransaction.js'
import {
type BuildProveWithdrawalParameters,
type BuildProveWithdrawalReturnType,
buildProveWithdrawal,
} from '../actions/buildProveWithdrawal.js'
import {
type EstimateContractL1FeeParameters,
type EstimateContractL1FeeReturnType,
estimateContractL1Fee,
} from '../actions/estimateContractL1Fee.js'
import {
type EstimateContractL1GasParameters,
type EstimateContractL1GasReturnType,
estimateContractL1Gas,
} from '../actions/estimateContractL1Gas.js'
import {
type EstimateContractTotalFeeParameters,
type EstimateContractTotalFeeReturnType,
estimateContractTotalFee,
} from '../actions/estimateContractTotalFee.js'
import {
type EstimateContractTotalGasParameters,
type EstimateContractTotalGasReturnType,
estimateContractTotalGas,
} from '../actions/estimateContractTotalGas.js'
import {
type EstimateInitiateWithdrawalGasParameters,
type EstimateInitiateWithdrawalGasReturnType,
estimateInitiateWithdrawalGas,
} from '../actions/estimateInitiateWithdrawalGas.js'
import {
type EstimateL1FeeParameters,
type EstimateL1FeeReturnType,
estimateL1Fee,
} from '../actions/estimateL1Fee.js'
import {
type EstimateL1GasParameters,
type EstimateL1GasReturnType,
estimateL1Gas,
} from '../actions/estimateL1Gas.js'
import {
type EstimateOperatorFeeParameters,
type EstimateOperatorFeeReturnType,
estimateOperatorFee,
} from '../actions/estimateOperatorFee.js'
import {
type EstimateTotalFeeParameters,
type EstimateTotalFeeReturnType,
estimateTotalFee,
} from '../actions/estimateTotalFee.js'
import {
type EstimateTotalGasParameters,
type EstimateTotalGasReturnType,
estimateTotalGas,
} from '../actions/estimateTotalGas.js'
import {
type GetL1BaseFeeParameters,
type GetL1BaseFeeReturnType,
getL1BaseFee,
} from '../actions/getL1BaseFee.js'
export type PublicActionsL2<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = {
/**
* Prepares parameters for a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) to be initiated on an L1.
*
* - Docs: https://viem.sh/op-stack/actions/buildDepositTransaction
*
* @param client - Client to use
* @param parameters - {@link BuildDepositTransactionParameters}
* @returns Parameters for `depositTransaction`. {@link DepositTransactionReturnType}
*
* @example
* import { createWalletClient, http, parseEther } from 'viem'
* import { base } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createWalletClient({
* chain: base,
* transport: http(),
* }).extend(publicActionsL2())
*
* const args = await client.buildDepositTransaction({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
buildDepositTransaction: <
chainOverride extends Chain | undefined = undefined,
accountOverride extends Account | Address | undefined = undefined,
>(
parameters: BuildDepositTransactionParameters<
chain,
account,
chainOverride,
accountOverride
>,
) => Promise<BuildDepositTransactionReturnType<account, accountOverride>>
/**
* Builds the transaction that proves a withdrawal was initiated on an L2. Used in the Withdrawal flow.
*
* - Docs: https://viem.sh/op-stack/actions/buildProveWithdrawal
*
* @param client - Client to use
* @param parameters - {@link BuildProveWithdrawalParameters}
* @returns The prove withdraw transaction request. {@link BuildProveWithdrawalReturnType}
*
* @example
* import { createPublicClient, http } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const publicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const args = await publicClientL2.buildProveWithdrawal({
* output: { ... },
* withdrawal: { ... },
* })
*/
buildProveWithdrawal: <
chainOverride extends Chain | undefined = undefined,
accountOverride extends Account | Address | undefined = undefined,
>(
parameters: BuildProveWithdrawalParameters<
chain,
account,
chainOverride,
accountOverride
>,
) => Promise<
BuildProveWithdrawalReturnType<
chain,
account,
chainOverride,
accountOverride
>
>
/**
* Estimates the L1 data fee required to execute an L2 contract write.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractL1FeeParameters}
* @returns The gas estimate (in wei). {@link EstimateContractL1FeeReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const l1Fee = await client.estimateContractL1Fee({
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
estimateContractL1Fee: <
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateContractL1FeeParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
) => Promise<EstimateContractL1FeeReturnType>
/**
* Estimates the L1 data gas required to successfully execute a contract write function call.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractL1GasParameters}
* @returns The gas estimate (in wei). {@link EstimateContractL1GasReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const l1Gas = await client.estimateContractL1Gas({
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
estimateContractL1Gas: <
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateContractL1GasParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
) => Promise<EstimateContractL1GasReturnType>
/**
* Estimates the L1 + L2 fee to execute an L2 contract write.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractTotalFeeParameters}
* @returns The gas estimate (in wei). {@link EstimateContractTotalFeeReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const totalFee = await client.estimateContractTotalFee({
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
estimateContractTotalFee: <
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateContractTotalFeeParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
) => Promise<EstimateContractTotalFeeReturnType>
/**
* Estimates the L1 data gas + L2 gas required to successfully execute a contract write function call.
*
* @param client - Client to use
* @param parameters - {@link EstimateContractTotalGasParameters}
* @returns The gas estimate (in wei). {@link EstimateContractTotalGasReturnType}
*
* @example
* import { createPublicClient, http, parseAbi } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const totalGas = await client.estimateContractTotalGas({
* address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
* abi: parseAbi(['function mint() public']),
* functionName: 'mint',
* account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
* })
*/
estimateContractTotalGas: <
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateContractTotalGasParameters<
abi,
functionName,
args,
chain,
account,
chainOverride
>,
) => Promise<EstimateContractTotalGasReturnType>
/**
* Estimates gas required to initiate a [withdrawal](https://community.optimism.io/docs/protocol/withdrawal-flow/#withdrawal-initiating-transaction) on an L2 to the L1.
*
* - Docs: https://viem.sh/op-stack/actions/estimateInitiateWithdrawalGas
*
* @param client - Client to use
* @param parameters - {@link EstimateInitiateWithdrawalGasParameters}
* @returns The gas required. {@link EstimateInitiateWithdrawalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: mainnet,
* transport: http(),
* }).extend(publicActionsL2())
*
* const hash = await client.estimateInitiateWithdrawalGas({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* })
*/
estimateInitiateWithdrawalGas: <
chainOverride extends Chain | undefined = undefined,
>(
parameters: EstimateInitiateWithdrawalGasParameters<
chain,
account,
chainOverride
>,
) => Promise<EstimateInitiateWithdrawalGasReturnType>
/**
* Estimates the L1 data fee required to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateL1FeeParameters}
* @returns The fee (in wei). {@link EstimateL1FeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const l1Fee = await client.estimateL1Fee({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
estimateL1Fee: <chainOverride extends Chain | undefined = undefined>(
parameters: EstimateL1FeeParameters<chain, account, chainOverride>,
) => Promise<EstimateL1FeeReturnType>
/**
* Get the L1 basefee
*
* @param client - Client to use
* @param parameters - {@link GetL1BaseFeeParameters}
* @returns The fee (in wei). {@link GetL1BaseFeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const l1BaseFee = await client.getL1BaseFee()
*/
getL1BaseFee: <chainOverride extends Chain | undefined = undefined>(
parameters?: GetL1BaseFeeParameters<chain, chainOverride> | undefined,
) => Promise<GetL1BaseFeeReturnType>
/**
* Estimates the amount of L1 data gas required to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateL1GasParameters}
* @returns The gas estimate. {@link EstimateL1GasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const l1Gas = await client.estimateL1Gas({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
estimateL1Gas: <chainOverride extends Chain | undefined = undefined>(
parameters: EstimateL1GasParameters<chain, account, chainOverride>,
) => Promise<EstimateL1GasReturnType>
/**
* Estimates the operator fee required to execute an L2 transaction.
*
* Returns 0 for pre-Isthmus chains or when operator fee functions don't exist.
*
* @param client - Client to use
* @param parameters - {@link EstimateOperatorFeeParameters}
* @returns The operator fee (in wei). {@link EstimateOperatorFeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const operatorFee = await client.estimateOperatorFee({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
estimateOperatorFee: <chainOverride extends Chain | undefined = undefined>(
parameters: EstimateOperatorFeeParameters<chain, account, chainOverride>,
) => Promise<EstimateOperatorFeeReturnType>
/**
* Estimates the L1 data fee + L2 fee to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateTotalFeeParameters}
* @returns The gas estimate. {@link EstimateTotalFeeReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const totalFee = await client.estimateTotalFee({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
estimateTotalFee: <chainOverride extends Chain | undefined = undefined>(
parameters: EstimateTotalFeeParameters<chain, account, chainOverride>,
) => Promise<EstimateTotalFeeReturnType>
/**
* Estimates the total amount of combined L1 data gas + L2 gas required to execute an L2 transaction.
*
* @param client - Client to use
* @param parameters - {@link EstimateTotalGasParameters}
* @returns The gas estimate. {@link EstimateTotalGasReturnType}
*
* @example
* import { createPublicClient, http, parseEther } from 'viem'
* import { optimism } from 'viem/chains'
* import { publicActionsL2 } from 'viem/op-stack'
*
* const client = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*
* const totalGas = await client.estimateTotalGas({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* })
*/
estimateTotalGas: <chainOverride extends Chain | undefined = undefined>(
parameters: EstimateTotalGasParameters<chain, account, chainOverride>,
) => Promise<EstimateTotalGasReturnType>
}
/**
* A suite of Public Actions for suited for development with Layer 2 (OP Stack) chains.
*
* - Docs: https://viem.sh/op-stack/client
*
* @example
* import { publicActionsL2 } from 'viem/op-stack'
* import { optimism } from 'viem/chains'
* import { buildDepositTransaction } from 'viem/wallet'
*
* export const opStackPublicClientL2 = createPublicClient({
* chain: optimism,
* transport: http(),
* }).extend(publicActionsL2())
*/
export function publicActionsL2() {
return <
transport extends Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: Client<transport, chain, account>,
): PublicActionsL2<chain, account> => {
return {
buildDepositTransaction: (args) => buildDepositTransaction(client, args),
buildProveWithdrawal: (args) => buildProveWithdrawal(client, args),
estimateContractL1Fee: (args) => estimateContractL1Fee(client, args),
estimateContractL1Gas: (args) => estimateContractL1Gas(client, args),
estimateContractTotalFee: (args) =>
estimateContractTotalFee(client, args),
estimateContractTotalGas: (args) =>
estimateContractTotalGas(client, args),
estimateInitiateWithdrawalGas: (args) =>
estimateInitiateWithdrawalGas(client, args),
estimateL1Fee: (args) => estimateL1Fee(client, args),
getL1BaseFee: (args) => getL1BaseFee(client, args),
estimateL1Gas: (args) => estimateL1Gas(client, args),
estimateOperatorFee: (args) => estimateOperatorFee(client, args),
estimateTotalFee: (args) => estimateTotalFee(client, args),
estimateTotalGas: (args) => estimateTotalGas(client, args),
}
}
}

172
node_modules/viem/op-stack/decorators/walletL1.ts generated vendored Normal file
View File

@@ -0,0 +1,172 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import {
type DepositTransactionParameters,
type DepositTransactionReturnType,
depositTransaction,
} from '../actions/depositTransaction.js'
import {
type FinalizeWithdrawalParameters,
type FinalizeWithdrawalReturnType,
finalizeWithdrawal,
} from '../actions/finalizeWithdrawal.js'
import {
type ProveWithdrawalParameters,
type ProveWithdrawalReturnType,
proveWithdrawal,
} from '../actions/proveWithdrawal.js'
export type WalletActionsL1<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = {
/**
* Initiates a [deposit transaction](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md) on an L1, which executes a transaction on L2.
*
* Internally performs a contract write to the [`depositTransaction` function](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L1/OptimismPortal.sol#L378)
* on the [Optimism Portal contract](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L1/OptimismPortal.sol).
*
* - Docs: https://viem.sh/op-stack/actions/depositTransaction
*
* @param client - Client to use
* @param parameters - {@link DepositTransactionParameters}
* @returns The L1 transaction hash. {@link DepositTransactionReturnType}
*
* @example
* import { createWalletClient, custom, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { walletActionsL1 } from 'viem/op-stack'
*
* const client = createWalletClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* }).extend(walletActionsL1())
*
* const hash = await client.depositTransaction({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* targetChain: base,
* })
*
* @example
* // Account Hoisting
* import { createWalletClient, http } from 'viem'
* import { privateKeyToAccount } from 'viem/accounts'
* import { base, mainnet } from 'viem/chains'
* import { walletActionsL1 } from 'viem/op-stack'
*
* const client = createWalletClient({
* account: privateKeyToAccount('0x…'),
* chain: mainnet,
* transport: http(),
* }).extend(walletActionsL1())
*
* const hash = await client.depositTransaction({
* request: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* targetChain: base,
* })
*/
depositTransaction: <chainOverride extends Chain | undefined = undefined>(
parameters: DepositTransactionParameters<chain, account, chainOverride>,
) => Promise<DepositTransactionReturnType>
/**
* Finalizes a withdrawal that occurred on an L2. Used in the Withdrawal flow.
*
* - Docs: https://viem.sh/op-stack/actions/finalizeWithdrawal
*
* @param client - Client to use
* @param parameters - {@link FinalizeWithdrawalParameters}
* @returns The finalize transaction hash. {@link FinalizeWithdrawalReturnType}
*
* @example
* import { createWalletClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { walletActionsL1 } from 'viem/op-stack'
*
* const walletClientL1 = createWalletClient({
* chain: mainnet,
* transport: http(),
* }).extend(walletActionsL1)
*
* const hash = await walletClientL1.finalizeWithdrawal({
* targetChain: optimism,
* withdrawal: { ... },
* })
*/
finalizeWithdrawal: <chainOverride extends Chain | undefined = undefined>(
parameters: FinalizeWithdrawalParameters<chain, account, chainOverride>,
) => Promise<FinalizeWithdrawalReturnType>
/**
* Proves a withdrawal that occurred on an L2. Used in the Withdrawal flow.
*
* - Docs: https://viem.sh/op-stack/actions/proveWithdrawal
*
* @param client - Client to use
* @param parameters - {@link ProveWithdrawalParameters}
* @returns The prove transaction hash. {@link ProveWithdrawalReturnType}
*
* @example
* import { createWalletClient, http } from 'viem'
* import { mainnet, optimism } from 'viem/chains'
* import { walletActionsL1 } from 'viem/op-stack'
*
* const walletClientL1 = createWalletClient({
* chain: mainnet,
* transport: http(),
* }).extend(walletActionsL1())
*
* const hash = await walletClientL1.proveWithdrawal({
* l2OutputIndex: 4529n,
* outputRootProof: { ... },
* targetChain: optimism,
* withdrawalProof: [ ... ],
* withdrawalTransaction: { ... },
* })
*/
proveWithdrawal: <chainOverride extends Chain | undefined = undefined>(
parameters: ProveWithdrawalParameters<chain, account, chainOverride>,
) => Promise<ProveWithdrawalReturnType>
}
/**
* A suite of Wallet Actions for suited for development with Layer 2 (OP Stack) chains.
*
* - Docs: https://viem.sh/op-stack/client
*
* @example
* import { createPublicClient, createWalletClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
* import { walletActionsL1 } from 'viem/op-stack'
*
* const walletClient = createWalletClient({
* chain: mainnet,
* transport: http(),
* }).extend(walletActionsL1())
*
* const hash = await walletClient.depositTransaction({...})
*/
export function walletActionsL1() {
return <
transport extends Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: Client<transport, chain, account>,
): WalletActionsL1<chain, account> => {
return {
depositTransaction: (args) => depositTransaction(client, args),
finalizeWithdrawal: (args) => finalizeWithdrawal(client, args),
proveWithdrawal: (args) => proveWithdrawal(client, args),
}
}
}

101
node_modules/viem/op-stack/decorators/walletL2.ts generated vendored Normal file
View File

@@ -0,0 +1,101 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { Account } from '../../types/account.js'
import type { Chain } from '../../types/chain.js'
import {
type InitiateWithdrawalParameters,
type InitiateWithdrawalReturnType,
initiateWithdrawal,
} from '../actions/initiateWithdrawal.js'
export type WalletActionsL2<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = {
/**
* Initiates a [withdrawal](https://community.optimism.io/docs/protocol/withdrawal-flow/#withdrawal-initiating-transaction) on an L2 to the L1.
*
* Internally performs a contract write to the [`initiateWithdrawal` function](https://github.com/ethereum-optimism/optimism/blob/283f0aa2e3358ced30ff7cbd4028c0c0c3faa140/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol#L73)
* on the [Optimism L2ToL1MessagePasser predeploy contract](https://github.com/ethereum-optimism/optimism/blob/283f0aa2e3358ced30ff7cbd4028c0c0c3faa140/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol).
*
* - Docs: https://viem.sh/op-stack/actions/initiateWithdrawal
*
* @param client - Client to use
* @param parameters - {@link InitiateWithdrawalParameters}
* @returns The L2 transaction hash. {@link InitiateWithdrawalReturnType}
*
* @example
* import { createWalletClient, custom, parseEther } from 'viem'
* import { base, mainnet } from 'viem/chains'
* import { walletActionsL2 } from 'viem/op-stack'
*
* const client = createWalletClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* }).extend(walletActionsL2())
*
* const hash = await client.initiateWithdrawal({
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* args: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* })
*
* @example
* // Account Hoisting
* import { createWalletClient, http } from 'viem'
* import { privateKeyToAccount } from 'viem/accounts'
* import { base, mainnet } from 'viem/chains'
* import { walletActionsL2 } from 'viem/op-stack'
*
* const client = createWalletClient({
* account: privateKeyToAccount('0x…'),
* chain: mainnet,
* transport: http(),
* }).extend(walletActionsL2())
*
* const hash = await client.initiateWithdrawal({
* args: {
* gas: 21_000n,
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: parseEther('1'),
* },
* })
*/
initiateWithdrawal: <chainOverride extends Chain | undefined = undefined>(
parameters: InitiateWithdrawalParameters<chain, account, chainOverride>,
) => Promise<InitiateWithdrawalReturnType>
}
/**
* A suite of Wallet Actions for suited for development with Layer 2 (OP Stack) chains.
*
* - Docs: https://viem.sh/op-stack/client
*
* @example
* import { createPublicClient, createWalletClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
* import { walletActionsL1 } from 'viem/op-stack'
*
* const walletClient = createWalletClient({
* chain: mainnet,
* transport: http(),
* }).extend(walletActionsL1())
*
* const hash = await walletClient.depositTransaction({...})
*/
export function walletActionsL2() {
return <
transport extends Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: Client<transport, chain, account>,
): WalletActionsL2<chain, account> => {
return {
initiateWithdrawal: (args) => initiateWithdrawal(client, args),
}
}
}

24
node_modules/viem/op-stack/errors/withdrawal.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { BaseError } from '../../errors/base.js'
import type { Hex } from '../../types/misc.js'
export type GameNotFoundErrorType = GameNotFoundError & {
name: 'GameNotFoundError'
}
export class GameNotFoundError extends BaseError {
constructor() {
super('Dispute game not found.', { name: 'GameNotFoundError' })
}
}
export type ReceiptContainsNoWithdrawalsErrorType =
ReceiptContainsNoWithdrawalsError & {
name: 'ReceiptContainsNoWithdrawalsError'
}
export class ReceiptContainsNoWithdrawalsError extends BaseError {
constructor({ hash }: { hash: Hex }) {
super(
`The provided transaction receipt with hash "${hash}" contains no withdrawals.`,
{ name: 'ReceiptContainsNoWithdrawalsError' },
)
}
}

64
node_modules/viem/op-stack/formatters.ts generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import type { ChainFormatters } from '../types/chain.js'
import type { RpcTransaction } from '../types/rpc.js'
import { hexToBigInt } from '../utils/encoding/fromHex.js'
import { defineBlock } from '../utils/formatters/block.js'
import {
defineTransaction,
formatTransaction,
} from '../utils/formatters/transaction.js'
import { defineTransactionReceipt } from '../utils/formatters/transactionReceipt.js'
import type { OpStackBlock, OpStackRpcBlock } from './types/block.js'
import type {
OpStackRpcTransaction,
OpStackRpcTransactionReceipt,
OpStackTransaction,
OpStackTransactionReceipt,
} from './types/transaction.js'
export const formatters = {
block: /*#__PURE__*/ defineBlock({
format(args: OpStackRpcBlock): OpStackBlock {
const transactions = args.transactions?.map((transaction) => {
if (typeof transaction === 'string') return transaction
const formatted = formatTransaction(
transaction as RpcTransaction,
) as OpStackTransaction
if (formatted.typeHex === '0x7e') {
formatted.isSystemTx = transaction.isSystemTx
formatted.mint = transaction.mint
? hexToBigInt(transaction.mint)
: undefined
formatted.sourceHash = transaction.sourceHash
formatted.type = 'deposit'
}
return formatted
})
return {
transactions,
stateRoot: args.stateRoot,
} as OpStackBlock
},
}),
transaction: /*#__PURE__*/ defineTransaction({
format(args: OpStackRpcTransaction): OpStackTransaction {
const transaction = {} as OpStackTransaction
if (args.type === '0x7e') {
transaction.isSystemTx = args.isSystemTx
transaction.mint = args.mint ? hexToBigInt(args.mint) : undefined
transaction.sourceHash = args.sourceHash
transaction.type = 'deposit'
}
return transaction
},
}),
transactionReceipt: /*#__PURE__*/ defineTransactionReceipt({
format(args: OpStackRpcTransactionReceipt): OpStackTransactionReceipt {
return {
l1GasPrice: args.l1GasPrice ? hexToBigInt(args.l1GasPrice) : null,
l1GasUsed: args.l1GasUsed ? hexToBigInt(args.l1GasUsed) : null,
l1Fee: args.l1Fee ? hexToBigInt(args.l1Fee) : null,
l1FeeScalar: args.l1FeeScalar ? Number(args.l1FeeScalar) : null,
} as OpStackTransactionReceipt
},
}),
} as const satisfies ChainFormatters

304
node_modules/viem/op-stack/index.ts generated vendored Normal file
View File

@@ -0,0 +1,304 @@
// biome-ignore lint/performance/noBarrelFile: entrypoint module
export {
type BuildDepositTransactionErrorType,
type BuildDepositTransactionParameters,
type BuildDepositTransactionReturnType,
buildDepositTransaction,
} from './actions/buildDepositTransaction.js'
export {
type BuildInitiateWithdrawalErrorType,
type BuildInitiateWithdrawalParameters,
type BuildInitiateWithdrawalReturnType,
buildInitiateWithdrawal,
} from './actions/buildInitiateWithdrawal.js'
export {
type BuildProveWithdrawalErrorType,
type BuildProveWithdrawalParameters,
type BuildProveWithdrawalReturnType,
buildProveWithdrawal,
} from './actions/buildProveWithdrawal.js'
export {
type DepositTransactionErrorType,
type DepositTransactionParameters,
type DepositTransactionReturnType,
depositTransaction,
} from './actions/depositTransaction.js'
export {
type EstimateContractL1FeeErrorType,
type EstimateContractL1FeeParameters,
type EstimateContractL1FeeReturnType,
estimateContractL1Fee,
} from './actions/estimateContractL1Fee.js'
export {
type EstimateContractL1GasErrorType,
type EstimateContractL1GasParameters,
type EstimateContractL1GasReturnType,
estimateContractL1Gas,
} from './actions/estimateContractL1Gas.js'
export {
type EstimateContractTotalFeeErrorType,
type EstimateContractTotalFeeParameters,
type EstimateContractTotalFeeReturnType,
estimateContractTotalFee,
} from './actions/estimateContractTotalFee.js'
export {
type EstimateContractTotalGasErrorType,
type EstimateContractTotalGasParameters,
type EstimateContractTotalGasReturnType,
estimateContractTotalGas,
} from './actions/estimateContractTotalGas.js'
export {
type EstimateDepositTransactionGasErrorType,
type EstimateDepositTransactionGasParameters,
type EstimateDepositTransactionGasReturnType,
estimateDepositTransactionGas,
} from './actions/estimateDepositTransactionGas.js'
export {
type EstimateFinalizeWithdrawalGasErrorType,
type EstimateFinalizeWithdrawalGasParameters,
type EstimateFinalizeWithdrawalGasReturnType,
estimateFinalizeWithdrawalGas,
} from './actions/estimateFinalizeWithdrawalGas.js'
export {
type EstimateInitiateWithdrawalGasErrorType,
type EstimateInitiateWithdrawalGasParameters,
type EstimateInitiateWithdrawalGasReturnType,
estimateInitiateWithdrawalGas,
} from './actions/estimateInitiateWithdrawalGas.js'
export {
type EstimateL1FeeErrorType,
type EstimateL1FeeParameters,
type EstimateL1FeeReturnType,
estimateL1Fee,
} from './actions/estimateL1Fee.js'
export {
type EstimateL1GasErrorType,
type EstimateL1GasParameters,
type EstimateL1GasReturnType,
estimateL1Gas,
} from './actions/estimateL1Gas.js'
export {
type EstimateOperatorFeeErrorType,
type EstimateOperatorFeeParameters,
type EstimateOperatorFeeReturnType,
estimateOperatorFee,
} from './actions/estimateOperatorFee.js'
export {
type EstimateProveWithdrawalGasErrorType,
type EstimateProveWithdrawalGasParameters,
type EstimateProveWithdrawalGasReturnType,
estimateProveWithdrawalGas,
} from './actions/estimateProveWithdrawalGas.js'
export {
type EstimateTotalFeeErrorType,
type EstimateTotalFeeParameters,
type EstimateTotalFeeReturnType,
estimateTotalFee,
} from './actions/estimateTotalFee.js'
export {
type EstimateTotalGasErrorType,
type EstimateTotalGasParameters,
type EstimateTotalGasReturnType,
estimateTotalGas,
} from './actions/estimateTotalGas.js'
export {
type FinalizeWithdrawalErrorType,
type FinalizeWithdrawalParameters,
type FinalizeWithdrawalReturnType,
finalizeWithdrawal,
} from './actions/finalizeWithdrawal.js'
export {
type GetGameErrorType,
type GetGameParameters,
type GetGameReturnType,
getGame,
} from './actions/getGame.js'
export {
type GetGamesErrorType,
type GetGamesParameters,
type GetGamesReturnType,
getGames,
} from './actions/getGames.js'
export {
type GetL1BaseFeeErrorType,
type GetL1BaseFeeParameters,
type GetL1BaseFeeReturnType,
getL1BaseFee,
} from './actions/getL1BaseFee.js'
export {
type GetL2OutputErrorType,
type GetL2OutputParameters,
type GetL2OutputReturnType,
getL2Output,
} from './actions/getL2Output.js'
export {
type GetPortalVersionErrorType,
type GetPortalVersionParameters,
type GetPortalVersionReturnType,
getPortalVersion,
} from './actions/getPortalVersion.js'
export {
type GetTimeToFinalizeErrorType,
type GetTimeToFinalizeParameters,
type GetTimeToFinalizeReturnType,
getTimeToFinalize,
} from './actions/getTimeToFinalize.js'
export {
type GetTimeToNextGameErrorType,
type GetTimeToNextGameParameters,
type GetTimeToNextGameReturnType,
getTimeToNextGame,
} from './actions/getTimeToNextGame.js'
export {
type GetTimeToNextL2OutputErrorType,
type GetTimeToNextL2OutputParameters,
type GetTimeToNextL2OutputReturnType,
getTimeToNextL2Output,
} from './actions/getTimeToNextL2Output.js'
export {
type GetTimeToProveErrorType,
type GetTimeToProveParameters,
type GetTimeToProveReturnType,
getTimeToProve,
} from './actions/getTimeToProve.js'
export {
type GetWithdrawalStatusErrorType,
type GetWithdrawalStatusParameters,
type GetWithdrawalStatusReturnType,
getWithdrawalStatus,
} from './actions/getWithdrawalStatus.js'
export {
type InitiateWithdrawalErrorType,
type InitiateWithdrawalParameters,
type InitiateWithdrawalReturnType,
initiateWithdrawal,
} from './actions/initiateWithdrawal.js'
export {
type ProveWithdrawalErrorType,
type ProveWithdrawalParameters,
type ProveWithdrawalReturnType,
proveWithdrawal,
} from './actions/proveWithdrawal.js'
export {
type WaitForNextGameErrorType,
type WaitForNextGameParameters,
type WaitForNextGameReturnType,
waitForNextGame,
} from './actions/waitForNextGame.js'
export {
type WaitForNextL2OutputErrorType,
type WaitForNextL2OutputParameters,
type WaitForNextL2OutputReturnType,
waitForNextL2Output,
} from './actions/waitForNextL2Output.js'
export {
type WaitToFinalizeErrorType,
type WaitToFinalizeParameters,
type WaitToFinalizeReturnType,
waitToFinalize,
} from './actions/waitToFinalize.js'
export {
type WaitToProveErrorType,
type WaitToProveParameters,
type WaitToProveReturnType,
waitToProve,
} from './actions/waitToProve.js'
export { chainConfig } from './chainConfig.js'
export * from './chains.js'
export {
type PublicActionsL1,
publicActionsL1,
} from './decorators/publicL1.js'
export {
type PublicActionsL2,
publicActionsL2,
} from './decorators/publicL2.js'
export {
type WalletActionsL1,
walletActionsL1,
} from './decorators/walletL1.js'
export {
type WalletActionsL2,
walletActionsL2,
} from './decorators/walletL2.js'
export {
type ParseTransactionErrorType,
type ParseTransactionReturnType,
parseTransaction,
} from './parsers.js'
export {
type SerializeTransactionErrorType,
type SerializeTransactionReturnType,
serializers,
serializeTransaction,
} from './serializers.js'
export type {
OpStackBlock,
OpStackBlockOverrides,
OpStackRpcBlock,
OpStackRpcBlockOverrides,
} from './types/block.js'
export type {
OpStackDepositTransaction,
OpStackRpcDepositTransaction,
OpStackRpcTransaction,
OpStackRpcTransactionReceipt,
OpStackRpcTransactionReceiptOverrides,
OpStackTransaction,
OpStackTransactionReceipt,
OpStackTransactionReceiptOverrides,
} from './types/transaction.js'
export {
type ExtractTransactionDepositedLogsErrorType,
type ExtractTransactionDepositedLogsParameters,
type ExtractTransactionDepositedLogsReturnType,
extractTransactionDepositedLogs,
} from './utils/extractTransactionDepositedLogs.js'
export {
type ExtractWithdrawalMessageLogsErrorType,
type ExtractWithdrawalMessageLogsParameters,
type ExtractWithdrawalMessageLogsReturnType,
extractWithdrawalMessageLogs,
} from './utils/extractWithdrawalMessageLogs.js'
export {
type GetL2TransactionHashErrorType,
type GetL2TransactionHashParameters,
type GetL2TransactionHashReturnType,
getL2TransactionHash,
} from './utils/getL2TransactionHash.js'
export {
type GetL2TransactionHashesErrorType,
type GetL2TransactionHashesParameters,
type GetL2TransactionHashesReturnType,
getL2TransactionHashes,
} from './utils/getL2TransactionHashes.js'
export {
type GetSourceHashErrorType,
type GetSourceHashParameters,
type GetSourceHashReturnType,
getSourceHash,
} from './utils/getSourceHash.js'
export {
type GetWithdrawalHashStorageSlotErrorType,
type GetWithdrawalHashStorageSlotParameters,
type GetWithdrawalHashStorageSlotReturnType,
getWithdrawalHashStorageSlot,
} from './utils/getWithdrawalHashStorageSlot.js'
export {
type GetWithdrawalsErrorType,
type GetWithdrawalsParameters,
type GetWithdrawalsReturnType,
getWithdrawals,
} from './utils/getWithdrawals.js'
export {
type OpaqueDataToDepositDataErrorType,
type OpaqueDataToDepositDataParameters,
type OpaqueDataToDepositDataReturnType,
opaqueDataToDepositData,
} from './utils/opaqueDataToDepositData.js'

6
node_modules/viem/op-stack/package.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"type": "module",
"types": "../_types/op-stack/index.d.ts",
"module": "../_esm/op-stack/index.js",
"main": "../_cjs/op-stack/index.js"
}

88
node_modules/viem/op-stack/parsers.ts generated vendored Normal file
View File

@@ -0,0 +1,88 @@
import { InvalidSerializedTransactionError } from '../errors/transaction.js'
import type { ErrorType } from '../errors/utils.js'
import { isHex } from '../utils/data/isHex.js'
import { sliceHex } from '../utils/data/slice.js'
import { hexToBigInt, hexToBool } from '../utils/encoding/fromHex.js'
import type { GetSerializedTransactionType } from '../utils/transaction/getSerializedTransactionType.js'
import {
type ParseTransactionErrorType as ParseTransactionErrorType_,
type ParseTransactionReturnType as ParseTransactionReturnType_,
parseTransaction as parseTransaction_,
toTransactionArray,
} from '../utils/transaction/parseTransaction.js'
import { assertTransactionDeposit } from './serializers.js'
import type {
OpStackTransactionSerialized,
OpStackTransactionType,
TransactionSerializableDeposit,
TransactionSerializedDeposit,
} from './types/transaction.js'
export type ParseTransactionReturnType<
serialized extends
OpStackTransactionSerialized = OpStackTransactionSerialized,
type extends
OpStackTransactionType = GetSerializedTransactionType<serialized>,
> = serialized extends TransactionSerializedDeposit
? TransactionSerializableDeposit
: ParseTransactionReturnType_<serialized, type>
export type ParseTransactionErrorType = ParseTransactionErrorType_ | ErrorType
export function parseTransaction<
serialized extends OpStackTransactionSerialized,
>(serializedTransaction: serialized): ParseTransactionReturnType<serialized> {
const serializedType = sliceHex(serializedTransaction, 0, 1)
if (serializedType === '0x7e')
return parseTransactionDeposit(
serializedTransaction as TransactionSerializedDeposit,
) as ParseTransactionReturnType<serialized>
return parseTransaction_(
serializedTransaction,
) as ParseTransactionReturnType<serialized>
}
function parseTransactionDeposit(
serializedTransaction: TransactionSerializedDeposit,
): ParseTransactionReturnType<TransactionSerializedDeposit> {
const transactionArray = toTransactionArray(serializedTransaction)
const [sourceHash, from, to, mint, value, gas, isSystemTx, data] =
transactionArray
if (transactionArray.length !== 8 || !isHex(sourceHash) || !isHex(from))
throw new InvalidSerializedTransactionError({
attributes: {
sourceHash,
from,
gas,
to,
mint,
value,
isSystemTx,
data,
},
serializedTransaction,
type: 'deposit',
})
const transaction: TransactionSerializableDeposit = {
sourceHash,
from,
type: 'deposit',
}
if (isHex(gas) && gas !== '0x') transaction.gas = hexToBigInt(gas)
if (isHex(to) && to !== '0x') transaction.to = to
if (isHex(mint) && mint !== '0x') transaction.mint = hexToBigInt(mint)
if (isHex(value) && value !== '0x') transaction.value = hexToBigInt(value)
if (isHex(isSystemTx) && isSystemTx !== '0x')
transaction.isSystemTx = hexToBool(isSystemTx)
if (isHex(data) && data !== '0x') transaction.data = data
assertTransactionDeposit(transaction)
return transaction
}

88
node_modules/viem/op-stack/serializers.ts generated vendored Normal file
View File

@@ -0,0 +1,88 @@
import { InvalidAddressError } from '../errors/address.js'
import type { ErrorType } from '../errors/utils.js'
import type { ChainSerializers } from '../types/chain.js'
import type { Hex, Signature } from '../types/misc.js'
import type { TransactionSerializable } from '../types/transaction.js'
import type { RequiredBy } from '../types/utils.js'
import { isAddress } from '../utils/address/isAddress.js'
import { concatHex } from '../utils/data/concat.js'
import { toHex } from '../utils/encoding/toHex.js'
import { toRlp } from '../utils/encoding/toRlp.js'
import {
type SerializeTransactionErrorType as SerializeTransactionErrorType_,
serializeTransaction as serializeTransaction_,
} from '../utils/transaction/serializeTransaction.js'
import type {
OpStackTransactionSerializable,
TransactionSerializableDeposit,
TransactionSerializedDeposit,
} from './types/transaction.js'
export type SerializeTransactionReturnType = ReturnType<
typeof serializeTransaction
>
export type SerializeTransactionErrorType =
| SerializeTransactionErrorType_
| ErrorType
export function serializeTransaction(
transaction: OpStackTransactionSerializable,
signature?: Signature,
) {
if (isDeposit(transaction)) return serializeTransactionDeposit(transaction)
return serializeTransaction_(
transaction as TransactionSerializable,
signature,
)
}
export const serializers = {
transaction: serializeTransaction,
} as const satisfies ChainSerializers
//////////////////////////////////////////////////////////////////////////////
// Serializers
export type SerializeTransactionDepositReturnType = TransactionSerializedDeposit
function serializeTransactionDeposit(
transaction: TransactionSerializableDeposit,
): SerializeTransactionDepositReturnType {
assertTransactionDeposit(transaction)
const { sourceHash, data, from, gas, isSystemTx, mint, to, value } =
transaction
const serializedTransaction: Hex[] = [
sourceHash,
from,
to ?? '0x',
mint ? toHex(mint) : '0x',
value ? toHex(value) : '0x',
gas ? toHex(gas) : '0x',
isSystemTx ? '0x1' : '0x',
data ?? '0x',
]
return concatHex([
'0x7e',
toRlp(serializedTransaction),
]) as SerializeTransactionDepositReturnType
}
function isDeposit(
transaction: OpStackTransactionSerializable,
): transaction is RequiredBy<TransactionSerializableDeposit, 'type'> {
if (transaction.type === 'deposit') return true
if (typeof transaction.sourceHash !== 'undefined') return true
return false
}
export function assertTransactionDeposit(
transaction: TransactionSerializableDeposit,
) {
const { from, to } = transaction
if (from && !isAddress(from)) throw new InvalidAddressError({ address: from })
if (to && !isAddress(to)) throw new InvalidAddressError({ address: to })
}

34
node_modules/viem/op-stack/types/block.ts generated vendored Normal file
View File

@@ -0,0 +1,34 @@
import type { Block, BlockTag } from '../../types/block.js'
import type { Hash } from '../../types/misc.js'
import type { RpcBlock } from '../../types/rpc.js'
import type {
OpStackRpcTransaction,
OpStackTransaction,
} from './transaction.js'
export type OpStackBlockOverrides = {
stateRoot: Hash
}
export type OpStackBlock<
includeTransactions extends boolean = boolean,
blockTag extends BlockTag = BlockTag,
> = Block<
bigint,
includeTransactions,
blockTag,
OpStackTransaction<blockTag extends 'pending' ? true : false>
> &
OpStackBlockOverrides
export type OpStackRpcBlockOverrides = {
stateRoot: Hash
}
export type OpStackRpcBlock<
blockTag extends BlockTag = BlockTag,
includeTransactions extends boolean = boolean,
> = RpcBlock<
blockTag,
includeTransactions,
OpStackRpcTransaction<blockTag extends 'pending' ? true : false>
> &
OpStackRpcBlockOverrides

10
node_modules/viem/op-stack/types/chain.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import type { Chain, ChainContract } from '../../types/chain.js'
export type TargetChain<
chain extends Chain = Chain,
contractName extends string = string,
> = {
contracts: {
[_ in contractName]: { [_ in chain['id']]: ChainContract }
}
}

26
node_modules/viem/op-stack/types/contract.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import type { Address } from 'abitype'
import type { Chain } from '../../types/chain.js'
import type { Prettify } from '../../types/utils.js'
import type { TargetChain } from './chain.js'
export type GetContractAddressParameter<
chain extends Chain | undefined,
contractName extends string,
> =
| (chain extends Chain
? Prettify<
{
targetChain: Prettify<TargetChain<chain, contractName>>
} & {
[_ in `${contractName}Address`]?: undefined
}
>
: never)
| Prettify<
{
targetChain?: undefined
} & {
[_ in `${contractName}Address`]: Address
}
>

28
node_modules/viem/op-stack/types/deposit.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import type { Address } from 'abitype'
import type { Hex } from '../../types/misc.js'
export type DepositRequest = {
/** Gas limit for transaction execution on the L2. */
gas: bigint
/** Value in wei to mint (deposit) on the L2. Debited from the caller's L1 balance. */
mint?: bigint | undefined
/** Value in wei sent with this transaction on the L2. Debited from the caller's L2 balance. */
value?: bigint | undefined
} & (
| {
/** Encoded contract method & arguments. */
data?: Hex | undefined
/** Whether or not this is a contract deployment transaction. */
isCreation?: false | undefined
/** L2 Transaction recipient. */
to?: Address | undefined
}
| {
/** Contract deployment bytecode. Required for contract deployment transactions. */
data: Hex
/** Whether or not this is a contract deployment transaction. */
isCreation: true
/** L2 Transaction recipient. Cannot exist for contract deployment transactions. */
to?: undefined
}
)

106
node_modules/viem/op-stack/types/transaction.ts generated vendored Normal file
View File

@@ -0,0 +1,106 @@
import type { FeeValuesEIP1559 } from '../../types/fee.js'
import type { Hex } from '../../types/misc.js'
import type {
Index,
Quantity,
RpcTransaction as RpcTransaction_,
RpcTransactionReceipt,
} from '../../types/rpc.js'
import type {
Transaction as Transaction_,
TransactionBase,
TransactionReceipt,
TransactionSerializable,
TransactionSerializableBase,
TransactionSerialized,
TransactionType,
} from '../../types/transaction.js'
import type { OneOf } from '../../types/utils.js'
type RpcTransaction<pending extends boolean = boolean> =
RpcTransaction_<pending> & {
isSystemTx?: undefined
mint?: undefined
sourceHash?: undefined
}
export type OpStackRpcDepositTransaction<pending extends boolean = boolean> =
Omit<TransactionBase<Quantity, Index, pending>, 'typeHex'> &
FeeValuesEIP1559<Quantity> & {
isSystemTx?: boolean | undefined
mint?: Hex | undefined
sourceHash: Hex
type: '0x7e'
}
export type OpStackRpcTransaction<pending extends boolean = boolean> = OneOf<
RpcTransaction<pending> | OpStackRpcDepositTransaction<pending>
>
export type OpStackRpcTransactionReceiptOverrides = {
l1GasPrice: Hex | null
l1GasUsed: Hex | null
l1Fee: Hex | null
l1FeeScalar: `${number}` | null
}
export type OpStackRpcTransactionReceipt = RpcTransactionReceipt &
OpStackRpcTransactionReceiptOverrides
type Transaction<pending extends boolean = boolean> = Transaction_<
bigint,
number,
pending
> & {
isSystemTx?: undefined
mint?: undefined
sourceHash?: undefined
}
export type OpStackDepositTransaction<pending extends boolean = boolean> =
TransactionBase<bigint, number, pending> &
FeeValuesEIP1559 & {
isSystemTx?: boolean
mint?: bigint | undefined
sourceHash: Hex
type: 'deposit'
}
export type OpStackTransaction<pending extends boolean = boolean> =
| Transaction<pending>
| OpStackDepositTransaction<pending>
export type OpStackTransactionReceiptOverrides = {
l1GasPrice: bigint | null
l1GasUsed: bigint | null
l1Fee: bigint | null
l1FeeScalar: number | null
}
export type OpStackTransactionReceipt = TransactionReceipt &
OpStackTransactionReceiptOverrides
export type OpStackTransactionSerializable = OneOf<
TransactionSerializableDeposit | TransactionSerializable
>
export type OpStackTransactionSerialized<
type extends OpStackTransactionType = OpStackTransactionType,
> = type extends 'deposit'
? TransactionSerializedDeposit
: TransactionSerialized<type>
export type OpStackTransactionType = TransactionType | 'deposit'
export type TransactionSerializableDeposit<
quantity = bigint,
index = number,
> = Omit<
TransactionSerializableBase<quantity, index>,
'nonce' | 'r' | 's' | 'v'
> & {
from: Hex
isSystemTx?: boolean
mint?: bigint | undefined
sourceHash: Hex
type: 'deposit'
}
export type TransactionSerializedDeposit = `0x7e${string}`

31
node_modules/viem/op-stack/types/withdrawal.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import type { Address } from 'abitype'
import type { Hex } from '../../types/misc.js'
export type Game = {
index: bigint
metadata: Hex
timestamp: bigint
rootClaim: Hex
extraData: Hex
}
export type WithdrawalRequest = {
/** Encoded contract method & arguments. */
data?: Hex | undefined
/** Gas limit for transaction execution on the L1. */
gas: bigint
/** L1 Transaction recipient. */
to: Address
/** Value in wei to withdrawal to the L1. Debited from the caller's L2 balance. */
value?: bigint | undefined
}
export type Withdrawal = {
nonce: bigint
sender: Hex
target: Hex
value: bigint
gasLimit: bigint
data: Hex
withdrawalHash: Hex
}

View File

@@ -0,0 +1,36 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Log } from '../../types/log.js'
import {
type ParseEventLogsErrorType,
parseEventLogs,
} from '../../utils/abi/parseEventLogs.js'
import { portalAbi } from '../abis.js'
export type ExtractTransactionDepositedLogsParameters = {
/** An opaque array of logs. */
logs: Log[]
}
export type ExtractTransactionDepositedLogsReturnType = Log<
bigint,
number,
false,
undefined,
true,
typeof portalAbi,
'TransactionDeposited'
>[]
export type ExtractTransactionDepositedLogsErrorType =
| ParseEventLogsErrorType
| ErrorType
export function extractTransactionDepositedLogs({
logs,
}: ExtractTransactionDepositedLogsParameters) {
return parseEventLogs({
abi: portalAbi,
eventName: 'TransactionDeposited',
logs,
})
}

View File

@@ -0,0 +1,36 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Log } from '../../types/log.js'
import {
type ParseEventLogsErrorType,
parseEventLogs,
} from '../../utils/abi/parseEventLogs.js'
import { l2ToL1MessagePasserAbi } from '../abis.js'
export type ExtractWithdrawalMessageLogsParameters = {
/** An opaque array of logs. */
logs: Log[]
}
export type ExtractWithdrawalMessageLogsReturnType = Log<
bigint,
number,
false,
undefined,
true,
typeof l2ToL1MessagePasserAbi,
'MessagePassed'
>[]
export type ExtractWithdrawalMessageLogsErrorType =
| ParseEventLogsErrorType
| ErrorType
export function extractWithdrawalMessageLogs({
logs,
}: ExtractWithdrawalMessageLogsParameters) {
return parseEventLogs({
abi: l2ToL1MessagePasserAbi,
eventName: 'MessagePassed',
logs,
})
}

View File

@@ -0,0 +1,52 @@
// Adapted from https://github.com/ethereum-optimism/optimism/blob/develop/packages/core-utils/src/optimism/deposit-transaction.ts#L117
import type { ErrorType } from '../../errors/utils.js'
import type { Log } from '../../types/log.js'
import type { Hex } from '../../types/misc.js'
import { keccak256 } from '../../utils/hash/keccak256.js'
import type { portalAbi } from '../abis.js'
import { serializeTransaction } from '../serializers.js'
import { getSourceHash } from './getSourceHash.js'
import { opaqueDataToDepositData } from './opaqueDataToDepositData.js'
export type GetL2TransactionHashParameters = {
/** The "TransactionDeposited" log to compute the L2 hash from. */
log: Log<
bigint,
number,
false,
undefined,
true,
typeof portalAbi,
'TransactionDeposited'
>
}
export type GetL2TransactionHashReturnType = Hex
export type GetL2TransactionHashErrorType = ErrorType
export function getL2TransactionHash({ log }: GetL2TransactionHashParameters) {
const sourceHash = getSourceHash({
domain: 'userDeposit',
l1BlockHash: log.blockHash,
l1LogIndex: log.logIndex,
})
const { data, gas, isCreation, mint, value } = opaqueDataToDepositData(
log.args.opaqueData,
)
return keccak256(
serializeTransaction({
from: log.args.from,
to: isCreation ? undefined : log.args.to,
sourceHash,
data,
gas,
isSystemTx: false,
mint,
type: 'deposit',
value,
}),
)
}

View File

@@ -0,0 +1,21 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Log } from '../../types/log.js'
import type { Hex } from '../../types/misc.js'
import { extractTransactionDepositedLogs } from './extractTransactionDepositedLogs.js'
import { getL2TransactionHash } from './getL2TransactionHash.js'
export type GetL2TransactionHashesParameters = {
/** The L1 transaction receipt logs. */
logs: Log[]
}
export type GetL2TransactionHashesReturnType = Hex[]
export type GetL2TransactionHashesErrorType = ErrorType
export function getL2TransactionHashes({
logs,
}: GetL2TransactionHashesParameters): GetL2TransactionHashesReturnType {
const extractedLogs = extractTransactionDepositedLogs({ logs })
return extractedLogs.map((log) => getL2TransactionHash({ log }))
}

61
node_modules/viem/op-stack/utils/getSourceHash.ts generated vendored Normal file
View File

@@ -0,0 +1,61 @@
// Adapted from https://github.com/ethereum-optimism/optimism/blob/develop/packages/core-utils/src/optimism/deposit-transaction.ts#L117
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
import { type ConcatErrorType, concat } from '../../utils/data/concat.js'
import { type PadErrorType, pad } from '../../utils/data/pad.js'
import { type ToHexErrorType, toHex } from '../../utils/encoding/toHex.js'
import {
type Keccak256ErrorType,
keccak256,
} from '../../utils/hash/keccak256.js'
export type GetSourceHashParameters = {
/** The L1 block hash. */
l1BlockHash: Hex
} & (
| {
/** Domain of source hash. */
domain: 'userDeposit'
/** The index of the log on the L1. */
l1LogIndex: number
/** The sequence number. */
sequenceNumber?: undefined
}
| {
/** Domain of source hash. */
domain: 'l1InfoDeposit'
/** The index of the log on the L1. */
l1LogIndex?: undefined
/** The sequence number. */
sequenceNumber: number
}
)
export type GetSourceHashReturnType = Hex
export type GetSourceHashErrorType =
| ConcatErrorType
| Keccak256ErrorType
| PadErrorType
| ToHexErrorType
| ErrorType
const sourceHashDomainMap = {
userDeposit: 0,
l1InfoDeposit: 1,
} as const
export function getSourceHash({
domain,
l1LogIndex,
l1BlockHash,
sequenceNumber,
}: GetSourceHashParameters) {
const marker = toHex(l1LogIndex! ?? sequenceNumber!)
const input = concat([l1BlockHash, pad(marker, { size: 32 })])
const depositIdHash = keccak256(input)
const domainHex = toHex(sourceHashDomainMap[domain])
const domainInput = concat([pad(domainHex, { size: 32 }), depositIdHash])
return keccak256(domainInput)
}

View File

@@ -0,0 +1,29 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Hash } from '../../types/misc.js'
import {
type EncodeAbiParametersErrorType,
encodeAbiParameters,
} from '../../utils/abi/encodeAbiParameters.js'
import {
type Keccak256ErrorType,
keccak256,
} from '../../utils/hash/keccak256.js'
export type GetWithdrawalHashStorageSlotParameters = {
withdrawalHash: Hash
}
export type GetWithdrawalHashStorageSlotReturnType = Hash
export type GetWithdrawalHashStorageSlotErrorType =
| EncodeAbiParametersErrorType
| Keccak256ErrorType
| ErrorType
export function getWithdrawalHashStorageSlot({
withdrawalHash,
}: GetWithdrawalHashStorageSlotParameters) {
const data = encodeAbiParameters(
[{ type: 'bytes32' }, { type: 'uint256' }],
[withdrawalHash, 0n],
)
return keccak256(data)
}

25
node_modules/viem/op-stack/utils/getWithdrawals.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Log } from '../../types/log.js'
import type { Withdrawal } from '../types/withdrawal.js'
import {
type ExtractWithdrawalMessageLogsErrorType,
extractWithdrawalMessageLogs,
} from './extractWithdrawalMessageLogs.js'
export type GetWithdrawalsParameters = {
/** The L2 transaction receipt logs. */
logs: Log[]
}
export type GetWithdrawalsReturnType = Withdrawal[]
export type GetWithdrawalsErrorType =
| ExtractWithdrawalMessageLogsErrorType
| ErrorType
export function getWithdrawals({
logs,
}: GetWithdrawalsParameters): GetWithdrawalsReturnType {
const extractedLogs = extractWithdrawalMessageLogs({ logs })
return extractedLogs.map((log) => log.args)
}

View File

@@ -0,0 +1,45 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
import { type SizeErrorType, size } from '../../utils/data/size.js'
import { type SliceErrorType, slice } from '../../utils/data/slice.js'
import { hexToBigInt } from '../../utils/encoding/fromHex.js'
export type OpaqueDataToDepositDataParameters = Hex
export type OpaqueDataToDepositDataReturnType = {
mint: bigint
value: bigint
gas: bigint
isCreation: boolean
data: Hex
}
export type OpaqueDataToDepositDataErrorType =
| SliceErrorType
| SizeErrorType
| ErrorType
export function opaqueDataToDepositData(
opaqueData: Hex,
): OpaqueDataToDepositDataReturnType {
let offset = 0
const mint = slice(opaqueData, offset, offset + 32)
offset += 32
const value = slice(opaqueData, offset, offset + 32)
offset += 32
const gas = slice(opaqueData, offset, offset + 8)
offset += 8
const isCreation = BigInt(slice(opaqueData, offset, offset + 1)) === 1n
offset += 1
const data =
offset > size(opaqueData) - 1
? '0x'
: slice(opaqueData, offset, opaqueData.length)
return {
mint: hexToBigInt(mint),
value: hexToBigInt(value),
gas: hexToBigInt(gas),
isCreation,
data,
}
}