UNPKG

zksync-ethers

Version:

A Web3 library for interacting with the ZkSync Layer 2 scaling solution.

1,564 lines (1,513 loc) 50.6 kB
import {EIP712Signer} from './signer'; import {Provider} from './provider'; import {EIP712_TX_TYPE, serializeEip712} from './utils'; import { BigNumberish, BlockTag, BytesLike, ContractTransactionResponse, ethers, Overrides, ProgressCallback, } from 'ethers'; import { Address, BalancesMap, Fee, FinalizeL1DepositParams, FinalizeWithdrawalParams, FullDepositFee, PaymasterParams, PriorityOpResponse, TransactionLike, TransactionRequest, TransactionResponse, } from './types'; import {AdapterL1, AdapterL2} from './adapters'; import { IBridgehub, IL1ERC20Bridge, IL1SharedBridge, IL2Bridge, IL2SharedBridge, IZkSyncHyperchain, } from './typechain'; /** * A `Wallet` is an extension of {@link ethers.Wallet} with additional features for interacting with ZKsync Era. * It facilitates bridging assets between different networks. * All transactions must originate from the address corresponding to the provided private key. */ export class Wallet extends AdapterL2(AdapterL1(ethers.Wallet)) { override readonly provider!: Provider; providerL1?: ethers.Provider; public eip712!: EIP712Signer; override _providerL1(): ethers.Provider { if (!this.providerL1) { throw new Error( 'L1 provider is missing! Specify an L1 provider using `Wallet.connectToL1()`.' ); } return this.providerL1; } override _providerL2(): Provider { return this.provider; } override _signerL1(): ethers.Wallet { return this.ethWallet(); } override _signerL2(): Wallet { return this; } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const mainContract = await wallet.getMainContract(); */ override async getMainContract(): Promise<IZkSyncHyperchain> { return super.getMainContract(); } /** * @inheritDoc * * @example * * import { Wallet, Provider, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const bridgehub = await wallet.getBridgehubContract(); */ override async getBridgehubContract(): Promise<IBridgehub> { return super.getBridgehubContract(); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const l1BridgeContracts = await wallet.getL1BridgeContracts(); */ override async getL1BridgeContracts(): Promise<{ erc20: IL1ERC20Bridge; weth: IL1ERC20Bridge; shared: IL1SharedBridge; }> { return super.getL1BridgeContracts(); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; * * console.log(`Token balance: ${await wallet.getBalanceL1(tokenL1)}`); */ override async getBalanceL1( token?: Address, blockTag?: BlockTag ): Promise<bigint> { return super.getBalanceL1(token, blockTag); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; * console.log(`Token allowance: ${await wallet.getAllowanceL1(tokenL1)}`); */ override async getAllowanceL1( token: Address, bridgeAddress?: Address, blockTag?: BlockTag ): Promise<bigint> { return super.getAllowanceL1(token, bridgeAddress, blockTag); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; * * console.log(`Token L2 address: ${await wallet.l2TokenAddress(tokenL1)}`); */ override async l2TokenAddress(token: Address): Promise<string> { return super.l2TokenAddress(token); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL2 = "0xe1134444211593Cfda9fc9eCc7B43208615556E2"; * * console.log(`Token L1 address: ${await wallet.l1TokenAddress(tokenL1)}`); */ override async l1TokenAddress(token: Address): Promise<string> { return super.l1TokenAddress(token); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; * const tx = await wallet.approveERC20(tokenL1, "10000000"); * * await tx.wait(); */ override async approveERC20( token: Address, amount: BigNumberish, overrides?: Overrides & { bridgeAddress?: Address; } ): Promise<ethers.TransactionResponse> { return super.approveERC20(token, amount, overrides); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * console.log(`Base cost: ${await wallet.getBaseCost({ gasLimit: 100_000 })}`); */ override async getBaseCost(params: { gasLimit: BigNumberish; gasPerPubdataByte?: BigNumberish; gasPrice?: BigNumberish; }): Promise<bigint> { return super.getBaseCost(params); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * console.log(`Base token: ${await wallet.getBaseToken()}`); */ override async getBaseToken(): Promise<string> { return super.getBaseToken(); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * console.log(`Is ETH-based chain: ${await wallet.isETHBasedChain()}`); */ override async isETHBasedChain(): Promise<boolean> { return super.isETHBasedChain(); } /** * @inheritDoc * * @example Get allowance parameters for depositing ETH on ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const token = "<L1_TOKEN>"; * const amount = 5; * const approveParams = await wallet.getDepositAllowanceParams(token, amount); * * await ( * await wallet.approveERC20( * approveParams[0].token, * approveParams[0].allowance * ) * ).wait(); * * @example Get allowance parameters for depositing ETH on non-ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const token = utils.LEGACY_ETH_ADDRESS; * const amount = 5; * const approveParams = await wallet.getDepositAllowanceParams(token, amount); * * await ( * await wallet.approveERC20( * approveParams[0].token, * approveParams[0].allowance * ) * ).wait(); * * @example Get allowance parameters for depositing base token on non-ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const token = await wallet.getBaseToken(); * const amount = 5; * const approveParams = await wallet.getDepositAllowanceParams(token, amount); * * await ( * await wallet.approveERC20( * approveParams[0].token, * approveParams[0].allowance * ) * ).wait(); * * @example Get allowance parameters for depositing non-base token on non-ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const token = "<L1_TOKEN>"; * const amount = 5; * const approveParams = await wallet.getDepositAllowanceParams(token, amount); * * await ( * await wallet.approveERC20( * approveParams[0].token, * approveParams[0].allowance * ) * ).wait(); * * await ( * await wallet.approveERC20( * approveParams[1].token, * approveParams[1].allowance * ) * ).wait(); */ override async getDepositAllowanceParams( token: Address, amount: BigNumberish, overrides?: ethers.Overrides ): Promise< { token: Address; allowance: BigNumberish; }[] > { return super.getDepositAllowanceParams(token, amount, overrides); } /** * @inheritDoc * * @example Deposit ETH on ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const depositTx = await wallet.deposit({ * token: utils.ETH_ADDRESS, * amount: 10_000_000n, * }); * // Note that we wait not only for the L1 transaction to complete but also for it to be * // processed by zkSync. If we want to wait only for the transaction to be processed on L1, * // we can use `await depositTx.waitL1Commit()` * await depositTx.wait(); * * @example Deposit token on ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; * const depositTx = await wallet.deposit({ * token: tokenL1, * amount: 10_000_000n, * approveERC20: true, * }); * // Note that we wait not only for the L1 transaction to complete but also for it to be * // processed by zkSync. If we want to wait only for the transaction to be processed on L1, * // we can use `await depositTx.waitL1Commit()` * await depositTx.wait(); * * @example Deposit ETH on non-ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const depositTx = await wallet.deposit({ * token: utils.ETH_ADDRESS, * amount: 10_000_000n, * approveBaseERC20: true, * }); * // Note that we wait not only for the L1 transaction to complete but also for it to be * // processed by zkSync. If we want to wait only for the transaction to be processed on L1, * // we can use `await depositTx.waitL1Commit()` * await depositTx.wait(); * * @example Deposit base token on non-ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const depositTx = await wallet.deposit({ * token: await wallet.getBaseToken(), * amount: 10_000_000n, * approveERC20: true, // or approveBaseERC20: true * }); * // Note that we wait not only for the L1 transaction to complete but also for it to be * // processed by zkSync. If we want to wait only for the transaction to be processed on L1, * // we can use `await depositTx.waitL1Commit()` * await depositTx.wait(); * * @example Deposit non-base token on non-ETH-based chain. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; * const depositTx = await wallet.deposit({ * token: tokenL1, * amount: 10_000_000n, * approveERC20: true, * approveBaseERC20: true, * }); * // Note that we wait not only for the L1 transaction to complete but also for it to be * // processed by zkSync. If we want to wait only for the transaction to be processed on L1, * // we can use `await depositTx.waitL1Commit()` * await depositTx.wait(); */ override async deposit(transaction: { token: Address; amount: BigNumberish; to?: Address; operatorTip?: BigNumberish; bridgeAddress?: Address; approveERC20?: boolean; approveBaseERC20?: boolean; l2GasLimit?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; approveOverrides?: Overrides; approveBaseOverrides?: Overrides; customBridgeData?: BytesLike; }): Promise<PriorityOpResponse> { return super.deposit(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; * const gas = await wallet.estimateGasDeposit({ * token: tokenL1, * amount: 10_000_000n, * }); * console.log(`Gas: ${gas}`); */ override async estimateGasDeposit(transaction: { token: Address; amount: BigNumberish; to?: Address; operatorTip?: BigNumberish; bridgeAddress?: Address; customBridgeData?: BytesLike; l2GasLimit?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; }): Promise<bigint> { return super.estimateGasDeposit(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; * const tx = await wallet.getDepositTx({ * token: tokenL1, * amount: "10_000_000n, * }); */ override async getDepositTx(transaction: { token: Address; amount: BigNumberish; to?: Address; operatorTip?: BigNumberish; bridgeAddress?: Address; l2GasLimit?: BigNumberish; gasPerPubdataByte?: BigNumberish; customBridgeData?: BytesLike; refundRecipient?: Address; overrides?: Overrides; }): Promise<any> { return super.getDepositTx(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; * const fee = await wallet.getFullRequiredDepositFee({ * token: tokenL1, * to: await wallet.getAddress(), * }); * console.log(`Fee: ${fee}`); */ override async getFullRequiredDepositFee(transaction: { token: Address; to?: Address; bridgeAddress?: Address; customBridgeData?: BytesLike; gasPerPubdataByte?: BigNumberish; overrides?: Overrides; }): Promise<FullDepositFee> { return super.getFullRequiredDepositFee(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const WITHDRAWAL_HASH = "<WITHDRAWAL_TX_HASH>"; * const params = await wallet.finalizeWithdrawalParams(WITHDRAWAL_HASH); */ override async finalizeWithdrawalParams( withdrawalHash: BytesLike, index = 0 ): Promise<FinalizeWithdrawalParams> { return super.finalizeWithdrawalParams(withdrawalHash, index); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const WITHDRAWAL_HASH = "<WITHDRAWAL_TX_HASH>"; * const params = await wallet.finalizeWithdrawalParams(WITHDRAWAL_HASH); */ override async getFinalizeWithdrawalParams( withdrawalHash: BytesLike, index = 0 ): Promise<FinalizeWithdrawalParams> { return super.getFinalizeWithdrawalParams(withdrawalHash, index); } override async getFinalizeDepositParams( withdrawalHash: BytesLike, index = 0 ): Promise<FinalizeL1DepositParams> { return super.getFinalizeDepositParams(withdrawalHash, index); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const WITHDRAWAL_HASH = "<WITHDRAWAL_TX_HASH>"; * const finalizeWithdrawTx = await wallet.finalizeWithdrawal(WITHDRAWAL_HASH); */ override async finalizeWithdrawal( withdrawalHash: BytesLike, index = 0, overrides?: Overrides ): Promise<ContractTransactionResponse> { return super.finalizeWithdrawal(withdrawalHash, index, overrides); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const WITHDRAWAL_HASH = "<WITHDRAWAL_TX_HASH>"; * const isFinalized = await wallet.isWithdrawalFinalized(WITHDRAWAL_HASH); */ override async isWithdrawalFinalized( withdrawalHash: BytesLike, index = 0 ): Promise<boolean> { return super.isWithdrawalFinalized(withdrawalHash, index); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const FAILED_DEPOSIT_HASH = "<FAILED_DEPOSIT_TX_HASH>"; * const claimFailedDepositTx = await wallet.claimFailedDeposit(FAILED_DEPOSIT_HASH); */ override async claimFailedDeposit( depositHash: BytesLike, overrides?: Overrides ): Promise<ContractTransactionResponse> { return super.claimFailedDeposit(depositHash, overrides); } /** * @inheritDoc * * @example * * import { Wallet, Provider, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tx = { * contractAddress: await wallet.getAddress(), * calldata: '0x', * l2Value: 7_000_000_000, * }; * * const approveParams = await wallet.getRequestExecuteAllowanceParams(tx); * await ( * await wallet.approveERC20( * approveParams.token, * approveParams.allowance * ) * ).wait(); */ override async getRequestExecuteAllowanceParams(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; l2Value?: BigNumberish; factoryDeps?: BytesLike[]; operatorTip?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; }): Promise<{token: Address; allowance: BigNumberish}> { return super.getRequestExecuteAllowanceParams(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const CONTRACT_ADDRESS = "<CONTRACT_ADDRESS>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tx = await wallet.requestExecute({ * contractAddress: await provider.getMainContractAddress(), * calldata: "0x", * l2Value: 7_000_000_000, * }); * await tx.wait(); */ override async requestExecute(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; mintValue?: BigNumberish; l2Value?: BigNumberish; factoryDeps?: BytesLike[]; operatorTip?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; }): Promise<PriorityOpResponse> { return super.requestExecute(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const CONTRACT_ADDRESS = "<CONTRACT_ADDRESS>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const gas = await wallet.estimateGasRequestExecute({ * contractAddress: await provider.getMainContractAddress(), * calldata: "0x", * l2Value: 7_000_000_000, * }); * console.log(`Gas: ${gas}`); */ override async estimateGasRequestExecute(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; mintValue?: BigNumberish; l2Value?: BigNumberish; factoryDeps?: BytesLike[]; operatorTip?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; }): Promise<bigint> { return super.estimateGasRequestExecute(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const CONTRACT_ADDRESS = "<CONTRACT_ADDRESS>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tx = await wallet.getRequestExecuteTx({ * contractAddress: await provider.getMainContractAddress(), * calldata: "0x", * l2Value: 7_000_000_000, * }); */ override async getRequestExecuteTx(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; mintValue?: BigNumberish; l2Value?: BigNumberish; factoryDeps?: BytesLike[]; operatorTip?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; }): Promise<TransactionRequest> { return super.getRequestExecuteTx(transaction); } /** * @inheritDoc * * @example Get ETH balance. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * console.log(`ETH balance: ${await wallet.getBalance()}`); * * @example Get token balance. * * import { Wallet, Provider, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const token = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; * * console.log(`Token balance: ${await wallet.getBalance(token)}`); */ override async getBalance( token?: Address, blockTag: BlockTag = 'committed' ): Promise<bigint> { return super.getBalance(token, blockTag); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const allBalances = await wallet.getAllBalances(); */ override async getAllBalances(): Promise<BalancesMap> { return super.getAllBalances(); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * console.log(`Nonce: ${await wallet.getDeploymentNonce()}`); */ override async getDeploymentNonce(): Promise<bigint> { return super.getDeploymentNonce(); } /** * @inheritDoc * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const l2BridgeContracts = await wallet.getL2BridgeContracts(); */ override async getL2BridgeContracts(): Promise<{ erc20: IL2Bridge; weth: IL2Bridge; shared: IL2SharedBridge; }> { return super.getL2BridgeContracts(); } /** * @inheritDoc * * @example Withdraw ETH. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const withdrawTx = await wallet.withdraw({ * token: utils.ETH_ADDRESS, * amount: 10_000_000n, * }); * * @example Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free * const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const withdrawTx = await wallet.withdraw({ * token: utils.ETH_ADDRESS, * amount: 10_000_000n, * paymasterParams: utils.getPaymasterParams(paymaster, { * type: "ApprovalBased", * token: token, * minimalAllowance: 1, * innerInput: new Uint8Array(), * }), * }); * * @example Withdraw token. * * import { Wallet, Provider, types } from "zksync-ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; * const withdrawTx = await wallet.withdraw({ * token: tokenL2, * amount: 10_000_000, * }); * * @example Withdraw token using paymaster to facilitate fee payment with an ERC20 token. * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free * const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; * const withdrawTx = await wallet.withdraw({ * token: tokenL2, * amount: 10_000_000n, * paymasterParams: utils.getPaymasterParams(paymaster, { * type: "ApprovalBased", * token: token, * minimalAllowance: 1, * innerInput: new Uint8Array(), * }), * }); */ override async withdraw(transaction: { token: Address; amount: BigNumberish; to?: Address; bridgeAddress?: Address; paymasterParams?: PaymasterParams; overrides?: Overrides; }): Promise<TransactionResponse> { return super.withdraw(transaction); } /** * @inheritDoc * * @example Transfer ETH. * * import { Wallet, Provider, types } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const transferTx = await wallet.transfer({ * to: Wallet.createRandom().address, * amount: ethers.parseEther("0.01"), * }); * * const receipt = await transferTx.wait(); * * console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); * * @example Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. * * import { Wallet, Provider, types } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free * const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const transferTx = await wallet.transfer({ * to: Wallet.createRandom().address, * amount: ethers.parseEther("0.01"), * paymasterParams: utils.getPaymasterParams(paymaster, { * type: "ApprovalBased", * token: token, * minimalAllowance: 1, * innerInput: new Uint8Array(), * }), * }); * * const receipt = await transferTx.wait(); * * console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); * * @example Transfer token. * * import { Wallet, Provider, types } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; * const transferTx = await wallet.transfer({ * token: tokenL2, * to: Wallet.createRandom().address, * amount: ethers.parseEther("0.01"), * }); * * const receipt = await transferTx.wait(); * * console.log(`The sum of ${receipt.value} token was transferred to ${receipt.to}`); * * @example Transfer token using paymaster to facilitate fee payment with an ERC20 token. * * import { Wallet, Provider, types } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free * const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; * const transferTx = await wallet.transfer({ * token: tokenL2, * to: Wallet.createRandom().address, * amount: ethers.parseEther("0.01"), * paymasterParams: utils.getPaymasterParams(paymaster, { * type: "ApprovalBased", * token: token, * minimalAllowance: 1, * innerInput: new Uint8Array(), * }), * }); * * const receipt = await transferTx.wait(); * * console.log(`The sum of ${receipt.value} token was transferred to ${receipt.to}`); */ override async transfer(transaction: { to: Address; amount: BigNumberish; token?: Address; paymasterParams?: PaymasterParams; overrides?: Overrides; }): Promise<TransactionResponse> { return super.transfer(transaction); } /** * @inheritDoc * * @example * * import { Wallet, Provider, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = new Wallet(PRIVATE_KEY, provider); * * // Any L2 -> L1 transaction can be used. * // In this case, withdrawal transaction is used. * const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; * console.log(`Confirmation data: ${utils.toJSON(await wallet.getPriorityOpConfirmation(tx, 0))}`); */ override async getPriorityOpConfirmation( txHash: string, index = 0 ): Promise<{ l1BatchNumber: number; l2MessageIndex: number; l2TxNumberInBlock: number | null; proof: string[]; }> { return super.getPriorityOpConfirmation(txHash, index); } /** * Returns `ethers.Wallet` object with the same private key. * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const ethWallet = wallet.ethWallet(); */ ethWallet(): ethers.Wallet { return new ethers.Wallet(this.signingKey, this._providerL1()); } /** * Connects to the L2 network using `provider`. * * @param provider The provider instance for connecting to an L2 network. * * @see {@link connectToL1} in order to connect to L1 network. * * @example * * import { Wallet, Provider, types } from "zksync-ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const unconnectedWallet = new Wallet(PRIVATE_KEY); * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const wallet = unconnectedWallet.connect(provider); */ override connect(provider: Provider): Wallet { return new Wallet(this.signingKey, provider, this.providerL1); } /** * Connects to the L1 network using `provider`. * * @param provider The provider instance for connecting to a L1 network. * * @see {@link connect} in order to connect to L2 network. * * @example * * import { Wallet } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * const unconnectedWallet = new Wallet(PRIVATE_KEY); * * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = unconnectedWallet.connectToL1(ethProvider); * * @param provider */ connectToL1(provider: ethers.Provider): Wallet { return new Wallet(this.signingKey, this.provider, provider); } /** * Creates a new `Wallet` with the `provider` as L1 provider and a private key that is built from the mnemonic passphrase. * * @param mnemonic The mnemonic of the private key. * @param [provider] The provider instance for connecting to a L1 network. * * @example * * import { Wallet, Provider, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const MNEMONIC = "stuff slice staff easily soup parent arm payment cotton hammer scatter struggle"; * * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = Wallet.fromMnemonic(MNEMONIC, ethProvider); */ static fromMnemonic(mnemonic: string, provider?: ethers.Provider): Wallet { const wallet = super.fromPhrase(mnemonic, provider); return new Wallet( wallet.signingKey, undefined, wallet.provider as ethers.Provider ); } /** * Creates a new `Wallet` from encrypted json file using provided `password`. * * @param json The encrypted json file. * @param password The password for the encrypted json file. * @param [callback] If provided, it is called periodically during decryption so that any UI can be updated. * * @example * * import { Wallet, Provider, utils } from "zksync-ethers"; * import * as fs from "fs"; * * const wallet = await Wallet.fromEncryptedJson(fs.readFileSync("wallet.json", "utf8"), "password"); */ static override async fromEncryptedJson( json: string, password: string | Uint8Array, callback?: ProgressCallback ): Promise<Wallet> { const wallet = await super.fromEncryptedJson(json, password, callback); return new Wallet(wallet.signingKey); } /** * Creates a new `Wallet` from encrypted json file using provided `password`. * * @param json The encrypted json file. * @param password The password for the encrypted json file. * * @example * * import { Wallet } from "zksync-ethers"; * import * as fs from "fs"; * * const wallet = Wallet.fromEncryptedJsonSync(fs.readFileSync("tests/files/wallet.json", "utf8"), "password"); */ static override fromEncryptedJsonSync( json: string, password: string | Uint8Array ): Wallet { const wallet = super.fromEncryptedJsonSync(json, password); return new Wallet(wallet.signingKey); } /** * * @param privateKey The private key of the account. * @param providerL2 The provider instance for connecting to a L2 network. * @param providerL1 The provider instance for connecting to a L1 network. * * @example * * import { Wallet, Provider, types } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); */ constructor( privateKey: string | ethers.SigningKey, providerL2?: Provider, providerL1?: ethers.Provider ) { super(privateKey, providerL2); if (this.provider) { const network = this.provider.getNetwork(); this.eip712 = new EIP712Signer( this, network.then(n => Number(n.chainId)) ); } this.providerL1 = providerL1; } /** * Designed for users who prefer a simplified approach by providing only the necessary data to create a valid transaction. * The only required fields are `transaction.to` and either `transaction.data` or `transaction.value` (or both, if the method is payable). * Any other fields that are not set will be prepared by this method. * * @param tx The transaction request that needs to be populated. * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const populatedTx = await wallet.populateTransaction({ * type: utils.EIP712_TX_TYPE, * to: RECEIVER, * value: 7_000_000_000n, * }); */ override async populateTransaction( tx: TransactionRequest ): Promise<TransactionLike> { const populated = (await this.populateCall(tx)) as TransactionLike; if ( populated.gasPrice && (populated.maxFeePerGas || populated.maxPriorityFeePerGas) ) { throw new Error( 'Provide combination of maxFeePerGas and maxPriorityFeePerGas or provide gasPrice. Not both!' ); } let fee: Fee; if ( !populated.gasLimit || !tx.customData || !tx.customData.gasPerPubdata || (!populated.gasPrice && (!populated.maxFeePerGas || populated.maxPriorityFeePerGas === null || populated.maxPriorityFeePerGas === undefined)) ) { fee = await this.provider.estimateFee(populated); populated.gasLimit ??= fee.gasLimit; if (!populated.gasPrice && populated.type === 0) { populated.gasPrice = fee.maxFeePerGas; } else if (!populated.gasPrice && populated.type !== 0) { populated.maxFeePerGas ??= fee.maxFeePerGas; populated.maxPriorityFeePerGas ??= fee.maxPriorityFeePerGas; } } if ( tx.type === null || tx.type === undefined || tx.type === EIP712_TX_TYPE || tx.customData ) { tx.customData ??= {}; tx.customData.gasPerPubdata ??= fee!.gasPerPubdataLimit; populated.type = EIP712_TX_TYPE; populated.value ??= 0; populated.data ??= '0x'; populated.customData = this._fillCustomData(tx.customData ?? {}); populated.nonce = populated.nonce ?? (await this.getNonce('pending')); populated.chainId = populated.chainId ?? (await this.provider.getNetwork()).chainId; return populated; } return super.populateTransaction(populated); } /*** * Signs the transaction and serializes it to be ready to be broadcast to the network. * * @param tx The transaction request that needs to be signed. * * @throws {Error} If `transaction.from` is mismatched from the private key. * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); * * const tx = await wallet.signTransaction({ * type: utils.EIP712_TX_TYPE, * to: Wallet.createRandom().address, * value: ethers.parseEther('1'), * }); */ override async signTransaction(tx: TransactionRequest): Promise<string> { const populated = await this.populateTransaction(tx); if (populated.type !== EIP712_TX_TYPE) { return await super.signTransaction(populated); } populated.customData!.customSignature = await this.eip712.sign(populated); return serializeEip712(populated); } /** * Broadcast the transaction to the network. * * @param tx The transaction request that needs to be broadcast to the network. * * @throws {Error} If `transaction.from` is mismatched from the private key. * * @example * * import { Wallet, Provider, types, utils } from "zksync-ethers"; * import { ethers } from "ethers"; * * const PRIVATE_KEY = "<WALLET_PRIVATE_KEY>"; * * const provider = Provider.getDefaultProvider(types.Network.Sepolia); * const ethProvider = ethers.getDefaultProvider("sepolia"); * const wallet = new Wallet(PRIVATE