diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/00.providers/01.provider.md b/content/sdk/10.js/00.ethers/05.api/10.v5/00.providers/01.provider.md index 90c94f52..5039367b 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/00.providers/01.provider.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/00.providers/01.provider.md @@ -6,6 +6,31 @@ tags: ["zksync", "providers", "integration"] Provider objects facilitate interaction with the ZKsync network, allowing users to manage transactions, estimate fees, and retrieve network information. + +### `connectL2Bridge` + +Returns contract wrapper. If given address is shared bridge address it +returns Il2SharedBridge and if its legacy it returns Il2Bridge. + +#### Inputs + +| Parameter | Type | Description | +| --------------- |-----------| ------------------------------------------------- | +| `address` | 'Address' | The bridge address. | + +```ts +async connectL2Bridge(address: Address): Promise +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const l2Bridge = await provider.connectL2Bridge(""); +``` + ### `constructor` Initializes a ZKsync Era `Provider` object. @@ -25,7 +50,7 @@ constructor(url?: ConnectionInfo | string, network?: ethers.providers.Networkish ```ts import { Provider } from "zksync-ethers"; - + const provider = new Provider("https://sepolia.era.zksync.dev"); ``` @@ -45,7 +70,7 @@ async estimateFee(transaction: TransactionRequest): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const fee = await provider.estimateFee({ from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", @@ -71,7 +96,7 @@ async estimateGas(transaction: utils.Deferrable): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasL1 = await provider.estimateGasL1({ from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", @@ -176,7 +201,7 @@ async estimateGasTransfer(transaction: { ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasTransfer = await provider.estimateGasTransfer({ token: utils.ETH_ADDRESS, @@ -222,7 +247,7 @@ async estimateGasWithdraw(transaction: { ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasWithdraw = await provider.estimateGasWithdraw({ token: utils.ETH_ADDRESS, @@ -265,7 +290,7 @@ async estimateL1ToL2Execute(transaction: { ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasL1ToL2 = await provider.estimateL1ToL2Execute({ contractAddress: await provider.getMainContractAddress(), @@ -297,7 +322,7 @@ async getAllAccountBalances(address: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const balances = await provider.getAllAccountBalances("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); console.log(`All balances: ${utils.toJSON(balances)}`); @@ -325,7 +350,7 @@ async getBalance(address: Address, blockTag?: BlockTag, tokenAddress?: Address) ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"; const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free @@ -347,7 +372,7 @@ async getBaseTokenContractAddress(): Promise
```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Base token: ${await provider.getBaseTokenContractAddress()}`); ``` @@ -364,7 +389,7 @@ async getBlock(blockHashOrBlockTag: BlockTag | string | Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Block details: ${utils.toJSON(await provider.getBlockDetails(90_000))}`); ``` @@ -408,7 +433,7 @@ async getBridgehubContractAddress(): Promise
```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Bridgehub: ${await provider.getBridgehubContractAddress()}`); ``` @@ -433,13 +458,13 @@ async getBytecodeByHash(bytecodeHash: BytesLike): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + // Bytecode hash can be computed by following these steps: // const testnetPaymasterBytecode = await provider.getCode(await provider.getTestnetPaymasterAddress()); // const testnetPaymasterBytecodeHash = ethers.utils.hexlify(utils.hashBytecode(testnetPaymasterBytecode)); - + const testnetPaymasterBytecodeHash = "0x010000f16d2b10ddeb1c32f2c9d222eb1aea0f638ec94a81d4e916c627720e30"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Bytecode: ${await provider.getBytecodeByHash(testnetPaymasterBytecodeHash)}`); ``` @@ -466,7 +491,7 @@ async getConfirmedTokens(start: number = 0, limit: number = 255): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free console.log(`Contract account info: ${utils.toJSON(await provider.getContractAccountInfo(tokenAddress))}`); @@ -515,59 +540,11 @@ getDefaultBridgeAddresses(): Promise<{ ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Default bridges: ${utils.toJSON(await provider.getDefaultBridgeAddresses())}`); ``` -### `connectL2Bridge` - -Returns contract wrapper. If given address is shared bridge address it -returns Il2SharedBridge and if its legacy it returns Il2Bridge. - -#### Inputs - -| Parameter | Type | Description | -| --------------- |-----------| ------------------------------------------------- | -| `address` | 'Address' | The bridge address. | - -```ts -async connectL2Bridge(address: Address): Promise -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const l2Bridge = await provider.connectL2Bridge(""); -``` - -### `isL2BridgeLegacy` - -Returns true if passed bridge address is legacy and false if its shared bridge. - -#### Inputs - -| Parameter | Type | Description | -| --------------- |-----------| ------------------------------------------------- | -| `address` | 'Address' | The bridge address. | - -```ts -async isL2BridgeLegacy(address: Address): Promise -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const isBridgeLegacy = await provider.isL2BridgeLegacy(""); -console.log(isBridgeLegacy); -``` - ### `getDefaultProvider` Static method which returns a Provider object from the RPC URL or localhost. @@ -586,7 +563,7 @@ static getDefaultProvider(zksyncNetwork: ZkSyncNetwork = ZkSyncNetwork.Localhost ```ts import { Provider, types, utils } from "zksync-ethers"; - + const providerMainnet = Provider.getDefaultProvider(types.Network.Mainnet); const providerTestnet = Provider.getDefaultProvider(types.Network.Sepolia); const providerLocalnet = Provider.getDefaultProvider(types.Network.Localhost); @@ -607,7 +584,7 @@ async getFeeParams(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const feeParams = await provider.getFeeParams(); console.log(`Fee: ${utils.toJSON(feeParams)}`); @@ -632,7 +609,7 @@ async getFilterChanges(idx: BigNumber): Promise> ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const filter = await provider.newFilter({ address: utils.L2_ETH_TOKEN_ADDRESS, @@ -653,7 +630,7 @@ static override getFormatter(): Formatter ```ts import { Provider, types, utils } from "zksync-ethers"; - + const formatter = Provider.getFormatter(); ``` @@ -669,7 +646,7 @@ async getGasPrice(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Gas price: ${await provider.getGasPrice()}`); ``` @@ -695,7 +672,7 @@ async getL1BatchBlockRange(l1BatchNumber: number): Promise<[number, number] | nu ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const l1BatchNumber = await provider.getL1BatchNumber(); console.log(`L1 batch block range: ${utils.toJSON(await provider.getL1BatchBlockRange(l1BatchNumber))}`); @@ -721,7 +698,7 @@ async getL1BatchDetails(number: number): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const l1BatchNumber = await provider.getL1BatchNumber(); console.log(`L1 batch details: ${utils.toJSON(await provider.getL1BatchDetails(l1BatchNumber))}`); @@ -741,7 +718,7 @@ async getL1BatchNumber(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L1 batch number: ${await provider.getL1BatchNumber()}`); ``` @@ -764,7 +741,7 @@ async getL2TransactionFromPriorityOp(l1TxResponse: ethers.TransactionResponse): ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const l1Tx = "0xcca5411f3e514052f4a4ae1c2020badec6e0998adb52c09959c5f5ff15fba3a8"; @@ -795,7 +772,7 @@ async getLogProof(txHash: BytesLike, index ? : number): Promise L1 transaction can be used. // In this case, withdrawal transaction is used. @@ -822,7 +799,7 @@ getLogs(filter: Filter | FilterByBlockHash | Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Logs: ${utils.toJSON(await provider.getLogs({ fromBlock: 0, toBlock: 5, address: utils.L2_ETH_TOKEN_ADDRESS }))}`); ``` @@ -841,7 +818,7 @@ async getMainContractAddress(): Promise
```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Main contract: ${await provider.getMainContractAddress()}`); ``` @@ -870,7 +847,7 @@ async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); // Any L2 -> L1 transaction can be used. // In this case, withdrawal transaction is used. @@ -897,7 +874,7 @@ async getPriorityOpResponse(l1TxResponse: ethers.TransactionResponse): Promise

uint256) internal rawNonces; - + // Ensure the address is a 256-bit number by padding it // because rawNonces slot uses uint256 for mapping addresses and their nonces. const addressPadded = ethers.utils.hexZeroPad(wallet.address, 32); - + // Convert the slot number to a hex string and pad it to 32 bytes. const slotPadded = ethers.utils.hexZeroPad(ethers.utils.hexlify(0), 32); - + // Concatenate the padded address and slot number. const concatenated = addressPadded + slotPadded.slice(2); // slice to remove '0x' from the slotPadded - + // Hash the concatenated string using Keccak-256. const storageKey = ethers.utils.keccak256(concatenated); - + const l1BatchNumber = await provider.getL1BatchNumber(); const storageProof = await provider.getProof(utils.NONCE_HOLDER_ADDRESS, [storageKey], l1BatchNumber); console.log(`Storage proof: ${utils.toJSON(storageProof)}`); @@ -975,7 +952,7 @@ async getProtocolVersion(id?: number): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Protocol version: ${await provider.getProtocolVersion()}`); ``` @@ -1001,7 +978,7 @@ async getRawBlockTransactions(number: number): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Raw block transactions: ${utils.toJSON(await provider.getRawBlockTransactions(90_000))}`); ``` @@ -1019,7 +996,7 @@ async getTestnetPaymasterAddress(): Promise

```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`); ``` @@ -1043,12 +1020,12 @@ async getTransaction(hash: string | Promise): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const TX_HASH = ""; console.log(`Transaction details: ${utils.toJSON(await provider.getTransactionDetails(TX_HASH))}`); ``` @@ -1103,7 +1080,7 @@ async getTransactionReceipt(transactionHash: string | Promise): Promise< ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const TX_HASH = ""; console.log(`Transaction receipt: ${utils.toJSON(await provider.getTransactionReceipt(TX_HASH))}`); @@ -1127,9 +1104,9 @@ async getTransactionStatus(txHash: string): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const TX_HASH = ""; console.log(`Transaction status: ${utils.toJSON(await provider.getTransactionStatus(TX_HASH))}`); ``` @@ -1166,9 +1143,9 @@ Retrieve populated ETH transfer transaction. ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const tx = await provider.getTransferTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1182,11 +1159,11 @@ Retrieve populated ETH transfer transaction using paymaster to facilitate fee pa ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token - + const tx = await provider.getTransferTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1236,9 +1213,9 @@ Retrieve populated ETH withdrawal transactions. ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const tx = await provider.getWithdrawTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1252,11 +1229,11 @@ Retrieve populated ETH withdrawal transaction using paymaster to facilitate fee ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token - + const tx = await provider.getWithdrawTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1290,7 +1267,7 @@ async isBaseToken(token: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Is base token: ${await provider.isBaseToken("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` @@ -1307,11 +1284,35 @@ async isEthBasedChain(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Is ETH based chain: ${await provider.isEthBasedChain()}`); ``` +### `isL2BridgeLegacy` + +Returns true if passed bridge address is legacy and false if its shared bridge. + +#### Inputs + +| Parameter | Type | Description | +| --------------- |-----------| ------------------------------------------------- | +| `address` | 'Address' | The bridge address. | + +```ts +async isL2BridgeLegacy(address: Address): Promise +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const isBridgeLegacy = await provider.isL2BridgeLegacy(""); +console.log(isBridgeLegacy); +``` + ### `l1ChainId` Returns the chain id of the underlying L1. @@ -1326,7 +1327,7 @@ async l1ChainId(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L1 chain ID: ${await provider.l1ChainId()}`); ``` @@ -1354,7 +1355,7 @@ async l1TokenAddress(token: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L1 token address: ${await provider.l1TokenAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b")}`); ``` @@ -1383,7 +1384,7 @@ async l2TokenAddress(token: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L2 token address: ${await provider.l2TokenAddress("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` @@ -1401,7 +1402,7 @@ async newBlockFilter(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`New block filter: ${await provider.newBlockFilter()}`); ``` @@ -1426,7 +1427,7 @@ async newFilter(filter: EventFilter | Promise): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log( `New filter: ${await provider.newFilter({ @@ -1451,7 +1452,7 @@ async newPendingTransactionsFilter(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`New pending transaction filter: ${await provider.newPendingTransactionsFilter()}`); ``` @@ -1486,18 +1487,18 @@ async sendRawTransactionWithDetailedOutput(signedTx: string): Promise): Promise +override async estimateFee(transaction: TransactionRequest): Promise ``` #### Example ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -const TX_HASH = ""; -console.log(`Transaction receipt: ${utils.toJSON(await provider.getTransactionReceipt(TX_HASH))}`); +const fee = await provider.estimateFee({ + from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + to: "0xa61464658AfeAf65CccaaFD3 + +a512b69A83B77618", + value: BigNumber.from(7_000_000_000).toHexString(), +}); +console.log(`Fee: ${utils.toJSON(fee)}`); ``` -### `getTransaction` +### `estimateGasL1` -Returns the transaction for the specified `txHash`. +Estimates the amount of gas required to submit a transaction from L1 to L2. #### Inputs -| Parameter | Type | Description | -|-----------|----------|--------------------| -| `txHash` | `string` | The transaction hash. | +| Parameter | Type | Description | +|---------------|----------------------|-----------------------| +| `transaction` | `TransactionRequest` | The transaction request. | ```typescript -override async getTransaction(txHash: string): Promise +override async estimateGasL1(transaction: TransactionRequest): Promise ``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -const TX_HASH = ""; -const tx = await provider.getTransaction(TX_HASH); - -// Wait until the transaction is processed by the server. -await tx.wait(); -// Wait until the transaction is finalized. -await tx.waitFinalize(); +const gasL1 = await provider.estimateGasL1({ + from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + to: await provider.getMainContractAddress(), + value: 7_000_000_000, + customData: { + gasPerPubdata: 800, + }, +}); +console.log(`L1 gas: ${gasL1}`); ``` -### `getBlock` +### `getAllAccountBalances` -Returns the block for the specified `blockHashOrBlockTag`. +Returns all balances for confirmed tokens given by an account address. #### Inputs -| Parameter | Type | Description | -|----------------------|---------------------------------|-------------------------| -| `blockHashOrBlockTag`| `BlockTag` or `string` | The block hash or tag. | +| Parameter | Type | Description | +|-----------|-----------|---------------------------| +| `address` | `Address` | The account address. | ```typescript -override async getBlock(blockHashOrBlockTag: BlockTag | string | Promise): Promise +override async getAllAccountBalances(address: Address): Promise ``` #### Example ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -console.log(`Block: ${utils.toJSON(await provider.getBlock("latest", true))}`); +const balances = await provider.getAllAccountBalances("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); +console.log(`All balances: ${utils.toJSON(balances)}`); ``` -### `getBlockWithTransactions` +### `getBalance` -Returns the block for the specified `blockHashOrBlockTag`, including all transactions. +Returns the account balance for the specified `address`, `blockTag`, and `tokenAddress`. #### Inputs -| Parameter | Type | Description | -|----------------------|---------------------------------|-------------------------| -| `blockHashOrBlockTag`| `BlockTag` or `string` | The block hash or tag. | +| Parameter | Type | Description | +|-----------------|--------------|----------------------------------------------| +| `address` | `Address` | The account address. | +| `blockTag?` | `BlockTag` | Optional. The block tag for balance query. | +| `tokenAddress?` | `Address` | Optional. The token address. | ```typescript -override async getBlockWithTransactions(blockHashOrBlockTag: BlockTag | string | Promise): Promise +override async getBalance(address: Address, blockTag?: BlockTag, tokenAddress?: Address): Promise ``` #### Example ```typescript -import { Web3Provider, utils } from "zksync-ethers"; - +import { Web3Provider } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Block: ${utils.toJSON(await provider.getBlockWithTransactions("latest", true))}`); +const account = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"; +const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free +console.log(`ETH balance: ${await provider.getBalance(account)}`); +console.log(`Token balance: ${await provider.getBalance(account, "latest", tokenAddress)}`); ``` -### `getLogs` - -Returns the list of logs that match the specified `filter`. - -#### Inputs +### `getBaseTokenContractAddress` -| Parameter | Type | Description | -|-----------|-----------|--------------------| -| `filter` | `EventFilter` or `Promise` | The filter object. | +Returns the L1 base token address. ```typescript -override async getLogs(filter: EventFilter | Promise = {}): Promise> +override async getBaseTokenContractAddress(): Promise
``` #### Example ```typescript -import { Web3Provider, utils } from "zksync-ethers"; - +import { Web3Provider } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Logs: ${utils.toJSON(await provider.getLogs({ fromBlock: 0, toBlock: 5, address: utils.L2_ETH_TOKEN_ADDRESS }))}`); +console.log(`Base token: ${await provider.getBaseTokenContractAddress()}`); ``` -### `getBalance` +### `getBlock` -Returns the account balance for the specified `address`, `blockTag`, and `tokenAddress`. +Returns the block for the specified `blockHashOrBlockTag`. #### Inputs -| Parameter | Type | Description | -|-----------------|--------------|----------------------------------------------| -| `address` | `Address` | The account address. | -| `blockTag?` | `BlockTag` | Optional. The block tag for balance query. | -| `tokenAddress?` | `Address` | Optional. The token address. | +| Parameter | Type | Description | +|----------------------|---------------------------------|-------------------------| +| `blockHashOrBlockTag`| `BlockTag` or `string` | The block hash or tag. | ```typescript -override async getBalance(address: Address, blockTag?: BlockTag, tokenAddress?: Address): Promise +override async getBlock(blockHashOrBlockTag: BlockTag | string | Promise): Promise ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - +import { Web3Provider, utils } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -const account = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"; -const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free -console.log(`ETH balance: ${await provider.getBalance(account)}`); -console.log(`Token balance: ${await provider.getBalance(account, "latest", tokenAddress)}`); +console.log(`Block: ${utils.toJSON(await provider.getBlock("latest", true))}`); ``` -### `l2TokenAddress` +### `getBlockDetails` -Returns the L2 token address equivalent for an L1 token address. +Returns additional ZKsync-specific information about the L2 block. #### Inputs -| Parameter | Type | Description | -|-----------|-----------|----------------------------| -| `token` | `Address` | The address of the L1 token. | +| Parameter | Type | Description | +|-----------|---------|-----------------------| +| `number` | `number`| The block number. | ```typescript -override async l2TokenAddress(token: Address): Promise +override async getBlockDetails(number: number): Promise ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - -const provider = new Web3Provider(window.ethereum); -console.log(`L2 token address: ${await provider.l2TokenAddress("0x5C221E77624690fff6dd741493D735a17716c26B")}`); +import { Web3Provider, utils } from "zksync-ethers"; + +const provider = new Web3 + +Provider(window.ethereum); +console.log(`Block details: ${utils.toJSON(await provider.getBlockDetails(90_000))}`); ``` -### `l1TokenAddress` +### `getBlockWithTransactions` -Returns the L1 token address equivalent for an L2 token address. +Returns the block for the specified `blockHashOrBlockTag`, including all transactions. #### Inputs -| Parameter | Type | Description | -|-----------|-----------|----------------------------| -| `token` | `Address` | The address of the L2 token. | +| Parameter | Type | Description | +|----------------------|---------------------------------|-------------------------| +| `blockHashOrBlockTag`| `BlockTag` or `string` | The block hash or tag. | ```typescript -override async l1TokenAddress(token: Address): Promise +override async getBlockWithTransactions(blockHashOrBlockTag: BlockTag | string | Promise): Promise ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - +import { Web3Provider, utils } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`L1 token address: ${await provider.l1TokenAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b")}`); +console.log(`Block: ${utils.toJSON(await provider.getBlockWithTransactions("latest", true))}`); ``` -### `getProtocolVersion` - -Returns the protocol version. - -#### Inputs +### `getBridgehubContractAddress` -| Parameter | Type | Description | -|-----------|----------|---------------------------| -| `id?` | `number` | Optional. Specific version ID. | +Returns the Bridgehub smart contract address. ```typescript -override async getProtocolVersion(id?: number): Promise +override async getBridgehubContractAddress(): Promise
``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -console.log(`Protocol version: ${await provider.getProtocolVersion()}`); +console.log(`Bridgehub: ${await provider.getBridgehubContractAddress()}`); ``` -### `estimateGasL1` +### `getBytecodeByHash` -Estimates the amount of gas required to submit a transaction from L1 to L2. +Returns bytecode of a contract given by its hash. #### Inputs -| Parameter | Type | Description | -|---------------|----------------------|-----------------------| -| `transaction` | `TransactionRequest` | The transaction request. | +| Parameter | Type | Description | +|----------------|-------------|--------------------| +| `bytecodeHash` | `BytesLike` | The bytecode hash. | ```typescript -override async estimateGasL1(transaction: TransactionRequest): Promise +override async getBytecodeByHash(bytecodeHash: BytesLike): Promise ``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + +// Bytecode hash can be computed by following these steps: +// const testnetPaymasterBytecode = await provider.getCode(await provider.getTestnetPaymasterAddress()); +// const testnetPaymasterBytecodeHash = ethers.utils.hexlify(utils.hashBytecode(testnetPaymasterBytecode)); + +const testnetPaymasterBytecodeHash = "0x010000f16d2b10ddeb1c32f2c9d222eb1aea0f638ec94a81d4e916c627720e30"; + const provider = new Web3Provider(window.ethereum); -const gasL1 = await provider.estimateGasL1({ - from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", - to: await provider.getMainContractAddress(), - value: 7_000_000_000, - customData: { - gasPerPubdata: 800, - }, -}); -console.log(`L1 gas: ${gasL1}`); +console.log(`Bytecode: ${await provider.getBytecodeByHash(testnetPaymasterBytecodeHash)}`); ``` -### `estimateFee` +### `getConfirmedTokens` -Returns an estimated fee for the requested transaction. +Returns confirmed tokens. Confirmed token is any token bridged to ZKsync Era via the official bridge. #### Inputs -| Parameter | Type | Description | -|---------------|----------------------|-----------------------| -| `transaction` | `TransactionRequest` | The transaction request. | +| Parameter | Type | Description | +|-----------|---------|-------------------------------| +| `start?` | `number`| The token ID from which to start. Default is 0. | +| `limit?` | `number`| The maximum number of tokens to list. Default is 255. | ```typescript -override async estimateFee(transaction: TransactionRequest): Promise +override async getConfirmedTokens(start?: number, limit?: number): Promise ``` #### Example ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -const fee = await provider.estimateFee({ - from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", - to: "0xa61464658AfeAf65CccaaFD3 +const tokens = await provider.getConfirmedTokens(); +console.log(`Confirmed tokens: ${utils.toJSON(tokens)}`); +``` -a512b69A83B77618", - value: BigNumber.from(7_000_000_000).toHexString(), -}); -console.log(`Fee: ${utils.toJSON(fee)}`); +### `getDefaultBridgeAddresses` + +Returns the addresses of the default ZKsync Era bridge contracts on both L1 and L2. + +```typescript +override async getDefaultBridgeAddresses(): Promise<{ erc20L1: string; erc20L2: string; wethL1: string; wethL2: string; sharedL1: string; sharedL2: string; }> +``` + +#### Example + +```typescript +import { Web3Provider } from "zksync-ethers"; + +const provider = new Web3Provider(window.ethereum); +console.log(`Bridge addresses: ${await provider.getDefaultBridgeAddresses()}`); ``` ### `getFeeParams` @@ -322,7 +331,7 @@ override async getFeeParams(): Promise ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); const feeParams = await provider.getFeeParams(); console.log(`Fee: ${utils.toJSON(feeParams)}`); @@ -340,41 +349,14 @@ override async getGasPrice(): Promise ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); console.log(`Gas price: ${await provider.getGasPrice()}`); ``` -### `getLogProof` +### `getL1BatchBlockRange` -Returns the proof for a transaction's L2 to L1 log sent via the `L1Messenger` system contract. - -#### Inputs - -| Parameter | Type | Description | -|-----------|-------------|----------------------------------------------| -| `txHash` | `BytesLike` | Hash of the L2 transaction. | -| `index?` | `number` | Optional. Index of the L2 to L1 log in the transaction. | - -```typescript -override async getLogProof(txHash: BytesLike, index?: number): Promise -``` - -#### Example - -```typescript -import { Web3Provider, utils } from "zksync-ethers"; - -const provider = new Web3Provider(window.ethereum); -// Any L2 -> L1 transaction can be used. -// In this case, withdrawal transaction is used. -const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; -console.log(`Log ${utils.toJSON(await provider.getLogProof(tx, 0))}`); -``` - -### `getL1BatchBlockRange` - -Returns the range of blocks contained within a batch given by batch number. +Returns the range of blocks contained within a batch given by batch number. #### Inputs @@ -390,84 +372,101 @@ override async getL1BatchBlockRange(l1BatchNumber: number): Promise<[number, num ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); const l1BatchNumber = await provider.getL1BatchNumber(); console.log(`L1 batch block range: ${utils.toJSON(await provider.getL1BatchBlockRange(l1BatchNumber))}`); ``` -### `getBridgehubContractAddress` +### `getL1BatchDetails` -Returns the Bridgehub smart contract address. +Returns data pertaining to a given batch. + +#### Inputs + +| Parameter | Type | Description | +|-----------|---------|------------------------| +| `number` | `number`| The L1 batch number. | ```typescript -override async getBridgehubContractAddress(): Promise
+override async getL1BatchDetails(number: number): Promise ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - +import { Web3Provider, utils } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Bridgehub: ${await provider.getBridgehubContractAddress()}`); +const l1BatchNumber = await provider.getL1BatchNumber(); +console.log(`L1 batch details: ${utils.toJSON(await provider.getL1BatchDetails(l1BatchNumber))}`); ``` -### `getBaseTokenContractAddress` +### `getL1BatchNumber` -Returns the L1 base token address. +Returns the latest L1 batch number. ```typescript -override async getBaseTokenContractAddress(): Promise
+override async getL1BatchNumber(): Promise ``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -console.log(`Base token: ${await provider.getBaseTokenContractAddress()}`); +console.log(`L1 batch number: ${await provider.getL1BatchNumber()}`); ``` -### `isEthBasedChain` +### `getLogProof` -Returns whether the chain is ETH-based. +Returns the proof for a transaction's L2 to L1 log sent via the `L1Messenger` system contract. + +#### Inputs + +| Parameter | Type | Description | +|-----------|-------------|----------------------------------------------| +| `txHash` | `BytesLike` | Hash of the L2 transaction. | +| `index?` | `number` | Optional. Index of the L2 to L1 log in the transaction. | ```typescript -override async isEthBasedChain(): Promise +override async getLogProof(txHash: BytesLike, index?: number): Promise ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - +import { Web3Provider, utils } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Is ETH based chain: ${await provider.isEthBasedChain()}`); +// Any L2 -> L1 transaction can be used. +// In this case, withdrawal transaction is used. +const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; +console.log(`Log ${utils.toJSON(await provider.getLogProof(tx, 0))}`); ``` -### `isBaseToken` +### `getLogs` -Returns whether the `token` is the base token. +Returns the list of logs that match the specified `filter`. #### Inputs -| Parameter | Type | Description | -|-----------|-----------|----------------------------| -| `token` | `Address` | The address of the token. | +| Parameter | Type | Description | +|-----------|-----------|--------------------| +| `filter` | `EventFilter` or `Promise` | The filter object. | ```typescript -override async isBaseToken(token: Address): Promise +override async getLogs(filter: EventFilter | Promise = {}): Promise> ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - +import { Web3Provider, utils } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Is base token: ${await provider.isBaseToken("0x5C221E77624690fff6dd741493D735a17716c26B")}`); +console.log(`Logs: ${utils.toJSON(await provider.getLogs({ fromBlock: 0, toBlock: 5, address: utils.L2_ETH_TOKEN_ADDRESS }))}`); ``` ### `getMainContractAddress` @@ -482,296 +481,324 @@ override async getMainContractAddress(): Promise
```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); console.log(`Main contract: ${await provider.getMainContractAddress()}`); ``` -### `getTestnetPaymasterAddress` +### `getProof` -Returns the testnet paymaster address, if available. +Returns Merkle proofs for one or more storage values at the specified account along with a Merkle proof of their authenticity. + +#### Inputs + +| Parameter | Type | Description | +|-----------------|--------------|----------------------------------------------| +| `address` | `Address` | The account to fetch storage values and proofs for. | +| `keys` | `string[]` | Vector of storage keys in the account. | +| `l1BatchNumber` | `number` | The L1 batch number. | ```typescript -override async getTestnetPaymasterAddress(): Promise
+override async getProof(address: Address, keys: string[], l1BatchNumber: number): Promise ``` #### Example ```typescript -import { Web3Provider } from "zksync-ethers"; - +import { Web3Provider, utils } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`); +const address = "0x082b1BB53fE43810f646dDd71AA2AB201b4C6b04"; + +// Fetching the storage proof for rawNonces storage slot in NonceHolder system contract. +// mapping(uint256 => uint256) internal rawNonces; + +// Ensure the address is a 256-bit number by padding it +// because rawNonces slot uses uint256 for mapping addresses and their nonces. +const addressPadded = ethers.utils.hexZeroPad(address, 32); + +// Convert the slot number to a hex string and pad it to 32 bytes. +const slotPadded = ethers.utils.hexZeroPad(ethers.utils.hexlify(0), 32); + +// Concatenate the padded address and slot number. +const concatenated = addressPadded + slotPadded.slice(2); // slice to remove '0x' from the slotPadded + +// Hash the concatenated string using Keccak-256. +const storageKey = ethers.utils.keccak256(concatenated); + +const l1BatchNumber = await provider.getL1BatchNumber(); +const storageProof = await provider.getProof(utils.NONCE_HOLDER_ADDRESS, [storageKey], l1BatchNumber); +console.log(`Storage proof: ${utils.toJSON(storageProof)}`); ``` -### `getDefaultBridgeAddresses` +### `getProtocolVersion` -Returns the addresses of the default ZKsync Era bridge contracts on both L1 and L2. +Returns the protocol version. + +#### Inputs + +| Parameter | Type | Description | +|-----------|----------|---------------------------| +| `id?` | `number` | Optional. Specific version ID. | ```typescript -override async getDefaultBridgeAddresses(): Promise<{ erc20L1: string; erc20L2: string; wethL1: string; wethL2: string; sharedL1: string; sharedL2: string; }> +override async getProtocolVersion(id?: number): Promise ``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -console.log(`Bridge addresses: ${await provider.getDefaultBridgeAddresses()}`); +console.log(`Protocol version: ${await provider.getProtocolVersion()}`); ``` -### `getAllAccountBalances` +### `getRawBlockTransactions` -Returns all balances for confirmed tokens given by an account address. +Returns data of transactions in a block. #### Inputs -| Parameter | Type | Description | -|-----------|-----------|---------------------------| -| `address` | `Address` | The account address. | +| Parameter | Type | Description | +|-----------|---------|-------------------| +| `number` | `number`| The block number. | ```typescript -override async getAllAccountBalances(address: Address): Promise +override async getRawBlockTransactions(number: number): Promise ``` #### Example ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -const balances = await provider.getAllAccountBalances("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); -console.log(`All balances: ${utils.toJSON(balances)}`); +console.log(`Raw block transactions: ${utils.toJSON(await provider.getRawBlockTransactions(90_000))}`); ``` -### `getConfirmedTokens` +### `getSigner` -Returns confirmed tokens. Confirmed token is any token bridged to ZKsync Era via the official bridge. +Returns a `JsonRpcSigner` instance for the specified `addressOrIndex`. This is used to sign transactions and +messages using the connected wallet. #### Inputs -| Parameter | Type | Description | -|-----------|---------|-------------------------------| -| `start?` | `number`| Optional. The token ID from which to start. Default is 0. | -| `limit?` | `number`| Optional. The maximum number of tokens to list. Default is 255. | +| Parameter | Type | Description | +|------------------|-----------------------|----------------------------------| +| `addressOrIndex?`| `string` or `number` | Optional. The address or index. | ```typescript -override async getConfirmedTokens(start?: number, limit?: number): Promise +getSigner(addressOrIndex?: string | number): JsonRpcSigner ``` #### Example ```typescript -import { Web3Provider, utils } from "zksync-ethers"; - +import { Web3Provider } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -const tokens = await provider.getConfirmedTokens(); -console.log(`Confirmed tokens: ${utils.toJSON(tokens)}`); +const signer = provider.getSigner(); +const message = "Hello, ZKsync!"; +const signature = await signer.signMessage(message); +console.log(`Signature: ${signature}`); ``` -### `l1ChainId` +### `getTestnetPaymasterAddress` -Returns the L1 chain ID. +Returns the testnet paymaster address, if available. ```typescript -override async l1ChainId(): Promise +override async getTestnetPaymasterAddress(): Promise
``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -console.log(`L1 chain ID: ${await provider.l1ChainId()}`); +console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`); ``` -### `getL1BatchNumber` +### `getTransaction` -Returns the latest L1 batch number. +Returns the transaction for the specified `txHash`. + +#### Inputs + +| Parameter | Type | Description | +|-----------|----------|--------------------| +| `txHash` | `string` | The transaction hash. | ```typescript -override async getL1BatchNumber(): Promise +override async getTransaction(txHash: string): Promise ``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -console.log(`L1 batch number: ${await provider.getL1BatchNumber()}`); +const TX_HASH = ""; +const tx = await provider.getTransaction(TX_HASH); + +// Wait until the transaction is processed by the server. +await tx.wait(); +// Wait until the transaction is finalized. +await tx.waitFinalize(); ``` -### `getL1BatchDetails` +### `getTransactionDetails` -Returns data pertaining to a given batch. +Returns data from a specific transaction given by the transaction hash. #### Inputs -| Parameter | Type | Description | -|-----------|---------|------------------------| -| `number` | `number`| The L1 batch number. | +| Parameter | Type | Description | +|-----------|-------------|--------------------| +| `txHash` | `BytesLike` | The transaction hash. | ```typescript -override async getL1BatchDetails(number: number): Promise +override async getTransactionDetails(txHash: BytesLike): Promise ``` #### Example ```typescript import { Web3Provider, utils } from "zksync-ethers"; - + const provider = new Web3Provider(window.ethereum); -const l1BatchNumber = await provider.getL1BatchNumber(); -console.log(`L1 batch details: ${utils.toJSON(await provider.getL1BatchDetails(l1BatchNumber))}`); +const TX_HASH = ""; +console.log(`Transaction details: ${utils.toJSON(await provider.getTransactionDetails(TX_HASH))}`); ``` -### `getBlockDetails` +### `getTransactionReceipt` -Returns additional ZKsync-specific information about the L2 block. +Returns the transaction receipt for the specified `txHash`, if mined. #### Inputs -| Parameter | Type | Description | -|-----------|---------|-----------------------| -| `number` | `number`| The block number. | +| Parameter | Type | Description | +|-----------|----------|--------------------| +| `txHash` | `string` | The transaction hash. | ```typescript -override async getBlockDetails(number: number): Promise +override async getTransactionReceipt(txHash: string): Promise ``` #### Example ```typescript import { Web3Provider, utils } from "zksync-ethers"; - -const provider = new Web3 - -Provider(window.ethereum); -console.log(`Block details: ${utils.toJSON(await provider.getBlockDetails(90_000))}`); + +const provider = new Web3Provider(window.ethereum); +const TX_HASH = ""; +console.log(`Transaction receipt: ${utils.toJSON(await provider.getTransactionReceipt(TX_HASH))}`); ``` -### `getTransactionDetails` +### `isBaseToken` -Returns data from a specific transaction given by the transaction hash. +Returns whether the `token` is the base token. #### Inputs -| Parameter | Type | Description | -|-----------|-------------|--------------------| -| `txHash` | `BytesLike` | The transaction hash. | +| Parameter | Type | Description | +|-----------|-----------|----------------------------| +| `token` | `Address` | The address of the token. | ```typescript -override async getTransactionDetails(txHash: BytesLike): Promise +override async isBaseToken(token: Address): Promise ``` #### Example ```typescript -import { Web3Provider, utils } from "zksync-ethers"; - +import { Web3Provider } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -const TX_HASH = ""; -console.log(`Transaction details: ${utils.toJSON(await provider.getTransactionDetails(TX_HASH))}`); +console.log(`Is base token: ${await provider.isBaseToken("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` -### `getBytecodeByHash` - -Returns bytecode of a contract given by its hash. - -#### Inputs +### `isEthBasedChain` -| Parameter | Type | Description | -|----------------|-------------|--------------------| -| `bytecodeHash` | `BytesLike` | The bytecode hash. | +Returns whether the chain is ETH-based. ```typescript -override async getBytecodeByHash(bytecodeHash: BytesLike): Promise +override async isEthBasedChain(): Promise ``` #### Example ```typescript import { Web3Provider } from "zksync-ethers"; - -// Bytecode hash can be computed by following these steps: -// const testnetPaymasterBytecode = await provider.getCode(await provider.getTestnetPaymasterAddress()); -// const testnetPaymasterBytecodeHash = ethers.utils.hexlify(utils.hashBytecode(testnetPaymasterBytecode)); - -const testnetPaymasterBytecodeHash = "0x010000f16d2b10ddeb1c32f2c9d222eb1aea0f638ec94a81d4e916c627720e30"; - + const provider = new Web3Provider(window.ethereum); -console.log(`Bytecode: ${await provider.getBytecodeByHash(testnetPaymasterBytecodeHash)}`); +console.log(`Is ETH based chain: ${await provider.isEthBasedChain()}`); ``` -### `getRawBlockTransactions` - -Returns data of transactions in a block. - -#### Inputs +### `l1ChainId` -| Parameter | Type | Description | -|-----------|---------|-------------------| -| `number` | `number`| The block number. | +Returns the L1 chain ID. ```typescript -override async getRawBlockTransactions(number: number): Promise +override async l1ChainId(): Promise ``` #### Example ```typescript -import { Web3Provider, utils } from "zksync-ethers"; - +import { Web3Provider } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -console.log(`Raw block transactions: ${utils.toJSON(await provider.getRawBlockTransactions(90_000))}`); +console.log(`L1 chain ID: ${await provider.l1ChainId()}`); ``` -### `getProof` +### `l1TokenAddress` -Returns Merkle proofs for one or more storage values at the specified account along with a Merkle proof of their authenticity. +Returns the L1 token address equivalent for an L2 token address. #### Inputs -| Parameter | Type | Description | -|-----------------|--------------|----------------------------------------------| -| `address` | `Address` | The account to fetch storage values and proofs for. | -| `keys` | `string[]` | Vector of storage keys in the account. | -| `l1BatchNumber` | `number` | The L1 batch number. | +| Parameter | Type | Description | +|-----------|-----------|----------------------------| +| `token` | `Address` | The address of the L2 token. | ```typescript -override async getProof(address: Address, keys: string[], l1BatchNumber: number): Promise +override async l1TokenAddress(token: Address): Promise ``` #### Example ```typescript -import { Web3Provider, utils } from "zksync-ethers"; - +import { Web3Provider } from "zksync-ethers"; + const provider = new Web3Provider(window.ethereum); -const address = "0x082b1BB53fE43810f646dDd71AA2AB201b4C6b04"; +console.log(`L1 token address: ${await provider.l1TokenAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b")}`); +``` -// Fetching the storage proof for rawNonces storage slot in NonceHolder system contract. -// mapping(uint256 => uint256) internal rawNonces; +### `l2TokenAddress` -// Ensure the address is a 256-bit number by padding it -// because rawNonces slot uses uint256 for mapping addresses and their nonces. -const addressPadded = ethers.utils.hexZeroPad(address, 32); +Returns the L2 token address equivalent for an L1 token address. -// Convert the slot number to a hex string and pad it to 32 bytes. -const slotPadded = ethers.utils.hexZeroPad(ethers.utils.hexlify(0), 32); +#### Inputs -// Concatenate the padded address and slot number. -const concatenated = addressPadded + slotPadded.slice(2); // slice to remove '0x' from the slotPadded +| Parameter | Type | Description | +|-----------|-----------|----------------------------| +| `token` | `Address` | The address of the L1 token. | -// Hash the concatenated string using Keccak-256. -const storageKey = ethers.utils.keccak256(concatenated); +```typescript +override async l2TokenAddress(token: Address): Promise +``` -const l1BatchNumber = await provider.getL1BatchNumber(); -const storageProof = await provider.getProof(utils.NONCE_HOLDER_ADDRESS, [storageKey], l1BatchNumber); -console.log(`Storage proof: ${utils.toJSON(storageProof)}`); +#### Example + +```typescript +import { Web3Provider } from "zksync-ethers"; + +const provider = new Web3Provider(window.ethereum); +console.log(`L2 token address: ${await provider.l2TokenAddress("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` ### `sendRawTransactionWithDetailedOutput` @@ -793,14 +820,14 @@ override async sendRawTransactionWithDetailedOutput(signedTx: string): Promise ``` #### Example @@ -29,87 +30,49 @@ The constructor initializes a wallet instance using a private key, and optionall ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 txHandle = await wallet.approveERC20(tokenL1, "10000000"); + +await txHandle.wait(); ``` -### `fromMnemonic` - -Creates a `Wallet` with the `provider` as L1 provider and a private key that is built from the `mnemonic` passphrase. - -#### Inputs - -| Parameter | Type | Description | -| ----------- | ------------------ | ----------------------------------------------------------------------- | -| `mnemonic` | `string` | The mnemonic of the private key. | -| `path?` | `string` | If path is not specified, the Ethereum default path is used. | -| `wordlist?` | `ethers.Worldlist` | If wordlist is not specified, the English Wordlist is used. | - -```ts -static fromMnemonic(mnemonic: string, path?: string, wordlist?: ethers.Wordlist) -``` - -#### Example - -```ts -import { Wallet } from "zksync-ethers"; - -const MNEMONIC = "stuff slice staff easily soup parent arm payment cotton hammer scatter struggle"; - -const wallet = Wallet.fromMnemonic(MNEMONIC); -``` - -### `fromEncryptedJson` +### `claimFailedDeposit` -Creates a `Wallet` from encrypted `json` file using provided `password`. +The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. +If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` +method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. #### Inputs -| Parameter | Type | Description | -| ----------- | -------------------------- | -------------------------------------------------------------------------------------------------------------- | -| `json` | `string` | Encrypted json file. | -| `password` | `string` or `ethers.Bytes` | Password for encrypted json file. | -| `callback?` | `ProgressCallback` | If callback is provided, it is called periodically during decryption so that any UI can be updated. | +| Parameter | Type | Description | +| ----------- | --------- | ---------------------------------------------- | +| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | ```ts -static async fromEncryptedJsonSync(json: string, password?: string | ethers.Bytes) +async claimFailedDeposit(depositHash: BytesLike): Promise ``` #### Example ```ts import { Wallet, Provider, utils } from "zksync-ethers"; -import * as fs from "fs"; - -const wallet = await Wallet.fromEncryptedJson(fs.readFileSync("wallet.json", "utf8"), "password"); -``` - -### `fromEncryptedJsonSync` - -Creates a `Wallet` from encrypted `json` file using provided `password`. - -#### Inputs - -| Parameter | Type | Description | -| ---------- | -------------------------- | --------------------------------- | -| `json` | `string` | Encrypted json file. | -| `password` | `string` or `ethers.Bytes` | Password for encrypted json file. | - -```ts -static fromEncryptedJsonSync(json: string, password?: string | ethers.Bytes) -``` - -#### Example - -```ts -import { Wallet } from "zksync-ethers"; -import * as fs from "fs"; - -const wallet = Wallet.fromEncryptedJsonSync(fs.readFileSync("tests/files/wallet.json", "utf8"), "password"); +import { ethers } from "ethers"; + +const 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 = ""; +const claimFailedDepositHandle = await wallet.claimFailedDeposit(FAILED_DEPOSIT_HASH); ``` ### `connect` @@ -131,10 +94,10 @@ Wallet.connect(provider:Provider): Wallet ```ts import { Wallet, Provider, types } from "zksync-ethers"; - + const PRIVATE_KEY = ""; const unconnectedWallet = new Wallet(PRIVATE_KEY); - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const wallet = unconnectedWallet.connect(provider); ``` @@ -168,10 +131,10 @@ Wallet.connectToL1(provider: ethers.Provider): Wallet ```ts import { Wallet } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; const unconnectedWallet = new Wallet(PRIVATE_KEY); - + const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = unconnectedWallet.connectToL1(ethProvider); ``` @@ -182,12 +145,22 @@ It is possible to chain `connect` and `connectToL1` methods: const wallet = unconnectedWallet.connect(zkSyncProvider).connectToL1(ethProvider); ``` -### `getMainContract` +### `constructor` -Returns `Contract` wrapper of the ZKsync smart contract. +The constructor initializes a wallet instance using a private key, and optionally connects it to L1 and L2 providers. + +#### Inputs + +| Parameter | Type | Description | +| ------------- |-----------------------------------------------------------------------------------------------| ---------------------------------------------------------------------- | +| `privateKey` | `BytesLike` or [`ethers.utils.SigningKey`](https://docs.ethers.org/v5/api/utils/signing-key/#SigningKey) | The private key of the Ethereum account. | +| `providerL2?` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | A ZKsync node provider. Needed for interaction with ZKsync. | +| `providerL1?` | [`ethers.providers.Provider`](https://docs.ethers.org/v5/api/providers/provider/#Provider) | An Ethereum node provider. Needed for interaction with L1. | ```ts -async getMainContract(): Promise + constructor (privateKey: ethers.utils.BytesLike | ethers.utils.SigningKey, + providerL2?: Provider, + providerL1?: ethers.providers.Provider) ``` #### Example @@ -195,129 +168,215 @@ async getMainContract(): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - -console.log(`Main contract: ${await wallet.getMainContract()}`); ``` -### `getBridgehubContract` +### `deposit` -Returns `Contract` wrapper of the Bridgehub smart contract. +Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. +The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the +specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). +In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` +can be enabled to perform token approval. +If there are already enough approved tokens for the L1 bridge, token approval will be skipped. +To check the amount of approved tokens for a specific bridge, use +the [`allowanceL1`](#getallowancel1) method. + +#### Inputs + +| Parameter | Type | Description | +|-------------------------------------| ------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveBaseOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | ```ts -async getBridgehubContract(): Promise +async deposit(transaction: { + token: Address; + amount: BigNumberish; + to?: Address; + operatorTip?: BigNumberish; + bridgeAddress?: Address; + approveERC20?: boolean; + approveBaseERC20?: boolean; + l2GasLimit?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.PayableOverrides; + approveOverrides?: ethers.Overrides; + approveBaseOverrides?: ethers.Overrides; + customBridgeData?: BytesLike; +}): Promise ``` #### Example +Deposit ETH on ETH-based chain. + ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); -``` - -### `getL1BridgeContracts` - -Returns L1 bridge contracts. - -```ts -async getL1BridgeContracts(): Promise<{ - erc20: IL1ERC20Bridge; - weth: IL1ERC20Bridge; - shared: IL1SharedBridge; -}> + +const depositTx = await wallet.deposit({ + token: utils.ETH_ADDRESS, + amount: 10_000_000, +}); +// 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. ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); -``` - -### `getL2BridgeContracts` - -Returns L2 bridge contracts. - -```ts -async getL2BridgeContracts(): Promise<{ - erc20: IL2Bridge; - weth: IL2Bridge; - shared: IL2Bridge; -}> + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +const depositTx = await wallet.deposit({ + token: tokenL1, + amount: 10_000_000, + 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. ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); + +const depositTx = await wallet.deposit({ + token: utils.ETH_ADDRESS, + amount: 10_000_000, + 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(); ``` -### `getAddress` - -Returns the wallet address. +Deposit base token on non-ETH-based chain. ```ts -async getAddress(): Promise
; -``` - -#### Example +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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_000, + 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(); +``` + +Deposit non-base token on non-ETH-based chain. ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - -console.log(`Address: ${await wallet.getAddress()}`); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +const depositTx = await wallet.deposit({ + token: tokenL1, + amount: 10_000_000, + 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(); ``` -### `getBalance` +### `estimateGasDeposit` -Returns the amount of the token the `Wallet` has. +Estimates the amount of gas required for a deposit transaction on L1 network. +Gas of approving ERC20 token is not included in estimation. #### Inputs -| Parameter | Type | Description | -| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | -| `token?` | `Address` | The address of the token. ETH by default. | -| `blockTag` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Parameter | Type | Description | +| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +async estimateGasDeposit(transaction: + token: Address; + amount: BigNumberish; + to?: Address; + operatorTip?: BigNumberish; + bridgeAddress?: Address; + customBridgeData?: BytesLike; + l2GasLimit?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.PayableOverrides; + }): Promise ``` #### Example @@ -325,31 +384,53 @@ async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +async estimateGasRequestExecute(transaction: { + contractAddress: Address; + calldata: BytesLike; + l2GasLimit?: BigNumberish; + mintValue?: BigNumberish; + l2Value?: BigNumberish; + factoryDeps?: BytesLike[]; + operatorTip?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.PayableOverrides; +}): Promise ``` #### Example @@ -357,24 +438,57 @@ async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - +const CONTRACT_ADDRESS = ""; + 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)}`); + +const gasPrice = await wallet.providerL1.getGasPrice(); + +// The calldata can be encoded the same way as for Ethereum. +// Here is an example of how to get the calldata from an ABI: +const abi = [ + { + inputs: [], + name: "increment", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; +const contractInterface = new ethers.utils.Interface(abi); +const calldata = contractInterface.encodeFunctionData("increment", []); +const l2GasLimit = BigNumber.from(1000); + +const txCostPrice = await wallet.getBaseCost({ + gasPrice, + calldataLength: ethers.utils.arrayify(calldata).length, + l2GasLimit, +}); + +console.log(`Executing the transaction will cost ${ethers.utils.formatEther(txCostPrice)} ETH`); + +const executeTx = await wallet.getRequestExecuteTx({ + contractAddress: CONTRACT_ADDRESS, + calldata, + l2Value: 1, + l2GasLimit, + overrides: { + gasPrice, + value: txCostPrice, + }, +}); ``` -### `getAllBalances` +### `ethWallet` -Returns all balances for confirmed tokens given by an account address. +You can get an `ethers.Wallet` object with the same private key with `ethWallet()` method. ```ts -async getAllBalances(): Promise +ethWallet(): ethers.Wallet ``` #### Example @@ -382,28 +496,29 @@ async getAllBalances(): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); + +const ethWallet = wallet.ethWallet(); ``` -### `getNonce` +### `finalizeWithdrawal` -Returns account's nonce number. +Proves the inclusion of the L2 -> L1 withdrawal message. #### Inputs -| Parameter | Type | Description | -| ----------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Name | Type | Description | +| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | ```ts -async getNonce(blockTag?: BlockTag): Promise +async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -411,22 +526,31 @@ async getNonce(blockTag?: BlockTag): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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.getNonce()}`); + +const WITHDRAWAL_HASH = ""; +const finalizeWithdrawHandle = await wallet.finalizeWithdrawal(WITHDRAWAL_HASH); ``` -### `getDeploymentNonce` +### `finalizeWithdrawalParams` -Returns account's deployment nonce number. +Returns the [parameters](/sdk/js/ethers/api/v5/types#finalizewithdrawalparams) required for finalizing a withdrawal +from the withdrawal transaction's log on the L1 network. + +#### Inputs + +| Name | Type | Description | +| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | ```ts -async getDeploymentNonce(): Promise +async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -434,87 +558,98 @@ async getDeploymentNonce(): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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()}`); + +const WITHDRAWAL_HASH = ""; +const params = await wallet.finalizeWithdrawalParams(WITHDRAWAL_HASH); ``` -### `ethWallet` +### `fromEncryptedJson` -You can get an `ethers.Wallet` object with the same private key with `ethWallet()` method. +Creates a `Wallet` from encrypted `json` file using provided `password`. + +#### Inputs + +| Parameter | Type | Description | +| ----------- | -------------------------- | -------------------------------------------------------------------------------------------------------------- | +| `json` | `string` | Encrypted json file. | +| `password` | `string` or `ethers.Bytes` | Password for encrypted json file. | +| `callback?` | `ProgressCallback` | If callback is provided, it is called periodically during decryption so that any UI can be updated. | ```ts -ethWallet(): ethers.Wallet +static async fromEncryptedJsonSync(json: string, password?: string | ethers.Bytes) ``` #### Example ```ts import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); +import * as fs from "fs"; + +const wallet = await Wallet.fromEncryptedJson(fs.readFileSync("wallet.json", "utf8"), "password"); ``` -### `l2TokenAddress` - -Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. +### `fromEncryptedJsonSync` -::callout{icon="i-heroicons-exclamation-triangle" color="amber"} -Only works for tokens bridged on default ZKsync Era bridges. -:: +Creates a `Wallet` from encrypted `json` file using provided `password`. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ------------------------------- | -| `token` | `Address` | The address of the token on L1. | +| Parameter | Type | Description | +| ---------- | -------------------------- | --------------------------------- | +| `json` | `string` | Encrypted json file. | +| `password` | `string` or `ethers.Bytes` | Password for encrypted json file. | ```ts -async l2TokenAddress(token: Address): Promise +static fromEncryptedJsonSync(json: string, password?: string | ethers.Bytes) ``` #### Example ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; +import { Wallet } from "zksync-ethers"; +import * as fs from "fs"; + +const wallet = Wallet.fromEncryptedJsonSync(fs.readFileSync("tests/files/wallet.json", "utf8"), "password"); +``` -const PRIVATE_KEY = ""; +### `fromMnemonic` -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const ethProvider = ethers.getDefaultProvider("sepolia"); -const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); +Creates a `Wallet` with the `provider` as L1 provider and a private key that is built from the `mnemonic` passphrase. -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +#### Inputs -console.log(`Token L2 address: ${await wallet.l2TokenAddress(tokenL1)}`); +| Parameter | Type | Description | +| ----------- | ------------------ | ----------------------------------------------------------------------- | +| `mnemonic` | `string` | The mnemonic of the private key. | +| `path?` | `string` | If path is not specified, the Ethereum default path is used. | +| `wordlist?` | `ethers.Worldlist` | If wordlist is not specified, the English Wordlist is used. | + +```ts +static fromMnemonic(mnemonic: string, path?: string, wordlist?: ethers.Wordlist) ``` -### `populateTransaction` +#### Example -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. +```ts +import { Wallet } from "zksync-ethers"; + +const MNEMONIC = "stuff slice staff easily soup parent arm payment cotton hammer scatter struggle"; + +const wallet = Wallet.fromMnemonic(MNEMONIC); +``` -| Parameter | Type | Description | -| ------------- | ----------------------------------------------------- | -------------------- | -| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | Transaction request. | +### `getAddress` + +Returns the wallet address. ```ts -async populateTransaction(transaction: TransactionRequest): Promise +async getAddress(): Promise
; ``` #### Example @@ -522,34 +657,57 @@ async populateTransaction(transaction: TransactionRequest): Promise ``` -### `signTransaction` +#### Example -Signs the transaction and serializes it to be ready to be broadcast to the network. -Throws an error when `transaction.from` is mismatched from the private key. +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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(); +``` + +### `getAllowanceL1` + +Returns the amount of approved tokens for a specific L1 bridge. #### Inputs -| Parameter | Type | Description | -| ------------- | ----------------------------------------------------- | -------------------- | -| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | Transaction request. | +| Parameter | Type | Description | +| ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `token` | `Address` | The Ethereum address of the token. | +| `bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge, either `L1EthBridge` or `L1Erc20Bridge`. | +| `blockTag?` | `BlockTag` | In which block an allowance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async signTransaction(transaction: TransactionRequest): Promise +async getAllowanceL1( + token: Address, + bridgeAddress?: Address, + blockTag?: ethers.BlockTag +): Promise ``` #### Example @@ -557,35 +715,30 @@ async signTransaction(transaction: TransactionRequest): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); -const wallet = new Wallet(PRIVATE_KEY, provider); - -const recipient = Wallet.createRandom(); - -const tx = await wallet.signTransaction({ - type: utils.EIP712_TX_TYPE, - to: recipient.address, - value: ethers.utils.parseEther("1"), -}); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +console.log(`Token allowance: ${await wallet.getAllowanceL1(tokenL1)}`); ``` -### `sendTransaction` +### `getBalance` -Broadcast the transaction to the network. -Throws an error when `tx.from` is mismatched from the private key. +Returns the amount of the token the `Wallet` has. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------------------- | -------------------- | -| `tx` | `ethers.providers.TransactionRequest` | Transaction request. | +| Parameter | Type | Description | +| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | +| `token?` | `Address` | The address of the token. ETH by default. | +| `blockTag` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async sendTransaction(tx: ethers.providers.TransactionRequest): Promise +async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise ``` #### Example @@ -593,244 +746,137 @@ async sendTransaction(tx: ethers.providers.TransactionRequest): Promise +async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise ``` -#### Examples - -Transfer ETH. +#### Example ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const wallet = new Wallet(PRIVATE_KEY, provider); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; + +console.log(`Token balance: ${await wallet.getBalanceL1(tokenL1)}`); +``` -const transferTx = await wallet.transfer({ - to: Wallet.createRandom().address, - amount: ethers.utils.parseEther("0.01"), -}); +### `getBaseCost` -const receipt = await transferHandle.wait(); +Returns base cost for L2 transaction. -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); +#### Inputs + +| Name | Type | Description | +| --------------------------- | -------------- | ------------------------------------------------------------------------------------------------- | +| `params.gasLimit` | `BigNumberish` | The `gasLimit` for the L2 contract call. | +| `params.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | +| `params.gasPrice?` | `BigNumberish` | The L1 gas price of the L1 transaction that will send the request for an execute call. | + +```ts +async getBaseCost(params: { + gasLimit: BigNumberish; + gasPerPubdataByte?: BigNumberish; + gasPrice?: BigNumberish; +}): Promise ``` -Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. +#### Example ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +console.log(`Base cost: ${await wallet.getBaseCost({ gasLimit: 100_000 })}`); +``` -const transferTx = await wallet.transfer({ - to: Wallet.createRandom().address, - amount: ethers.utils.parseEther("0.01"), - paymasterParams: utils.getPaymasterParams(paymaster, { - type: "ApprovalBased", - token: token, - minimalAllowance: 1, - innerInput: new Uint8Array(), - }), -}); +### `getBaseToken` -const receipt = await transferTx.wait(); +Returns the address of the base token on L1. -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); +```ts +async getBaseToken(): Promise ``` -Transfer token. +#### Example ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const wallet = new Wallet(PRIVATE_KEY, provider); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +console.log(`Base token: ${await wallet.getBaseToken()}`); +``` -const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; -const transferTx = await wallet.transfer({ - token: tokenL2, - to: Wallet.createRandom().address, - amount: ethers.utils.parseEther("0.01"), -}); +### `getBridgehubContract` -const receipt = await transferHandle.wait(); +Returns `Contract` wrapper of the Bridgehub smart contract. -console.log(`The sum of ${receipt.value} token was transferred to ${receipt.to}`); +```ts +async getBridgehubContract(): Promise ``` -Transfer token using paymaster to facilitate fee payment with an ERC20 token. +#### Example ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const bridgehub = await wallet.getBridgehubContract(); +``` -const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; -const transferTx = await wallet.transfer({ - token: tokenL2, - to: Wallet.createRandom().address, - amount: ethers.utils.parseEther("0.01"), - paymasterParams: utils.getPaymasterParams(paymaster, { - type: "ApprovalBased", - token: token, - minimalAllowance: 1, - innerInput: new Uint8Array(), - }), -}); +### `getDeploymentNonce` -const receipt = await transferTx.wait(); +Returns account's deployment nonce number. -console.log(`The sum of ${receipt.value} token was transferred to ${receipt.to}`); -``` - -### `getAllowanceL1` - -Returns the amount of approved tokens for a specific L1 bridge. - -#### Inputs - -| Parameter | Type | Description | -| ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -| `token` | `Address` | The Ethereum address of the token. | -| `bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge, either `L1EthBridge` or `L1Erc20Bridge`. | -| `blockTag?` | `BlockTag` | In which block an allowance should be checked on. `committed`, i.e. the latest processed one is the default option. | - -```ts -async getAllowanceL1( - token: Address, - bridgeAddress?: Address, - blockTag?: ethers.BlockTag -): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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)}`); -``` - -### `approveERC20` - -Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. - -#### Inputs - -| Parameter | Type | Description | -| ------------ | ------------------- | ----------------------------------------------------------------------------------------------------- | -| `token` | `Address` | The Ethereum address of the token. | -| `amount` | `BigNumberish` | The amount of the token to be approved. | -| `overrides?` | `ethers.Overrides?` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | - -```ts -async approveERC20( - token: Address, - amount: BigNumberish, - overrides?: ethers.Overrides & { bridgeAddress?: Address } -): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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 txHandle = await wallet.approveERC20(tokenL1, "10000000"); - -await txHandle.wait(); -``` - -### `getBaseCost` - -Returns base cost for L2 transaction. - -#### Inputs - -| Name | Type | Description | -| --------------------------- | -------------- | ------------------------------------------------------------------------------------------------- | -| `params.gasLimit` | `BigNumberish` | The `gasLimit` for the L2 contract call. | -| `params.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | -| `params.gasPrice?` | `BigNumberish` | The L1 gas price of the L1 transaction that will send the request for an execute call. | - -```ts -async getBaseCost(params: { - gasLimit: BigNumberish; - gasPerPubdataByte?: BigNumberish; - gasPrice?: BigNumberish; -}): Promise +```ts +async getDeploymentNonce(): Promise ``` #### Example @@ -838,60 +884,14 @@ async getBaseCost(params: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - -const 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 })}`); -``` - -### `getBaseToken` - -Returns the address of the base token on L1. - -```ts -async getBaseToken(): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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()}`); -``` - -### `isETHBasedChain` - -Returns whether the chain is ETH-based. - -```ts -async isETHBasedChain(): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - + const 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()}`); + +console.log(`Nonce: ${await wallet.getDeploymentNonce()}`); ``` ### `getDepositAllowanceParams` @@ -916,7 +916,7 @@ async getDepositAllowanceParams( token: Address; allowance: BigNumberish; }[] -> +> ``` #### Example @@ -926,17 +926,17 @@ Get allowance parameters for depositing token on ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const token = ""; const amount = 5; const approveParams = await wallet.getDepositAllowanceParams(token, amount); - + await ( await wallet.approveERC20( approveParams[0].token, @@ -950,17 +950,17 @@ Get allowance parameters for depositing ETH on non-ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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, @@ -974,17 +974,17 @@ Get allowance parameters for depositing base token on non-ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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, @@ -998,24 +998,24 @@ Get allowance parameters for depositing non-base token on non-ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const 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, @@ -1024,206 +1024,115 @@ await ( ).wait(); ``` -### `deposit` +### `getDepositTx` -Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. -The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the -specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). -In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` -can be enabled to perform token approval. -If there are already enough approved tokens for the L1 bridge, token approval will be skipped. -To check the amount of approved tokens for a specific bridge, use -the [`allowanceL1`](#getallowancel1) method. +Returns populated deposit transaction. #### Inputs -| Parameter | Type | Description | -|-------------------------------------| ------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveBaseOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| Parameter | Type | Description | +| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async deposit(transaction: { +async getDepositTx(transaction: { token: Address; amount: BigNumberish; to?: Address; operatorTip?: BigNumberish; bridgeAddress?: Address; - approveERC20?: boolean; - approveBaseERC20?: boolean; l2GasLimit?: BigNumberish; gasPerPubdataByte?: BigNumberish; + customBridgeData?: BytesLike; refundRecipient?: Address; overrides?: ethers.PayableOverrides; - approveOverrides?: ethers.Overrides; - approveBaseOverrides?: ethers.Overrides; - customBridgeData?: BytesLike; -}): Promise +}): Promise ``` #### Example -Deposit ETH on ETH-based chain. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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_000, -}); -// 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(); -``` - -Deposit token on ETH-based chain. - ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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({ +const tx = await wallet.getDepositTx({ token: tokenL1, - amount: 10_000_000, - approveERC20: true, + amount: "10000000", }); -// 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(); ``` -Deposit ETH on non-ETH-based chain. +### `getFullRequiredDepositFee` -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; +Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 fee [`FullDepositFee`](/sdk/js/ethers/api/v5/types#fulldepositfee). -const PRIVATE_KEY = ""; +#### Inputs -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_000, - 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(); -``` - -Deposit base token on non-ETH-based chain. +| Parameter | Type | Description | +| -------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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_000, - 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(); +async getFullRequiredDepositFee(transaction: { + token: Address; + to?: Address; + bridgeAddress?: Address; + customBridgeData?: BytesLike; + gasPerPubdataByte?: BigNumberish; + overrides?: ethers.PayableOverrides; +}): Promise ``` -Deposit non-base token on non-ETH-based chain. +#### Example ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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({ +const fee = await wallet.getFullRequiredDepositFee({ token: tokenL1, - amount: 10_000_000, - approveERC20: true, - approveBaseERC20: true, + to: await wallet.getAddress(), }); -// 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(); +console.log(`Fee: ${fee}`); ``` -### `getDepositTx` - -Returns populated deposit transaction. - -#### Inputs +### `getL1BridgeContracts` -| Parameter | Type | Description | -| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns L1 bridge contracts. ```ts -async getDepositTx(transaction: { - token: Address; - amount: BigNumberish; - to?: Address; - operatorTip?: BigNumberish; - bridgeAddress?: Address; - l2GasLimit?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - customBridgeData?: BytesLike; - refundRecipient?: Address; - overrides?: ethers.PayableOverrides; -}): Promise +async getL1BridgeContracts(): Promise<{ + erc20: IL1ERC20Bridge; + weth: IL1ERC20Bridge; + shared: IL1SharedBridge; +}> ``` #### Example @@ -1231,53 +1140,26 @@ async getDepositTx(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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: "10000000", -}); + +const l1BridgeContracts = await wallet.getL1BridgeContracts(); ``` -### `estimateGasDeposit` - -Estimates the amount of gas required for a deposit transaction on L1 network. -Gas of approving ERC20 token is not included in estimation. - -#### Inputs +### `getL2BridgeContracts` -| Parameter | Type | Description | -| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns L2 bridge contracts. ```ts -async estimateGasDeposit(transaction: - token: Address; - amount: BigNumberish; - to?: Address; - operatorTip?: BigNumberish; - bridgeAddress?: Address; - customBridgeData?: BytesLike; - l2GasLimit?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.PayableOverrides; - }): Promise +async getL2BridgeContracts(): Promise<{ + erc20: IL2Bridge; + weth: IL2Bridge; + shared: IL2Bridge; +}> ``` #### Example @@ -1285,45 +1167,22 @@ async estimateGasDeposit(transaction: ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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: "10000000", -}); -console.log(`Gas: ${gas}`); + +const l2BridgeContracts = await wallet.getL2BridgeContracts(); ``` -### `getFullRequiredDepositFee` - -Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 fee [`FullDepositFee`](/sdk/js/ethers/api/v5/types#fulldepositfee). - -#### Inputs +### `getMainContract` -| Parameter | Type | Description | -| -------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns `Contract` wrapper of the ZKsync smart contract. ```ts -async getFullRequiredDepositFee(transaction: { - token: Address; - to?: Address; - bridgeAddress?: Address; - customBridgeData?: BytesLike; - gasPerPubdataByte?: BigNumberish; - overrides?: ethers.PayableOverrides; -}): Promise +async getMainContract(): Promise ``` #### Example @@ -1331,35 +1190,28 @@ async getFullRequiredDepositFee(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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}`); + +console.log(`Main contract: ${await wallet.getMainContract()}`); ``` -### `claimFailedDeposit` +### `getNonce` -The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. -If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` -method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. +Returns account's nonce number. #### Inputs -| Parameter | Type | Description | -| ----------- | --------- | ---------------------------------------------- | -| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | +| Parameter | Type | Description | +| ----------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | +| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async claimFailedDeposit(depositHash: BytesLike): Promise +async getNonce(blockTag?: BlockTag): Promise ``` #### Example @@ -1367,220 +1219,51 @@ async claimFailedDeposit(depositHash: BytesLike): PromiseL1` message. #### Inputs -| Parameter | Type | Description | -| ------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | -| `transaction.to?` | `Address` | The address of the recipient on L1. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | -| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v5/types#paymasterparams) | Paymaster parameters. | -| `transaction.overrides?` | `ethers.CallOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | +| Name | Type | Description | +|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | ```ts -async withdraw(transaction: { - token: Address; - amount: BigNumberish; - to?: Address; - bridgeAddress?: Address; - paymasterParams?: PaymasterParams; - overrides?: ethers.CallOverrides; -}): Promise +async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ + l1BatchNumber: number; + l2MessageIndex: number; + l2TxNumberInBlock: number; + proof: string[] +}> ``` -#### Examples - -Withdraw ETH. +#### Example ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; - +import { ethers } from "ethers"; + const 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_000, -}); -``` - -Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; - -const 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_000, - paymasterParams: utils.getPaymasterParams(paymaster, { - type: "ApprovalBased", - token: token, - minimalAllowance: 1, - innerInput: new Uint8Array(), - }), -}); -``` - -Withdraw token. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; - -const 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, -}); -``` - -Withdraw token using paymaster to facilitate fee payment with an ERC20 token. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; - -const 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_000, - paymasterParams: utils.getPaymasterParams(paymaster, { - type: "ApprovalBased", - token: token, - minimalAllowance: 1, - innerInput: new Uint8Array(), - }), -}); -``` - -### `finalizeWithdrawal` - -Proves the inclusion of the L2 -> L1 withdrawal message. - -#### Inputs - -| Name | Type | Description | -| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | - -```ts -async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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 = ""; -const finalizeWithdrawHandle = await wallet.finalizeWithdrawal(WITHDRAWAL_HASH); -``` - -### `isWithdrawalFinalized` - -Returns weather the withdrawal transaction is finalized on the L1 network. - -#### Inputs - -| Name | Type | Description | -| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | - -```ts -async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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 = ""; -const isFinalized = await wallet.isWithdrawalFinalized(WITHDRAWAL_HASH); -``` - -### `finalizeWithdrawalParams` - -Returns the [parameters](/sdk/js/ethers/api/v5/types#finalizewithdrawalparams) required for finalizing a withdrawal -from the withdrawal transaction's log on the L1 network. - -#### Inputs - -| Name | Type | Description | -| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | - -```ts -async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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 = ""; -const params = await wallet.finalizeWithdrawalParams(WITHDRAWAL_HASH); + +// 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))}`); ``` ### `getRequestExecuteAllowanceParams` @@ -1621,19 +1304,19 @@ async getRequestExecuteAllowanceParams(transaction: { ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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( @@ -1643,14 +1326,14 @@ await ( ).wait(); ``` -### `requestExecute` +### `getRequestExecuteTx` -Request execution of L2 transaction from L1. +Returns populated request execute transaction. #### Inputs | Name | Type | Description | -|----------------------------------| ------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| -------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `transaction.contractAddress` | `Address` | The L2 contract to be called. | | `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | @@ -1660,10 +1343,10 @@ Request execution of L2 transaction from L1. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async requestExecute(transaction: { +async getRequestExecuteTx(transaction: { contractAddress: Address; calldata: BytesLike; l2GasLimit?: BigNumberish; @@ -1674,7 +1357,7 @@ async requestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: ethers.PayableOverrides; -}): Promise +}): Promise ``` #### Example @@ -1682,16 +1365,16 @@ async requestExecute(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; const CONTRACT_ADDRESS = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const gasPrice = await wallet.providerL1.getGasPrice(); - + // The calldata can be encoded the same way as for Ethereum. // Here is an example of how to get the calldata from an ABI: const abi = [ @@ -1706,16 +1389,16 @@ const abi = [ const contractInterface = new ethers.utils.Interface(abi); const calldata = contractInterface.encodeFunctionData("increment", []); const l2GasLimit = BigNumber.from(1000); - + const txCostPrice = await wallet.getBaseCost({ gasPrice, calldataLength: ethers.utils.arrayify(calldata).length, l2GasLimit, }); - + console.log(`Executing the transaction will cost ${ethers.utils.formatEther(txCostPrice)} ETH`); - -const executeTx = await wallet.requestExecute({ + +const executeTx = await wallet.getRequestExecuteTx({ contractAddress: CONTRACT_ADDRESS, calldata, l2Value: 1, @@ -1725,42 +1408,44 @@ const executeTx = await wallet.requestExecute({ value: txCostPrice, }, }); +``` -await executeTx.wait(); +### `isETHBasedChain` + +Returns whether the chain is ETH-based. + +```ts +async isETHBasedChain(): Promise ``` -### `getRequestExecuteTx` +#### Example -Returns populated request execute transaction. +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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()}`); +``` + +### `isWithdrawalFinalized` + +Returns weather the withdrawal transaction is finalized on the L1 network. #### Inputs -| Name | Type | Description | -| -------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.contractAddress` | `Address` | The L2 contract to be called. | -| `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | -| `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | -| `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| Name | Type | Description | +| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | ```ts -async getRequestExecuteTx(transaction: { - contractAddress: Address; - calldata: BytesLike; - l2GasLimit?: BigNumberish; - mintValue?: BigNumberish; - l2Value?: BigNumberish; - factoryDeps?: BytesLike[]; - operatorTip?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.PayableOverrides; -}): Promise +async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -1768,59 +1453,95 @@ async getRequestExecuteTx(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; -const CONTRACT_ADDRESS = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const WITHDRAWAL_HASH = ""; +const isFinalized = await wallet.isWithdrawalFinalized(WITHDRAWAL_HASH); +``` -const gasPrice = await wallet.providerL1.getGasPrice(); +### `l2TokenAddress` -// The calldata can be encoded the same way as for Ethereum. -// Here is an example of how to get the calldata from an ABI: -const abi = [ - { - inputs: [], - name: "increment", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, -]; -const contractInterface = new ethers.utils.Interface(abi); -const calldata = contractInterface.encodeFunctionData("increment", []); -const l2GasLimit = BigNumber.from(1000); +Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. -const txCostPrice = await wallet.getBaseCost({ - gasPrice, - calldataLength: ethers.utils.arrayify(calldata).length, - l2GasLimit, -}); +::callout{icon="i-heroicons-exclamation-triangle" color="amber"} +Only works for tokens bridged on default ZKsync Era bridges. +:: -console.log(`Executing the transaction will cost ${ethers.utils.formatEther(txCostPrice)} ETH`); +#### Inputs -const executeTx = await wallet.getRequestExecuteTx({ - contractAddress: CONTRACT_ADDRESS, - calldata, - l2Value: 1, - l2GasLimit, - overrides: { - gasPrice, - value: txCostPrice, - }, +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `token` | `Address` | The address of the token on L1. | + +```ts +async l2TokenAddress(token: Address): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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)}`); +``` + +### `populateTransaction` + +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. + +| Parameter | Type | Description | +| ------------- | ----------------------------------------------------- | -------------------- | +| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | Transaction request. | + +```ts +async populateTransaction(transaction: TransactionRequest): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const recipient = Wallet.createRandom(); + +const tx = wallet.populateTransaction({ + to: recipient.address, + amount: ethers.utils.parseEther("0.01"), }); ``` -### `estimateGasRequestExecute` +### `requestExecute` -Estimates the amount of gas required for a request execute transaction. +Request execution of L2 transaction from L1. #### Inputs | Name | Type | Description | -| -------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|----------------------------------| ------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `transaction.contractAddress` | `Address` | The L2 contract to be called. | | `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | @@ -1830,10 +1551,10 @@ Estimates the amount of gas required for a request execute transaction. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async estimateGasRequestExecute(transaction: { +async requestExecute(transaction: { contractAddress: Address; calldata: BytesLike; l2GasLimit?: BigNumberish; @@ -1844,7 +1565,7 @@ async estimateGasRequestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: ethers.PayableOverrides; -}): Promise +}): Promise ``` #### Example @@ -1852,16 +1573,16 @@ async estimateGasRequestExecute(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; const CONTRACT_ADDRESS = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const gasPrice = await wallet.providerL1.getGasPrice(); - + // The calldata can be encoded the same way as for Ethereum. // Here is an example of how to get the calldata from an ABI: const abi = [ @@ -1876,16 +1597,16 @@ const abi = [ const contractInterface = new ethers.utils.Interface(abi); const calldata = contractInterface.encodeFunctionData("increment", []); const l2GasLimit = BigNumber.from(1000); - + const txCostPrice = await wallet.getBaseCost({ gasPrice, calldataLength: ethers.utils.arrayify(calldata).length, l2GasLimit, }); - + console.log(`Executing the transaction will cost ${ethers.utils.formatEther(txCostPrice)} ETH`); - -const executeTx = await wallet.getRequestExecuteTx({ + +const executeTx = await wallet.requestExecute({ contractAddress: CONTRACT_ADDRESS, calldata, l2Value: 1, @@ -1895,41 +1616,319 @@ const executeTx = await wallet.getRequestExecuteTx({ value: txCostPrice, }, }); + +await executeTx.wait(); ``` -### `getPriorityOpConfirmation` +### `sendTransaction` -Returns the transaction confirmation data that is part of `L2->L1` message. +Broadcast the transaction to the network. +Throws an error when `tx.from` is mismatched from the private key. #### Inputs -| Name | Type | Description | -|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | +| Parameter | Type | Description | +| --------- | ------------------------------------- | -------------------- | +| `tx` | `ethers.providers.TransactionRequest` | Transaction request. | ```ts -async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ - l1BatchNumber: number; - l2MessageIndex: number; - l2TxNumberInBlock: number; - proof: string[] -}> +async sendTransaction(tx: ethers.providers.TransactionRequest): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider); + +const recipient = Wallet.createRandom(); + +const tx = await wallet.sendTransaction({ + type: utils.EIP712_TX_TYPE, + to: recipient.address, + value: ethers.utils.parseEther("1"), +}); +``` + +### `signTransaction` + +Signs the transaction and serializes it to be ready to be broadcast to the network. +Throws an error when `transaction.from` is mismatched from the private key. + +#### Inputs + +| Parameter | Type | Description | +| ------------- | ----------------------------------------------------- | -------------------- | +| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | Transaction request. | + +```ts +async signTransaction(transaction: TransactionRequest): Promise ``` #### Example +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider); + +const recipient = Wallet.createRandom(); + +const tx = await wallet.signTransaction({ + type: utils.EIP712_TX_TYPE, + to: recipient.address, + value: ethers.utils.parseEther("1"), +}); +``` + +### `transfer` + +For convenience, the `Wallet` class has `transfer` method, which can transfer +`ETH` or any `ERC20` token within the same interface. + +#### Inputs + +| Parameter | Type | Description | +| ------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `transaction.to` | `Address` | The address of the recipient. | +| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | +| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | +| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v5/types#paymasterparams) | Paymaster parameters. | +| `transaction.overrides?` | `ethers.CallOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async transfer(transaction: { + to: Address; + amount: BigNumberish; + token?: Address; + overrides?: ethers.CallOverrides; +}): Promise +``` + +#### Examples + +Transfer ETH. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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.utils.parseEther("0.01"), +}); + +const receipt = await transferHandle.wait(); + +console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); +``` + +Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. + ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; + +const 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.utils.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}`); +``` + +Transfer token. +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + const 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.utils.parseEther("0.01"), +}); + +const receipt = await transferHandle.wait(); + +console.log(`The sum of ${receipt.value} token was transferred to ${receipt.to}`); +``` + +Transfer token using paymaster to facilitate fee payment with an ERC20 token. +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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.utils.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}`); +``` -// 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))}`); +### `withdraw` + +Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated +account on L2 network to the target account on L1 network. + +#### Inputs + +| Parameter | Type | Description | +| ------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | +| `transaction.to?` | `Address` | The address of the recipient on L1. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | +| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v5/types#paymasterparams) | Paymaster parameters. | +| `transaction.overrides?` | `ethers.CallOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async withdraw(transaction: { + token: Address; + amount: BigNumberish; + to?: Address; + bridgeAddress?: Address; + paymasterParams?: PaymasterParams; + overrides?: ethers.CallOverrides; +}): Promise +``` + +#### Examples + +Withdraw ETH. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + +const 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_000, +}); +``` + +Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + +const 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_000, + paymasterParams: utils.getPaymasterParams(paymaster, { + type: "ApprovalBased", + token: token, + minimalAllowance: 1, + innerInput: new Uint8Array(), + }), +}); +``` + +Withdraw token. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + +const 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, +}); +``` + +Withdraw token using paymaster to facilitate fee payment with an ERC20 token. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + +const 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_000, + paymasterParams: utils.getPaymasterParams(paymaster, { + type: "ApprovalBased", + token: token, + minimalAllowance: 1, + innerInput: new Uint8Array(), + }), +}); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/02.signer.md b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/02.signer.md index e38458e5..9da735a7 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/02.signer.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/02.signer.md @@ -15,6 +15,25 @@ const browserProvider = new Web3Provider(window.ethereum); const signer = Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); ``` +### `getAllBalances` + +Returns all token balances of the account. + +```ts +async getAllBalances(): Promise +``` + +#### Example + +```ts +import { Web3Provider, Provider, types } from "zksync-ethers"; + +const browserProvider = new Web3Provider(window.ethereum); +const signer = Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const allBalances = await signer.getAllBalances(); +``` + ### `getBalance` Returns the amount of the token the `Signer` has. @@ -56,25 +75,6 @@ const token = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; console.log(`Token balance: ${await signer.getBalance(token)}`); ``` -### `getAllBalances` - -Returns all token balances of the account. - -```ts -async getAllBalances(): Promise -``` - -#### Example - -```ts -import { Web3Provider, Provider, types } from "zksync-ethers"; - -const browserProvider = new Web3Provider(window.ethereum); -const signer = Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const allBalances = await signer.getAllBalances(); -``` - ### `getDeploymentNonce` Returns the deployment nonce of the account. diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/03.l1signer.md b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/03.l1signer.md index df37efc9..df4d9506 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/03.l1signer.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/03.l1signer.md @@ -18,12 +18,24 @@ const zksyncProvider = Provider.getDefaultProvider(types.Network.Sepolia); const signer = L1Signer.from(provider.getSigner(), zksyncProvider); ``` -### `getMainContract` +### `approveERC20` -Returns the main ZKsync Era smart contract address. +Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. + +#### Inputs + +| Parameter | Type | Description | +| ------------ | ------------------- | ----------------------------------------------------------------------------------------------------- | +| `token` | `Address` | The Ethereum address of the token. | +| `amount` | `BigNumberish` | The amount of the token to be approved. | +| `overrides?` | `ethers.Overrides?` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getMainContract(): Promise +async approveERC20( + token: Address, + amount: BigNumberish, + overrides?: ethers.Overrides & { bridgeAddress?: Address } +): Promise ``` #### Example @@ -31,47 +43,224 @@ async getMainContract(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +await signer.approveERC20(tokenL1, 5); +``` -const mainContract = await signer.getMainContract(); -console.log(mainContract.address); +### `claimFailedDeposit` + +The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. +If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` method of +the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. + +#### Inputs + +| Parameter | Type | Description | +| ----------- | --------- | ---------------------------------------------- | +| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | + +```ts +async claimFailedDeposit(depositHash: BytesLike): Promise ``` -### `getBridgehubContract` +#### Example -Returns `Contract` wrapper of the Bridgehub smart contract. +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const FAILED_DEPOSIT_HASH = ""; +const claimFailedDepositHandle = await signer.claimFailedDeposit(FAILED_DEPOSIT_HASH); +``` + +### `deposit` + +Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. +The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the +specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). +In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` +can be enabled to perform token approval. +If there are already enough approved tokens for the L1 bridge, token approval will be skipped. +To check the amount of approved tokens for a specific bridge, use +the [`allowanceL1`](#getallowancel1) method. + +#### Inputs + +| Parameter | Type | Description | +|-------------------------------------| ------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveBaseOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | ```ts -async getBridgehubContract(): Promise +async deposit(transaction: { + token: Address; + amount: BigNumberish; + to?: Address; + operatorTip?: BigNumberish; + bridgeAddress?: Address; + approveERC20?: boolean; + approveBaseERC20?: boolean; + l2GasLimit?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.PayableOverrides; + approveOverrides?: ethers.Overrides; + approveBaseOverrides?: ethers.Overrides; + customBridgeData?: BytesLike; +}): Promise ``` #### Example +Deposit ETH on ETH-based chain. + ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from( + browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +await signer.deposit({ + token: utils.ETH_ADDRESS, + amount: 10_000_000, +}); +``` + +Deposit token on ETH-based chain. +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +await signer.deposit({ + token: tokenL1, + amount: 10_000_000, + approveERC20: true, +}); +``` -const bridgehub = await signer.getBridgehubContract(); +Deposit ETH on non-ETH-based chain. + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from( + browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +await signer.deposit({ + token: utils.ETH_ADDRESS, + amount: 10_000_000, + approveBaseERC20: true, +}); ``` -### `getL1BridgeContracts` +Deposit base token on non-ETH-based chain. -Returns L1 bridge contracts. +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from( + browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +await signer.deposit({ + token: await signer.getBaseToken(), + amount: 10_000_000, + approveERC20: true, // or approveBaseERC20: true +}); +``` + +Deposit non-base token on non-ETH-based chain. ```ts -async getL1BridgeContracts(): Promise<{ - erc20: IL1ERC20Bridge; - weth: IL1ERC20Bridge; - shared: IL1SharedBridge; -}> +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from( + browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +await signer.deposit({ + token: tokenL1, + amount: 10_000_000, + approveERC20: true, + approveBaseERC20: true, +}); +``` + +### `estimateGasDeposit` + +Estimates the amount of gas required for a deposit transaction on L1 network. +Gas of approving ERC20 token is not included in estimation. + +#### Inputs + +| Parameter | Type | Description | +| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async estimateGasDeposit(transaction: + token: Address; + amount: BigNumberish; + to?: Address; + operatorTip?: BigNumberish; + bridgeAddress?: Address; + customBridgeData?: BytesLike; + l2GasLimit?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.PayableOverrides; + }): Promise ``` #### Example @@ -79,71 +268,112 @@ async getL1BridgeContracts(): Promise<{ ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const l1BridgeContracts = await signer.getL1BridgeContracts(); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +const gas = await signer.estimateGasDeposit({ + token: tokenL1, + amount: 10_000_000, +}); +console.log(`Gas: ${gas}`); ``` -### `getBalanceL1` +### `estimateGasRequestExecute` -Returns the amount of the token the `L1Signer` has on Ethereum. +Estimates the amount of gas required for a request execute transaction. #### Inputs -| Parameter | Type | Description | -| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | -| `token?` | `Address` | The address of the token. ETH by default. | -| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Name | Type | Description | +| -------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.contractAddress?` | `Address` | The L2 contract to be called. | +| `transaction.calldata?` | `BytesLike` | The input of the L2 transaction. | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | +| `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | +| `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise +async estimateGasRequestExecute(transaction: { + contractAddress: Address; + calldata: BytesLike; + l2GasLimit?: BigNumberish; + mintValue?: BigNumberish; + l2Value?: BigNumberish; + factoryDeps?: BytesLike[]; + operatorTip?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.PayableOverrides; +}): Promise ``` #### Example -Get ETH balance. - ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const gas = await signer.estimateGasRequestExecute({ + contractAddress: await signer.providerL2.getMainContractAddress(), + calldata: "0x", + l2Value: 7_000_000_000, +}); + +console.log(`Gas: ${gas}`); +``` -console.log(await signer.getBalanceL1()); +### `finalizeWithdrawal` + +Proves the inclusion of the L2 -> L1 withdrawal message. + +#### Inputs + +| Name | Type | Description | +| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | + +```ts +async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0): Promise ``` -Get token balance. +#### Example ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; -console.log(await signer.getBalanceL1(tokenL1)); + +const WITHDRAWAL_HASH = ""; +const finalizeWithdrawHandle = await signer.finalizeWithdrawal(WITHDRAWAL_HASH); ``` -### `l2TokenAddress` - -Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. +### `finalizeWithdrawalParams` -::callout{icon="i-heroicons-exclamation-triangle" color="amber"} -Only works for tokens bridged on default ZKsync Era bridges. -:: +Returns the [parameters](/sdk/js/ethers/api/v5/types#smartaccountsigner) required for finalizing a withdrawal +from the withdrawal transaction's log on the L1 network. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ------------------------------- | -| `token` | `Address` | The address of the token on L1. | +| Name | Type | Description | +| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | ```ts -async l2TokenAddress(token: Address): Promise +async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -151,13 +381,12 @@ async l2TokenAddress(token: Address): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; - -console.log(`Token L2 address: ${await signer.l2TokenAddress(tokenL1)}`); + +const WITHDRAWAL_HASH = ""; +const params = await signer.finalizeWithdrawalParams(WITHDRAWAL_HASH); ``` ### `getAllowanceL1` @@ -185,45 +414,54 @@ async getAllowanceL1( ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; console.log(`Token allowance: ${await signer.getAllowanceL1(tokenL1)}`); ``` -### `approveERC20` +### `getBalanceL1` -Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. +Returns the amount of the token the `L1Signer` has on Ethereum. #### Inputs -| Parameter | Type | Description | -| ------------ | ------------------- | ----------------------------------------------------------------------------------------------------- | -| `token` | `Address` | The Ethereum address of the token. | -| `amount` | `BigNumberish` | The amount of the token to be approved. | -| `overrides?` | `ethers.Overrides?` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| Parameter | Type | Description | +| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | +| `token?` | `Address` | The address of the token. ETH by default. | +| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async approveERC20( - token: Address, - amount: BigNumberish, - overrides?: ethers.Overrides & { bridgeAddress?: Address } -): Promise +async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise ``` #### Example +Get ETH balance. + ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +console.log(await signer.getBalanceL1()); +``` -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; -await signer.approveERC20(tokenL1, 5); +Get token balance. + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +console.log(await signer.getBalanceL1(tokenL1)); ``` ### `getBaseCost` @@ -251,10 +489,10 @@ async getBaseCost(params: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + console.log(`Base cost: ${await signer.getBaseCost({ gasLimit: 100_000 })}`); ``` @@ -271,22 +509,22 @@ async getBaseToken(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + console.log(`Base token: ${await signer.getBaseToken()}`); ``` -### `isETHBasedChain` +### `getBridgehubContract` -Returns whether the chain is ETH-based. +Returns `Contract` wrapper of the Bridgehub smart contract. ```ts -async isETHBasedChain(): Promise +async getBridgehubContract(): Promise ``` #### Example @@ -294,14 +532,14 @@ async isETHBasedChain(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - -console.log(`Is ETH-based chain: ${await signer.isETHBasedChain()}`); + +const bridgehub = await signer.getBridgehubContract(); ``` ### `getDepositAllowanceParams` @@ -326,7 +564,7 @@ async getDepositAllowanceParams( token: Address; allowance: BigNumberish; }[] -> +> ``` #### Example @@ -336,17 +574,17 @@ Get allowance parameters for depositing token on ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = ""; const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); - + await ( await signer.approveERC20( approveParams[0].token, @@ -360,13 +598,13 @@ Get allowance parameters for depositing ETH on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = utils.LEGACY_ETH_ADDRESS; const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); @@ -383,13 +621,13 @@ Get allowance parameters for depositing base token on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = await signer.getBaseToken(); const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); @@ -406,24 +644,24 @@ Get allowance parameters for depositing non-base token on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = ""; const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); - + await ( await signer.approveERC20( approveParams[0].token, approveParams[0].allowance ) ).wait(); - + await ( await signer.approveERC20( approveParams[1].token, @@ -432,154 +670,6 @@ await ( ).wait(); ``` -### `deposit` - -Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. -The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the -specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). -In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` -can be enabled to perform token approval. -If there are already enough approved tokens for the L1 bridge, token approval will be skipped. -To check the amount of approved tokens for a specific bridge, use -the [`allowanceL1`](#getallowancel1) method. - -#### Inputs - -| Parameter | Type | Description | -|-------------------------------------| ------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveBaseOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | - -```ts -async deposit(transaction: { - token: Address; - amount: BigNumberish; - to?: Address; - operatorTip?: BigNumberish; - bridgeAddress?: Address; - approveERC20?: boolean; - approveBaseERC20?: boolean; - l2GasLimit?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.PayableOverrides; - approveOverrides?: ethers.Overrides; - approveBaseOverrides?: ethers.Overrides; - customBridgeData?: BytesLike; -}): Promise -``` - -#### Example - -Deposit ETH on ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from( - browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -await signer.deposit({ - token: utils.ETH_ADDRESS, - amount: 10_000_000, -}); -``` - -Deposit token on ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from( - browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; -await signer.deposit({ - token: tokenL1, - amount: 10_000_000, - approveERC20: true, -}); -``` - -Deposit ETH on non-ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from( - browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -await signer.deposit({ - token: utils.ETH_ADDRESS, - amount: 10_000_000, - approveBaseERC20: true, -}); -``` - -Deposit base token on non-ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from( - browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -await signer.deposit({ - token: await signer.getBaseToken(), - amount: 10_000_000, - approveERC20: true, // or approveBaseERC20: true -}); -``` - -Deposit non-base token on non-ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from( - browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; -await signer.deposit({ - token: tokenL1, - amount: 10_000_000, - approveERC20: true, - approveBaseERC20: true, -}); -``` - ### `getDepositTx` Returns populated deposit transaction. @@ -619,10 +709,10 @@ async getDepositTx(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; const tx = await signer.getDepositTx({ token: tokenL1, @@ -630,58 +720,6 @@ const tx = await signer.getDepositTx({ }); ``` -### `estimateGasDeposit` - -Estimates the amount of gas required for a deposit transaction on L1 network. -Gas of approving ERC20 token is not included in estimation. - -#### Inputs - -| Parameter | Type | Description | -| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | - -```ts -async estimateGasDeposit(transaction: - token: Address; - amount: BigNumberish; - to?: Address; - operatorTip?: BigNumberish; - bridgeAddress?: Address; - customBridgeData?: BytesLike; - l2GasLimit?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.PayableOverrides; - }): Promise -``` - -#### Example - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; -const gas = await signer.estimateGasDeposit({ - token: tokenL1, - amount: 10_000_000, -}); -console.log(`Gas: ${gas}`); -``` - ### `getFullRequiredDepositFee` Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 fee [`FullDepositFee`](/sdk/js/ethers/api/v5/types#fulldepositfee). @@ -698,75 +736,43 @@ Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getFullRequiredDepositFee(transaction: { - token: Address; - to?: Address; - bridgeAddress?: Address; - customBridgeData?: BytesLike; - gasPerPubdataByte?: BigNumberish; - overrides?: ethers.PayableOverrides; -}): Promise -``` - -#### Example - -```ts -import { Provider, L1Signer, Wallet, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; -const fee = await signer.getFullRequiredDepositFee({ - token: tokenL1, - to: Wallet.createRandom().address, -}); -console.log(`Fee: ${fee}`); -``` - -### `claimFailedDeposit` - -The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. -If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` method of -the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. - -#### Inputs - -| Parameter | Type | Description | -| ----------- | --------- | ---------------------------------------------- | -| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | - -```ts -async claimFailedDeposit(depositHash: BytesLike): Promise +async getFullRequiredDepositFee(transaction: { + token: Address; + to?: Address; + bridgeAddress?: Address; + customBridgeData?: BytesLike; + gasPerPubdataByte?: BigNumberish; + overrides?: ethers.PayableOverrides; +}): Promise ``` #### Example ```ts -import { Provider, L1Signer, types } from "zksync-ethers"; +import { Provider, L1Signer, Wallet, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const FAILED_DEPOSIT_HASH = ""; -const claimFailedDepositHandle = await signer.claimFailedDeposit(FAILED_DEPOSIT_HASH); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +const fee = await signer.getFullRequiredDepositFee({ + token: tokenL1, + to: Wallet.createRandom().address, +}); +console.log(`Fee: ${fee}`); ``` -### `finalizeWithdrawal` - -Proves the inclusion of the L2 -> L1 withdrawal message. - -#### Inputs +### `getL1BridgeContracts` -| Name | Type | Description | -| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | +Returns L1 bridge contracts. ```ts -async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0): Promise +async getL1BridgeContracts(): Promise<{ + erc20: IL1ERC20Bridge; + weth: IL1ERC20Bridge; + shared: IL1SharedBridge; +}> ``` #### Example @@ -774,27 +780,19 @@ async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0): Promise< ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const WITHDRAWAL_HASH = ""; -const finalizeWithdrawHandle = await signer.finalizeWithdrawal(WITHDRAWAL_HASH); + +const l1BridgeContracts = await signer.getL1BridgeContracts(); ``` -### `isWithdrawalFinalized` - -Returns weather the withdrawal transaction is finalized on the L1 network. - -#### Inputs +### `getMainContract` -| Name | Type | Description | -| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | +Returns the main ZKsync Era smart contract address. ```ts -async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise +async getMainContract(): Promise ``` #### Example @@ -802,28 +800,32 @@ async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promi ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const WITHDRAWAL_HASH = ""; -const isFinalized = await signer.isWithdrawalFinalized(WITHDRAWAL_HASH); + +const mainContract = await signer.getMainContract(); +console.log(mainContract.address); ``` -### `finalizeWithdrawalParams` +### `getPriorityOpConfirmation` -Returns the [parameters](/sdk/js/ethers/api/v5/types#smartaccountsigner) required for finalizing a withdrawal -from the withdrawal transaction's log on the L1 network. +Returns the transaction confirmation data that is part of `L2->L1` message. #### Inputs -| Name | Type | Description | -| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | +| Name | Type | Description | +|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | ```ts -async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise +async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ + l1BatchNumber: number; + l2MessageIndex: number; + l2TxNumberInBlock: number; + proof: string[] +}> ``` #### Example @@ -831,12 +833,17 @@ async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Pr ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const WITHDRAWAL_HASH = ""; -const params = await signer.finalizeWithdrawalParams(WITHDRAWAL_HASH); +const signer = L1Signer.from( + browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +// Any L2 -> L1 transaction can be used. +// In this case, withdrawal transaction is used. +const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; +console.log(`Confirmation data: ${utils.toJSON(await signer.getPriorityOpConfirmation(tx, 0))}`); ``` ### `getRequestExecuteAllowanceParams` @@ -877,19 +884,19 @@ async getRequestExecuteAllowanceParams(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from( browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const tx = { contractAddress: await signer.getAddress(), calldata: '0x', l2Value: 7_000_000_000, }; - + const approveParams = await signer.getRequestExecuteAllowanceParams(tx); await ( await signer.approveERC20( @@ -899,9 +906,9 @@ await ( ).wait(); ``` -### `requestExecute` +### `getRequestExecuteTx` -Request execution of L2 transaction from L1. +Returns populated deposit transaction. #### Inputs @@ -916,10 +923,10 @@ Request execution of L2 transaction from L1. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -requestExecute(transaction: { +async getRequestExecuteTx(transaction: { contractAddress: Address; calldata: BytesLike; l2GasLimit?: BigNumberish; @@ -930,7 +937,7 @@ requestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: ethers.PayableOverrides; -}): Promise +}): Promise ``` #### Example @@ -938,49 +945,53 @@ requestExecute(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -await signer.requestExecute({ + +const tx = await signer.getRequestExecuteTx({ contractAddress: await signer.providerL2.getMainContractAddress(), calldata: "0x", l2Value: 7_000_000_000, }); ``` -### `getRequestExecuteTx` +### `isETHBasedChain` -Returns populated deposit transaction. +Returns whether the chain is ETH-based. + +```ts +async isETHBasedChain(): Promise +``` + +#### Example + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from( + browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +console.log(`Is ETH-based chain: ${await signer.isETHBasedChain()}`); +``` + +### `isWithdrawalFinalized` + +Returns weather the withdrawal transaction is finalized on the L1 network. #### Inputs -| Name | Type | Description | -| -------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.contractAddress?` | `Address` | The L2 contract to be called. | -| `transaction.calldata?` | `BytesLike` | The input of the L2 transaction. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | -| `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | -| `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | +| Name | Type | Description | +| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | ```ts -async getRequestExecuteTx(transaction: { - contractAddress: Address; - calldata: BytesLike; - l2GasLimit?: BigNumberish; - mintValue?: BigNumberish; - l2Value?: BigNumberish; - factoryDeps?: BytesLike[]; - operatorTip?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.PayableOverrides; -}): Promise +async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -988,20 +999,49 @@ async getRequestExecuteTx(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const WITHDRAWAL_HASH = ""; +const isFinalized = await signer.isWithdrawalFinalized(WITHDRAWAL_HASH); +``` -const tx = await signer.getRequestExecuteTx({ - contractAddress: await signer.providerL2.getMainContractAddress(), - calldata: "0x", - l2Value: 7_000_000_000, -}); +### `l2TokenAddress` + +Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. + +::callout{icon="i-heroicons-exclamation-triangle" color="amber"} +Only works for tokens bridged on default ZKsync Era bridges. +:: + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `token` | `Address` | The address of the token on L1. | + +```ts +async l2TokenAddress(token: Address): Promise ``` -### `estimateGasRequestExecute` +#### Example -Estimates the amount of gas required for a request execute transaction. +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.providers.Web3Provider(window.ethereum); +const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; + +console.log(`Token L2 address: ${await signer.l2TokenAddress(tokenL1)}`); +``` + +### `requestExecute` + +Request execution of L2 transaction from L1. #### Inputs @@ -1016,10 +1056,10 @@ Estimates the amount of gas required for a request execute transaction. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async estimateGasRequestExecute(transaction: { +requestExecute(transaction: { contractAddress: Address; calldata: BytesLike; l2GasLimit?: BigNumberish; @@ -1030,7 +1070,7 @@ async estimateGasRequestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: ethers.PayableOverrides; -}): Promise +}): Promise ``` #### Example @@ -1038,53 +1078,13 @@ async estimateGasRequestExecute(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.providers.Web3Provider(window.ethereum); const signer = L1Signer.from(browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const gas = await signer.estimateGasRequestExecute({ + +await signer.requestExecute({ contractAddress: await signer.providerL2.getMainContractAddress(), calldata: "0x", l2Value: 7_000_000_000, }); - -console.log(`Gas: ${gas}`); -``` - -### `getPriorityOpConfirmation` - -Returns the transaction confirmation data that is part of `L2->L1` message. - -#### Inputs - -| Name | Type | Description | -|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | - -```ts -async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ - l1BatchNumber: number; - l2MessageIndex: number; - l2TxNumberInBlock: number; - proof: string[] -}> -``` - -#### Example - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.providers.Web3Provider(window.ethereum); -const signer = L1Signer.from( - browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -// Any L2 -> L1 transaction can be used. -// In this case, withdrawal transaction is used. -const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; -console.log(`Confirmation data: ${utils.toJSON(await signer.getPriorityOpConfirmation(tx, 0))}`); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/06.eip712signer.md b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/06.eip712signer.md index 41617316..cb60d416 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/06.eip712signer.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/06.eip712signer.md @@ -6,6 +6,14 @@ tags: ["zksync", "ethers.js", "blockchain", "EIP712", "smart contracts"] This class provides support for an EIP712 transaction. The methods of this class are mostly used internally. +### `getDomain` + +Returns the EIP712 domain. + +```ts +async getDomain(): Promise +``` + ### `getSignInput` Generates the EIP-712 typed data from provided transaction. Optional fields are populated by zero values. @@ -36,9 +44,9 @@ const tx = EIP712Signer.getSignInput({ }); ``` -### `sign` +### `getSignedDigest` -Signs an Ethereum transaction using EIP-712. +Generates the signed digest of an Ethereum transaction using EIP-712. #### Inputs @@ -47,12 +55,12 @@ Signs an Ethereum transaction using EIP-712. | `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | Transaction request. | ```ts -async sign(transaction: TransactionRequest): Promise +static getSignedDigest(transaction: TransactionRequest): ethers.BytesLike ``` -### `getSignedDigest` +### `sign` -Generates the signed digest of an Ethereum transaction using EIP-712. +Signs an Ethereum transaction using EIP-712. #### Inputs @@ -61,13 +69,5 @@ Generates the signed digest of an Ethereum transaction using EIP-712. | `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | Transaction request. | ```ts -static getSignedDigest(transaction: TransactionRequest): ethers.BytesLike -``` - -### `getDomain` - -Returns the EIP712 domain. - -```ts -async getDomain(): Promise +async sign(transaction: TransactionRequest): Promise ``` diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/07.smartaccount.md b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/07.smartaccount.md index fa5a4a71..b88b0b4c 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/07.smartaccount.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/01.accounts/07.smartaccount.md @@ -12,33 +12,48 @@ It is compatible with [ethers.ContractFactory](https://docs.ethers.org/v5/api/co for deploying contracts/accounts, as well as with [ethers.Contract](https://docs.ethers.org/v5/api/contract/contract/) for interacting with contracts/accounts using provided ABI along with custom transaction signing logic. -### `constructor` +### `_signTypedData` -Creates a `SmartAccount` instance with provided `signer` and `provider`. -By default, uses [`signPayloadWithECDSA`](/sdk/js/ethers/api/v5/utilities/smart-account-utils#populatetransactionecdsa) -and [`populateTransactionECDSA`](/sdk/js/ethers/api/v5/utilities/smart-account-utils#populatetransactionecdsa). +Signs a typed data using the provided [`PayloadSigner`](/sdk/js/ethers/api/v5/types#payloadsigner) function. #### Inputs -| Parameter | Type | Description | -| ---------- | ----------------------------------------------------- | --------------------------------------------------- | -| `signer` | [`SmartAccountSigner`](/sdk/js/ethers/api/v5/types#smartaccountsigner) | Contains necessary properties for signing payloads. | -| `provider` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | The provider to connect to (optional). | +| Parameter | Type | Description | +| --------- | ----------------------------------------- | -------------------------------------------------------- | +| `domain` | `ethers.TypedDataDomain` | The domain data. | +| `types` | `Record` | A map of records pointing from field name to field type. | +| `value` | `Record` | A single record value. | ```ts -constructor(signer: SmartAccountSigner, provider: Provider) +async signTypedData( + domain: ethers.TypedDataDomain, + types: Record, + value: Record +): Promise ``` #### Example ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - +import { ethers } from "ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); + +const signedTypedData = await account._signTypedData( + { name: "Example", version: "1", chainId: 270 }, + { + Person: [ + { name: "name", type: "string" }, + { name: "age", type: "uint8" }, + ], + }, + { name: "John", age: 30 } +); ``` ### `connect` @@ -59,66 +74,66 @@ connect(provider: Provider): SmartAccount ```ts import { Wallet, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const sepoliaProvider = Provider.getDefaultProvider(types.Network.Sepolia); const sepoliaAccount = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, sepoliaProvider); - + const mainnetProvider = Provider.getDefaultProvider(types.Network.Mainnet); const mainnetAccount = sepoliaAccount.connect(mainnetProvider); ``` -### `getAddress` +### `constructor` -Returns the address of the account. +Creates a `SmartAccount` instance with provided `signer` and `provider`. +By default, uses [`signPayloadWithECDSA`](/sdk/js/ethers/api/v5/utilities/smart-account-utils#populatetransactionecdsa) +and [`populateTransactionECDSA`](/sdk/js/ethers/api/v5/utilities/smart-account-utils#populatetransactionecdsa). + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ----------------------------------------------------- | --------------------------------------------------- | +| `signer` | [`SmartAccountSigner`](/sdk/js/ethers/api/v5/types#smartaccountsigner) | Contains necessary properties for signing payloads. | +| `provider` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | The provider to connect to (optional). | ```ts -getAddress(): Promise +constructor(signer: SmartAccountSigner, provider: Provider) ``` #### Example ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const address = await account.getAddress(); ``` -### `getBalance` - -Returns the balance of the account. - -#### Inputs +### `getAddress` -| Parameter | Type | Description | -| ---------- | ---------- | -------------------------------------------------------------------------------- | -| `token` | `Address` | The token address to query balance for. Defaults to the native token (optional). | -| `blockTag` | `BlockTag` | The block tag to get the balance at. Defaults to `committed`. | +Returns the address of the account. ```ts -async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +getAddress(): Promise ``` #### Example ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const balance = await account.getBalance(); + +const address = await account.getAddress(); ``` ### `getAllBalances` @@ -133,16 +148,45 @@ async getAllBalances(): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const balances = await account.getAllBalances(); ``` +### `getBalance` + +Returns the balance of the account. + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ---------- | -------------------------------------------------------------------------------- | +| `token` | `Address` | The token address to query balance for. Defaults to the native token (optional). | +| `blockTag` | `BlockTag` | The block tag to get the balance at. Defaults to `committed`. | + +```ts +async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +``` + +#### Example + +```ts +import { SmartAccount, Provider, types } from "zksync-ethers"; + +const ADDRESS = "
"; +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); + +const balance = await account.getBalance(); +``` + ### `getDeploymentNonce` Returns the deployment nonce of the account. @@ -155,13 +199,13 @@ async getDeploymentNonce(): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const nonce = await account.getDeploymentNonce(); ``` @@ -184,13 +228,13 @@ async getNonce(blockTag?: BlockTag): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const nonce = await account.getNonce(); ``` @@ -215,13 +259,13 @@ async populateTransaction(tx: TransactionRequest): Promise ```ts import { SmartAccount, Provider, types, utils } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const populatedTx = await account.populateTransaction({ type: utils.EIP712_TX_TYPE, to: "", @@ -229,41 +273,6 @@ const populatedTx = await account.populateTransaction({ }); ``` -### `signTransaction` - -Signs the transaction `tx` using the provided [`PayloadSigner`](/sdk/js/ethers/api/v5/types#payloadsigner) function, -returning the fully signed transaction. The `populateTransaction` method -is called first to ensure that all necessary properties for the transaction to be valid -have been populated. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------------------------------------------- | ---------------------------------------- | -| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | The transaction that needs to be signed. | - -```ts -async signTransaction(tx: TransactionRequest): Promise -``` - -#### Example - -```ts -import { SmartAccount, Provider, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const ADDRESS = "
"; -const PRIVATE_KEY = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const signedTx = await account.signTransaction({ - to: "", - value: ethers.utils.parseEther("1"), -}); -``` - ### `sendTransaction` Sends `tx` to the Network. The `signTransaction` @@ -284,13 +293,13 @@ async sendTransaction(tx: TransactionRequest): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const signedTx = await account.sendTransaction({ to: "", value: ethers.utils.parseEther("1"), @@ -316,34 +325,31 @@ signMessage(message: string | Uint8Array): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const signedMessage = await account.signMessage("Hello World!"); ``` -### `_signTypedData` +### `signTransaction` -Signs a typed data using the provided [`PayloadSigner`](/sdk/js/ethers/api/v5/types#payloadsigner) function. +Signs the transaction `tx` using the provided [`PayloadSigner`](/sdk/js/ethers/api/v5/types#payloadsigner) function, +returning the fully signed transaction. The `populateTransaction` method +is called first to ensure that all necessary properties for the transaction to be valid +have been populated. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------------------------------- | -------------------------------------------------------- | -| `domain` | `ethers.TypedDataDomain` | The domain data. | -| `types` | `Record` | A map of records pointing from field name to field type. | -| `value` | `Record` | A single record value. | +| Parameter | Type | Description | +| --------- | ----------------------------------------------------- | ---------------------------------------- | +| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v5/types#transactionrequest) | The transaction that needs to be signed. | ```ts -async signTypedData( - domain: ethers.TypedDataDomain, - types: Record, - value: Record -): Promise +async signTransaction(tx: TransactionRequest): Promise ``` #### Example @@ -351,94 +357,89 @@ async signTypedData( ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const signedTypedData = await account._signTypedData( - { name: "Example", version: "1", chainId: 270 }, - { - Person: [ - { name: "name", type: "string" }, - { name: "age", type: "uint8" }, - ], - }, - { name: "John", age: 30 } -); + +const signedTx = await account.signTransaction({ + to: "", + value: ethers.utils.parseEther("1"), +}); ``` -### `withdraw` - -Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated -account on L2 network to the target account on L1 network. +### `transfer` -#### Inputs +Transfer ETH or any ERC20 token within the same interface. | Parameter | Type | Description | | ------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | -| `transaction.to?` | `Address` | The address of the recipient on L1. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | +| `transaction.to` | `Address` | The address of the recipient. | +| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | +| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | | `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v5/types#paymasterparams) | Paymaster parameters. | | `transaction.overrides?` | `ethers.CallOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async withdraw(transaction: { - token: Address; +async transfer(transaction: { + to: Address; amount: BigNumberish; - to?: Address; - bridgeAddress?: Address; - paymasterParams?: PaymasterParams; + token?: Address; overrides?: ethers.CallOverrides; }): Promise ``` #### Examples -Withdraw ETH. +Transfer ETH. ```ts -import { SmartAccount, Provider, types, utils } from "zksync-ethers"; - +import { SmartAccount, Wallet, Provider, types } from "zksync-ethers"; +import { ethers } from "ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const withdrawTx = await account.withdraw({ + +const transferTx = await account.transfer({ token: utils.ETH_ADDRESS, - amount: 10_000_000, + to: Wallet.createRandom().address, + amount: ethers.utils.parseEther("0.01"), }); + +const receipt = await transferTx.wait(); + +console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` -Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. +Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. ```ts -import { SmartAccount, Provider, types, utils } from "zksync-ethers"; - +import { SmartAccount, Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + const ADDRESS = "
"; const 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 account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const withdrawTx = await account.withdraw({ - token: utils.ETH_ADDRESS, - amount: 10_000_000, + +const transferTx = await account.transfer({ + to: Wallet.createRandom().address, + amount: ethers.utils.parseEther("0.01"), paymasterParams: utils.getPaymasterParams(paymaster, { type: "ApprovalBased", token: token, @@ -446,78 +447,81 @@ const withdrawTx = await account.withdraw({ innerInput: new Uint8Array(), }), }); + +const receipt = await transferTx.wait(); + +console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` -### `transfer` +### `withdraw` -Transfer ETH or any ERC20 token within the same interface. +Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated +account on L2 network to the target account on L1 network. + +#### Inputs | Parameter | Type | Description | | ------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `transaction.to` | `Address` | The address of the recipient. | -| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | -| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | +| `transaction.token` | `Address` | The address of the token. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | +| `transaction.to?` | `Address` | The address of the recipient on L1. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | | `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v5/types#paymasterparams) | Paymaster parameters. | | `transaction.overrides?` | `ethers.CallOverrides` | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async transfer(transaction: { - to: Address; +async withdraw(transaction: { + token: Address; amount: BigNumberish; - token?: Address; + to?: Address; + bridgeAddress?: Address; + paymasterParams?: PaymasterParams; overrides?: ethers.CallOverrides; }): Promise ``` #### Examples -Transfer ETH. +Withdraw ETH. ```ts -import { SmartAccount, Wallet, Provider, types } from "zksync-ethers"; -import { ethers } from "ethers"; - +import { SmartAccount, Provider, types, utils } from "zksync-ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const transferTx = await account.transfer({ + +const withdrawTx = await account.withdraw({ token: utils.ETH_ADDRESS, - to: Wallet.createRandom().address, - amount: ethers.utils.parseEther("0.01"), + amount: 10_000_000, }); - -const receipt = await transferTx.wait(); - -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` -Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. +Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. ```ts -import { SmartAccount, Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - +import { SmartAccount, Provider, types, utils } from "zksync-ethers"; + const ADDRESS = "
"; const 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 account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const transferTx = await account.transfer({ - to: Wallet.createRandom().address, - amount: ethers.utils.parseEther("0.01"), + +const withdrawTx = await account.withdraw({ + token: utils.ETH_ADDRESS, + amount: 10_000_000, paymasterParams: utils.getPaymasterParams(paymaster, { type: "ApprovalBased", token: token, @@ -525,8 +529,4 @@ const transferTx = await account.transfer({ innerInput: new Uint8Array(), }), }); - -const receipt = await transferTx.wait(); - -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/00.utils.md b/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/00.utils.md index 442474c3..4dd22629 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/00.utils.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/00.utils.md @@ -237,7 +237,6 @@ const REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT = 800; ``` ## Functions - ### `applyL1ToL2Alias` Converts the address that submitted a transaction to the inbox on L1 to the `msg.sender` viewed on L2. @@ -436,21 +435,6 @@ Returns the calldata sent by an L1 ERC20 bridge to its L2 counterpart during tok async function getERC20BridgeCalldata(l1TokenAddress: string, l1Sender: string, l2Receiver: string, amount: BigNumberish, bridgeData: BytesLike): Promise; ``` -### `getL2HashFromPriorityOp` - -Returns the hash of the L2 priority operation from a given transaction receipt and L2 address. - -#### Inputs - -| Parameter | Type | Description | -| --------------- | ----------------------------------------------------- | ------------------------------------ | -| `txReceipt` | [`TransactionReceipt`](/sdk/js/ethers/api/v5/types#transactionreceipt) | Receipt of the L1 transaction. | -| `zkSyncAddress` | `Address` | Address of ZKsync Era main contract. | - -```ts -function getL2HashFromPriorityOp(txReceipt: ethers.providers.TransactionReceipt, zkSyncAddress: Address): string; -``` - ### `getHashedL2ToL1Msg` Returns a keccak encoded message with a given sender address and block number from the L1 messenger contract. @@ -475,6 +459,21 @@ const withdrawETHMessageHash = utils.getHashedL2ToL1Msg("0x36615Cf349d7F6344891B // withdrawETHMessageHash = "0xd8c80ecb64619e343f57c3b133c6c6d8dd0572dd3488f1ca3276c5b7fd3a938d" ``` +### `getL2HashFromPriorityOp` + +Returns the hash of the L2 priority operation from a given transaction receipt and L2 address. + +#### Inputs + +| Parameter | Type | Description | +| --------------- | ----------------------------------------------------- | ------------------------------------ | +| `txReceipt` | [`TransactionReceipt`](/sdk/js/ethers/api/v5/types#transactionreceipt) | Receipt of the L1 transaction. | +| `zkSyncAddress` | `Address` | Address of ZKsync Era main contract. | + +```ts +function getL2HashFromPriorityOp(txReceipt: ethers.providers.TransactionReceipt, zkSyncAddress: Address): string; +``` + ### `hashBytecode` Returns the hash of given bytecode. @@ -524,7 +523,7 @@ function isAddressEq(a: Address, b: Address): boolean ```ts import { Wallet, utils } from "zksync-ethers"; - + utils.isAddressEq("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", "0x36615cf349d7f6344891b1e7ca7c72883f5dc049") // true ``` @@ -552,15 +551,15 @@ function isECDSASignatureCorrect(address: string, msgHash: string, signature: Si ```ts import { Wallet, utils } from "zksync-ethers"; - + const ADDRESS = ""; const PRIVATE_KEY = ""; - + const message = "Hello, world!"; const signature = await new Wallet(PRIVATE_KEY).signMessage(message); // ethers.Wallet can be used as well // const signature = await new ethers.Wallet(PRIVATE_KEY).signMessage(message); - + const isValidSignature = await utils.isECDSASignatureCorrect(ADDRESS, message, signature); // isValidSignature = true ``` @@ -640,16 +639,16 @@ async function isMessageSignatureCorrect(provider: Provider, address: string, me ```ts import { Wallet, utils, Provider } from "zksync-ethers"; - + const ADDRESS = ""; const PRIVATE_KEY = ""; const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const message = "Hello, world!"; const signature = await new Wallet(PRIVATE_KEY).signMessage(message); // ethers.Wallet can be used as well // const signature = await new ethers.Wallet(PRIVATE_KEY).signMessage(message); - + const isValidSignature = await utils.isMessageSignatureCorrect(provider, ADDRESS, message, signature); // isValidSignature = true ``` @@ -704,11 +703,11 @@ async function isTypedDataSignatureCorrect( ```ts import { Wallet, utils, Provider, EIP712Signer } from "zksync-ethers"; - + const ADDRESS = ""; const PRIVATE_KEY = ""; const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const tx: types.TransactionRequest = { type: 113, chainId: 270, @@ -716,14 +715,14 @@ const tx: types.TransactionRequest = { to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", value: BigInt(7_000_000), }; - + const eip712Signer = new EIP712Signer( new Wallet(PRIVATE_KEY), // or new ethers.Wallet(PRIVATE_KEY), Number((await provider.getNetwork()).chainId) ); - + const signature = await eip712Signer.sign(tx); - + const isValidSignature = await utils.isTypedDataSignatureCorrect(provider, ADDRESS, await eip712Signer.getDomain(), utils.EIP712_TYPES, EIP712Signer.getSignInput(tx), signature); // isValidSignature = true ``` @@ -746,7 +745,7 @@ function parseTransaction(payload: ethers.BytesLike): ethers.Transaction; ```ts import { types } from "zksync-ethers"; - + const serializedTx = "0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0"; const tx: types.TransactionLike = utils.parseEip712(serializedTx); @@ -800,7 +799,7 @@ Serialize EIP712 transaction without signature. ```ts const serializedTx = utils.serializeEip712({ chainId: 270, from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" }, null); - + // serializedTx = "0x71ea8080808080808082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0" ``` @@ -808,7 +807,7 @@ Serialize EIP712 transaction with signature. ```ts const signature = ethers.Signature.from("0x73a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aaf87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a"); - + const serializedTx = utils.serializeEip712( { chainId: 270, @@ -835,6 +834,29 @@ Common sleep function that pauses execution for a number of milliseconds. function sleep(millis: number); ``` +### `toJSON` + +Creates a JSON string from an object, including support for serializing bigint types. + +```ts +function toJSON(object: any): string; +``` + +#### Inputs + +| Parameter | Type | Description | +|-----------|------|-------------| +| `object` | any | Any object. | + +#### Example + +```ts +import { utils } from "zksync-ethers"; + +const json = utils.toJSON({gasLimit: 1_000n}) +// {"gasLimit": 1000} +``` + ### `undoL1ToL2Alias` Converts and returns the `msg.sender` viewed on L2 to the address that submitted a transaction to the inbox on L1. @@ -860,26 +882,3 @@ const l1ContractAddress = utils.undoL1ToL2Alias(l2ContractAddress); ::callout See also [`applyl1tol2alias`](#applyl1tol2alias). :: - -### `toJSON` - -Creates a JSON string from an object, including support for serializing bigint types. - -```ts -function toJSON(object: any): string; -``` - -#### Inputs - -| Parameter | Type | Description | -|-----------|------|-------------| -| `object` | any | Any object. | - -#### Example - -```ts -import { utils } from "zksync-ethers"; - -const json = utils.toJSON({gasLimit: 1_000n}) -// {"gasLimit": 1000} -``` diff --git a/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/02.smart-account-utils.md b/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/02.smart-account-utils.md index bb6a09ca..8e3f6ad1 100644 --- a/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/02.smart-account-utils.md +++ b/content/sdk/10.js/00.ethers/05.api/10.v5/04.utilities/02.smart-account-utils.md @@ -8,6 +8,91 @@ This module provides utilities for signing transactions with ECDSA private keys ## Functions +### `populateTransactionECDSA` + +Populates missing properties meant for signing using an ECDSA private key: + +- Populates `from` using the address derived from the ECDSA private key. +- Populates `nonce` via `provider.getTransactionCount(tx.from, "pending")`. +- Populates `gasLimit` via `provider.estimateGas(tx)`. If `tx.from` is not EOA, the estimation is done with address +derived from the ECDSA private key. +- Populates `chainId` via `provider.getNetwork()`. +- Populates `type` with `utils.EIP712_TX_TYPE`. +- Populates `value` by converting to `bigint` if set, otherwise to `0n`. +- Populates `data` with `0x`. +- Populates `customData` with `{factoryDeps=[], gasPerPubdata=utils.DEFAULT_GAS_PER_PUBDATA_LIMIT}`. + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ------------------------------------- | ---------------------------------------------------------------------------------- | +| `tx` | `BytesLike` | The transaction that needs to be populated. | +| `secret` | `string` or `ethers.utils.SigningKey` | The ECDSA private key. | +| `provider` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | The provider is used to fetch data from the network if it is required for signing. | + +```ts +const populateTransactionECDSA: TransactionBuilder = async (tx, secret: string | utils.SigningKey, provider) +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); + +const populatedTx = await utils.populateTransactionECDSA( + { + chainId: 270, + to: "", + value: 7_000_000_000, + }, + PRIVATE_KEY, + provider +); +``` + +### `populateTransactionMultisigECDSA` + +Populates missing properties meant for signing using multiple ECDSA private keys. It +uses [`populateTransactionECDSA`](#populatetransactionecdsa), where the address of the first ECDSA key is +set as the `secret` argument. + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ----------------------------------------- | ---------------------------------------------------------------------------------- | +| `tx` | `BytesLike` | The transaction that needs to be populated. | +| `secret` | `string[]` or `ethers.utils.SigningKey[]` | The list of the ECDSA private keys used for populating the transaction. | +| `provider` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | The provider is used to fetch data from the network if it is required for signing. | + +```ts +const populateTransactionMultisigECDSA: TransactionBuilder = async (tx, secret: string[] | SigningKey[], provider) +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const PRIVATE_KEY1 = ""; +const PRIVATE_KEY2 = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); + +const populatedTx = await utils.populateTransactionMultisigECDSA( + { + chainId: 270, + to: "", + value: 7_000_000_000, + }, + [PRIVATE_KEY1, PRIVATE_KEY2], + provider +); +``` + ### `signPayloadWithECDSA` Signs the `payload` using an ECDSA private key. @@ -155,88 +240,3 @@ const typedDataHash = ethers.utils._TypedDataEncoder.hash( ); const signature = await utils.signPayloadWithMultipleECDSA(typedDataHash, [PRIVATE_KEY1, PRIVATE_KEY2]); ``` - -### `populateTransactionECDSA` - -Populates missing properties meant for signing using an ECDSA private key: - -- Populates `from` using the address derived from the ECDSA private key. -- Populates `nonce` via `provider.getTransactionCount(tx.from, "pending")`. -- Populates `gasLimit` via `provider.estimateGas(tx)`. If `tx.from` is not EOA, the estimation is done with address -derived from the ECDSA private key. -- Populates `chainId` via `provider.getNetwork()`. -- Populates `type` with `utils.EIP712_TX_TYPE`. -- Populates `value` by converting to `bigint` if set, otherwise to `0n`. -- Populates `data` with `0x`. -- Populates `customData` with `{factoryDeps=[], gasPerPubdata=utils.DEFAULT_GAS_PER_PUBDATA_LIMIT}`. - -#### Inputs - -| Parameter | Type | Description | -| ---------- | ------------------------------------- | ---------------------------------------------------------------------------------- | -| `tx` | `BytesLike` | The transaction that needs to be populated. | -| `secret` | `string` or `ethers.utils.SigningKey` | The ECDSA private key. | -| `provider` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | The provider is used to fetch data from the network if it is required for signing. | - -```ts -const populateTransactionECDSA: TransactionBuilder = async (tx, secret: string | utils.SigningKey, provider) -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const PRIVATE_KEY = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); - -const populatedTx = await utils.populateTransactionECDSA( - { - chainId: 270, - to: "", - value: 7_000_000_000, - }, - PRIVATE_KEY, - provider -); -``` - -### `populateTransactionMultisigECDSA` - -Populates missing properties meant for signing using multiple ECDSA private keys. It -uses [`populateTransactionECDSA`](#populatetransactionecdsa), where the address of the first ECDSA key is -set as the `secret` argument. - -#### Inputs - -| Parameter | Type | Description | -| ---------- | ----------------------------------------- | ---------------------------------------------------------------------------------- | -| `tx` | `BytesLike` | The transaction that needs to be populated. | -| `secret` | `string[]` or `ethers.utils.SigningKey[]` | The list of the ECDSA private keys used for populating the transaction. | -| `provider` | [`Provider`](/sdk/js/ethers/api/v5/providers/provider) | The provider is used to fetch data from the network if it is required for signing. | - -```ts -const populateTransactionMultisigECDSA: TransactionBuilder = async (tx, secret: string[] | SigningKey[], provider) -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const PRIVATE_KEY1 = ""; -const PRIVATE_KEY2 = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); - -const populatedTx = await utils.populateTransactionMultisigECDSA( - { - chainId: 270, - to: "", - value: 7_000_000_000, - }, - [PRIVATE_KEY1, PRIVATE_KEY2], - provider -); -``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/00.providers/01.provider.md b/content/sdk/10.js/00.ethers/05.api/20.v6/00.providers/01.provider.md index ccd43f13..4c1a7ff8 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/00.providers/01.provider.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/00.providers/01.provider.md @@ -6,35 +6,6 @@ tags: ["zksync", "providers", "integration"] Provider objects facilitate interaction with the ZKsync network, allowing users to manage transactions, estimate fees, and retrieve network information. - -### `constructor` - -Creates a ZKsync Era `Provider` object. - -**Parameters:** - -| Parameter | Type | Description | -| ---------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------- | -| `url?` | [`ethers.FetchRequest`](https://docs.ethers.org/v6/api/utils/fetching/#FetchRequest) | Network RPC URL. | -| `network?` | [`ethers.Networkish`](https://docs.ethers.org/v6/api/providers/#Networkish) | Network name, chain ID, or object with network details. | -| `options?` | `any` | Additional provider options. | - -```ts -constructor(url ? : ethers.FetchRequest | string, network ? : Networkish, options ? : any) -``` - -**Example:** - -```ts -import { Provider } from "zksync-ethers"; - -const provider = new Provider("https://sepolia.era.zksync.dev"); -``` - -The constructor for the `Provider` class creates an instance of the provider object, which connects your application to -the ZKsync Era network. The `url` parameter specifies the network RPC URL, the `network` -parameter allows you to define the network details, and `options` provides additional customization. - ### `broadcastTransaction` Overrides the Ethers implementation. @@ -53,11 +24,11 @@ async broadcastTransaction(signedTx: string): Promise ```ts import { Provider, types, Wallet } from "zksync-ethers"; - + const PRIVATE_KEY = ""; const provider = Provider.getDefaultProvider(types.Network.Sepolia); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const signedTx = await wallet.signTransaction({ to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", value: ethers.parseEther("0.01"), @@ -74,6 +45,58 @@ The `broadcastTransaction` method sends a signed transaction to the network. Thi a transaction that has already been signed by a wallet. The method returns a transaction response, which includes the transaction hash. +### `connectL2Bridge` + +Returns contract wrapper. If given address is shared bridge address it returns +Il2SharedBridge and if its legacy it returns Il2Bridge. + +#### Inputs + +| Parameter | Type | Description | +| --------------- |-----------| ------------------------------------------------- | +| `address` | 'Address' | The bridge address. | + +```ts +async connectL2Bridge(address: Address): Promise +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const l2Bridge = await provider.connectL2Bridge(""); +``` + +### `constructor` + +Creates a ZKsync Era `Provider` object. + +**Parameters:** + +| Parameter | Type | Description | +| ---------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------- | +| `url?` | [`ethers.FetchRequest`](https://docs.ethers.org/v6/api/utils/fetching/#FetchRequest) | Network RPC URL. | +| `network?` | [`ethers.Networkish`](https://docs.ethers.org/v6/api/providers/#Networkish) | Network name, chain ID, or object with network details. | +| `options?` | `any` | Additional provider options. | + +```ts +constructor(url ? : ethers.FetchRequest | string, network ? : Networkish, options ? : any) +``` + +**Example:** + +```ts +import { Provider } from "zksync-ethers"; + +const provider = new Provider("https://sepolia.era.zksync.dev"); +``` + +The constructor for the `Provider` class creates an instance of the provider object, which connects your application to +the ZKsync Era network. The `url` parameter specifies the network RPC URL, the `network` +parameter allows you to define the network details, and `options` provides additional customization. + ### `estimateFee` Returns an estimated [`Fee`](/sdk/js/ethers/api/v6/types#fee) for the requested transaction. @@ -92,7 +115,7 @@ async estimateFee(transaction: TransactionRequest): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const fee = await provider.estimateFee({ from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", @@ -124,7 +147,7 @@ async estimateGas(_tx: TransactionRequest): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasTokenApprove = await provider.estimateGas({ from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", @@ -155,7 +178,7 @@ async estimateGasL1(transaction: TransactionRequest): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasL1 = await provider.estimateGasL1({ from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", @@ -201,7 +224,7 @@ async estimateGasTransfer(transaction: { ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasTransfer = await provider.estimateGasTransfer({ token: utils.ETH_ADDRESS, @@ -247,7 +270,7 @@ async estimateGasWithdraw(transaction: { ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasWithdraw = await provider.estimateGasWithdraw({ token: utils.ETH_ADDRESS, @@ -290,7 +313,7 @@ async estimateL1ToL2Execute(transaction: { ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const gasL1ToL2 = await provider.estimateL1ToL2Execute({ contractAddress: await provider.getMainContractAddress(), @@ -322,7 +345,7 @@ async getAllAccountBalances(address: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const balances = await provider.getAllAccountBalances("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); console.log(`All balances: ${utils.toJSON(balances)}`); @@ -350,7 +373,7 @@ async getBalance(address: Address, blockTag?: BlockTag, tokenAddress?: Address) ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"; const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free @@ -372,7 +395,7 @@ async getBaseTokenContractAddress(): Promise
```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Base token: ${await provider.getBaseTokenContractAddress()}`); ``` @@ -396,7 +419,7 @@ async getBlock(blockHashOrBlockTag: BlockTag, includeTxs?: boolean): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Block details: ${utils.toJSON(await provider.getBlockDetails(90_000))}`); ``` @@ -440,7 +463,7 @@ async getBridgehubContractAddress(): Promise
```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Bridgehub: ${await provider.getBridgehubContractAddress()}`); ``` @@ -465,13 +488,13 @@ async getBytecodeByHash(bytecodeHash: BytesLike): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + // Bytecode hash can be computed by following these steps: // const testnetPaymasterBytecode = await provider.getCode(await provider.getTestnetPaymasterAddress()); // const testnetPaymasterBytecodeHash = ethers.hexlify(utils.hashBytecode(testnetPaymasterBytecode)); - + const testnetPaymasterBytecodeHash = "0x010000f16d2b10ddeb1c32f2c9d222eb1aea0f638ec94a81d4e916c627720e30"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Bytecode: ${await provider.getBytecodeByHash(testnetPaymasterBytecodeHash)}`); ``` @@ -498,7 +521,7 @@ async getConfirmedTokens(start: number = 0, limit: number = 255): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free console.log(`Contract account info: ${utils.toJSON(await provider.getContractAccountInfo(tokenAddress))}`); @@ -547,59 +570,11 @@ getDefaultBridgeAddresses(): Promise<{ ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Default bridges: ${utils.toJSON(await provider.getDefaultBridgeAddresses())}`); ``` -### `connectL2Bridge` - -Returns contract wrapper. If given address is shared bridge address it returns -Il2SharedBridge and if its legacy it returns Il2Bridge. - -#### Inputs - -| Parameter | Type | Description | -| --------------- |-----------| ------------------------------------------------- | -| `address` | 'Address' | The bridge address. | - -```ts -async connectL2Bridge(address: Address): Promise -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const l2Bridge = await provider.connectL2Bridge(""); -``` - -### `isL2BridgeLegacy` - -Returns true if passed bridge address is legacy and false if its shared bridge. - -#### Inputs - -| Parameter | Type | Description | -| --------------- |-----------| ------------------------------------------------- | -| `address` | 'Address' | The bridge address. | - -```ts -async isL2BridgeLegacy(address: Address): Promise -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const isBridgeLegacy = await provider.isL2BridgeLegacy(""); -console.log(isBridgeLegacy); -``` - ### `getDefaultProvider` Static method which returns a Provider object from the RPC URL or localhost. @@ -618,7 +593,7 @@ static getDefaultProvider(zksyncNetwork: ZkSyncNetwork = ZkSyncNetwork.Localhost ```ts import { Provider, types, utils } from "zksync-ethers"; - + const providerMainnet = Provider.getDefaultProvider(types.Network.Mainnet); const providerTestnet = Provider.getDefaultProvider(types.Network.Sepolia); const providerLocalnet = Provider.getDefaultProvider(types.Network.Localhost); @@ -639,7 +614,7 @@ async getFeeParams(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const feeParams = await provider.getFeeParams(); console.log(`Fee: ${utils.toJSON(feeParams)}`); @@ -663,7 +638,7 @@ async getFilterChanges(idx: bigint): Promise> ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const filter = await provider.newFilter({ address: utils.L2_ETH_TOKEN_ADDRESS, @@ -684,7 +659,7 @@ async getGasPrice(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Gas price: ${await provider.getGasPrice()}`); ``` @@ -710,7 +685,7 @@ async getL1BatchBlockRange(l1BatchNumber: number): Promise<[number, number] | nu ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const l1BatchNumber = await provider.getL1BatchNumber(); console.log(`L1 batch block range: ${utils.toJSON(await provider.getL1BatchBlockRange(l1BatchNumber))}`); @@ -736,7 +711,7 @@ async getL1BatchDetails(number: number): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const l1BatchNumber = await provider.getL1BatchNumber(); console.log(`L1 batch details: ${utils.toJSON(await provider.getL1BatchDetails(l1BatchNumber))}`); @@ -756,7 +731,7 @@ async getL1BatchNumber(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L1 batch number: ${await provider.getL1BatchNumber()}`); ``` @@ -779,7 +754,7 @@ async getL2TransactionFromPriorityOp(l1TxResponse: ethers.TransactionResponse): ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const l1Tx = "0xcca5411f3e514052f4a4ae1c2020badec6e0998adb52c09959c5f5ff15fba3a8"; @@ -810,7 +785,7 @@ async getLogProof(txHash: BytesLike, index ? : number): Promise L1 transaction can be used. // In this case, withdrawal transaction is used. @@ -836,7 +811,7 @@ async getLogs(filter: Filter | FilterByBlockHash): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Logs: ${utils.toJSON(await provider.getLogs({ fromBlock: 0, toBlock: 5, address: utils.L2_ETH_TOKEN_ADDRESS }))}`); ``` @@ -855,7 +830,7 @@ async getMainContractAddress(): Promise
```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Main contract: ${await provider.getMainContractAddress()}`); ``` @@ -884,7 +859,7 @@ async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); // Any L2 -> L1 transaction can be used. // In this case, withdrawal transaction is used. @@ -911,7 +886,7 @@ async getPriorityOpResponse(l1TxResponse: ethers.TransactionResponse): Promise

uint256) internal rawNonces; - + // Ensure the address is a 256-bit number by padding it // because rawNonces slot uses uint256 for mapping addresses and their nonces. const addressPadded = ethers.zeroPadValue(address, 32); - + // Convert the slot number to a hex string and pad it to 32 bytes. const slotPadded = ethers.zeroPadValue(ethers.toBeHex(0), 32); - + // Concatenate the padded address and slot number. const concatenated = addressPadded + slotPadded.slice(2); // slice to remove '0x' from the slotPadded - + // Hash the concatenated string using Keccak-256. const storageKey = ethers.keccak256(concatenated); - + const l1BatchNumber = await provider.getL1BatchNumber(); const storageProof = await provider.getProof(utils.NONCE_HOLDER_ADDRESS, [storageKey], l1BatchNumber); console.log(`Storage proof: ${utils.toJSON(storageProof)}`); @@ -989,7 +964,7 @@ async getProtocolVersion(id?: number): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Protocol version: ${await provider.getProtocolVersion()}`); ``` @@ -1015,7 +990,7 @@ async getRawBlockTransactions(number: number): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Raw block transactions: ${utils.toJSON(await provider.getRawBlockTransactions(90_000))}`); ``` @@ -1033,7 +1008,7 @@ async getTestnetPaymasterAddress(): Promise

```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`); ``` @@ -1041,7 +1016,7 @@ console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`) ### `getTransaction` Returns a specified L2 transaction response object by overriding the -[Ethers implementation](https://docs.ethers.org/v5/api/providers/provider/#Provider-getTransaction). +[Ethers implementation](https://docs.ethers.org/v6/api/providers/provider/#Provider-getTransaction). #### Inputs @@ -1057,12 +1032,12 @@ async getTransaction(txHash: string): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const TX_HASH = ""; const txHandle = await provider.getTransaction(TX_HASH); - + // Wait until the transaction is processed by the server. await txHandle.wait(); // Wait until the transaction is finalized. @@ -1090,9 +1065,9 @@ async getTransactionDetails(txHash: BytesLike): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const TX_HASH = ""; console.log(`Transaction details: ${utils.toJSON(await provider.getTransactionDetails(TX_HASH))}`); ``` @@ -1101,7 +1076,7 @@ console.log(`Transaction details: ${utils.toJSON(await provider.getTransactionDe Returns the transaction receipt from a given hash number. -[Ethers implementation.](https://docs.ethers.org/v5/api/providers/provider/#Provider-getTransactionReceipt) +[Ethers implementation.](https://docs.ethers.org/v6/api/providers/provider/#Provider-getTransactionReceipt) #### Inputs @@ -1117,7 +1092,7 @@ async getTransactionReceipt(txHash: string): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const TX_HASH = ""; console.log(`Transaction receipt: ${utils.toJSON(await provider.getTransactionReceipt(TX_HASH))}`); @@ -1141,9 +1116,9 @@ async getTransactionStatus(txHash: string): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const TX_HASH = ""; console.log(`Transaction status: ${utils.toJSON(await provider.getTransactionStatus(TX_HASH))}`); ``` @@ -1180,9 +1155,9 @@ Retrieve populated ETH transfer transaction. ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const tx = await provider.getTransferTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1196,11 +1171,11 @@ Retrieve populated ETH transfer transaction using paymaster to facilitate fee pa ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token - + const tx = await provider.getTransferTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1250,9 +1225,9 @@ Retrieve populated ETH withdrawal transactions. ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const tx = await provider.getWithdrawTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1266,11 +1241,11 @@ Retrieve populated ETH withdrawal transaction using paymaster to facilitate fee ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const token = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free const paymaster = "0x13D0D8550769f59aa241a41897D4859c87f7Dd46"; // Paymaster for Crown token - + const tx = await provider.getWithdrawTx({ token: utils.ETH_ADDRESS, amount: 7_000_000_000, @@ -1304,7 +1279,7 @@ async isBaseToken(token: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Is base token: ${await provider.isBaseToken("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` @@ -1321,11 +1296,35 @@ async isEthBasedChain(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`Is ETH based chain: ${await provider.isEthBasedChain()}`); ``` +### `isL2BridgeLegacy` + +Returns true if passed bridge address is legacy and false if its shared bridge. + +#### Inputs + +| Parameter | Type | Description | +| --------------- |-----------| ------------------------------------------------- | +| `address` | 'Address' | The bridge address. | + +```ts +async isL2BridgeLegacy(address: Address): Promise +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const isBridgeLegacy = await provider.isL2BridgeLegacy(""); +console.log(isBridgeLegacy); +``` + ### `l1ChainId` Returns the chain id of the underlying L1. @@ -1340,7 +1339,7 @@ async l1ChainId(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L1 chain ID: ${await provider.l1ChainId()}`); ``` @@ -1367,7 +1366,7 @@ async l1TokenAddress(token: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L1 token address: ${await provider.l1TokenAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b")}`); ``` @@ -1395,7 +1394,7 @@ async l2TokenAddress(token: Address): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`L2 token address: ${await provider.l2TokenAddress("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` @@ -1412,7 +1411,7 @@ async newBlockFilter(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`New block filter: ${await provider.newBlockFilter()}`); ``` @@ -1437,7 +1436,7 @@ async newFilter(filter: FilterByBlockHash | Filter): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log( `New filter: ${await provider.newFilter({ @@ -1462,7 +1461,7 @@ async newPendingTransactionsFilter(): Promise ```ts import { Provider, types, utils } from "zksync-ethers"; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); console.log(`New pending transaction filter: ${await provider.newPendingTransactionsFilter()}`); ``` @@ -1497,17 +1496,17 @@ async sendRawTransactionWithDetailedOutput(signedTx: string): Promise +async estimateFee(transaction: TransactionRequest): Promise ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -const TX_HASH = ""; -console.log(`Transaction receipt: ${utils.toJSON(await provider.getTransactionReceipt(TX_HASH))}`); +const fee = await provider.estimateFee + +({ + from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", + value: `0x${BigInt(7_000_000_000).toString(16)}`, +}); +console.log(`Fee: ${utils.toJSON(fee)}`); ``` -### `getTransaction` +### `estimateGasL1` -Returns the transaction for the given transaction hash. +Returns an estimate of the amount of gas required to submit a transaction from L1 to L2. #### Inputs -| Parameter | Type | Description | -| --------- | -------- | ----------------- | -| `txHash` | `string` | Transaction hash. | +| Parameter | Type | Description | +| ------------- | -------------------------------------------------------- | ---------------------- | +| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | ```ts -async getTransaction(txHash: string): Promise +async estimateGasL1(transaction: TransactionRequest): Promise ``` #### Example ```ts import { BrowserProvider } from "zksync-ethers"; - -const provider = new BrowserProvider(window.ethereum); - -const TX_HASH = ""; -const tx = await provider.getTransaction(TX_HASH); - -// Wait until the transaction is processed by the server. -await tx.wait(); -// Wait until the transaction is finalized. -await tx.waitFinalize(); -``` - -### `getBlock` - -Returns the block for the given block hash or block tag. - -#### Inputs - -| Parameter | Type | Description | -| --------------------- | ---------- | ----------------------------------------------------------- | -| `blockHashOrBlockTag` | `BlockTag` | Block tag for getting the balance on. | -| `includeTxs?` | `boolean` | Whether to fetch transactions that are in block. | - -```ts -async getBlock(blockHashOrBlockTag: BlockTag, includeTxs?: boolean): Promise -``` - -#### Example - -```ts -import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`Block: ${utils.toJSON(await provider.getBlock("latest", true))}`); +const gasL1 = await provider.estimateGasL1({ + from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + to: await provider.getMainContractAddress(), + value: 7_000_000_000, + customData: { + gasPerPubdata: 800, + }, +}); +console.log(`L1 gas: ${BigInt(gasL1)}`); ``` -### `getLogs` +### `getAllAccountBalances` -Returns the logs that match the given filter. +Returns all balances for confirmed tokens given by an account address. #### Inputs -| Parameter | Type | Description | -| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| `filter` | [`Filter`](https://docs.ethers.org/v6/api/providers/#Filter) or [`FilterByBlockHash`](https://docs.ethers.org/v6/api/providers/#FilterByBlockHash) | Filter query. | +| Parameter | Type | Description | +| --------- | --------- | ---------------- | +| `address` | `Address` | Account address. | ```ts -async getLogs(filter: Filter | FilterByBlockHash): Promise +async getAllAccountBalances(address: Address): Promise ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`Logs: ${utils.toJSON(await provider.getLogs({ fromBlock: 0, toBlock: 5, address: utils.L2_ETH_TOKEN_ADDRESS }))}`); +const balances = await provider.getAllAccountBalances("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); +console.log(`All balances: ${utils.toJSON(balances)}`); ``` ### `getBalance` @@ -153,7 +137,7 @@ async getBalance(address: Address, blockTag?: BlockTag, tokenAddress?: Address): ```ts import { BrowserProvider } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); const account = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"; const tokenAddress = "0x927488F48ffbc32112F1fF721759649A89721F8F"; // Crown token which can be minted for free @@ -161,134 +145,166 @@ console.log(`ETH balance: ${await provider.getBalance(account)}`); console.log(`Token balance: ${await provider.getBalance(account, "latest", tokenAddress)}`); ``` -### `l2TokenAddress` - -Returns the L2 token address equivalent for a given L1 token address. - -#### Inputs +### `getBaseTokenContractAddress` -| Parameter | Type | Description | -| --------- | --------- | ------------------------------- | -| `token` | `Address` | The address of the token on L1. | +Returns the L1 base token address. ```ts -async l2TokenAddress(token: Address): Promise +async getBaseTokenContractAddress(): Promise
``` #### Example ```ts import { BrowserProvider } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`L2 token address: ${await provider.l2TokenAddress("0x5C221E77624690fff6dd741493D735a17716c26B")}`); +console.log(`Base token: ${await provider.getBaseTokenContractAddress()}`); ``` -### `l1TokenAddress` +### `getBlock` -Returns the L1 token address equivalent for a given L2 token address. +Returns the block for the given block hash or block tag. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ------------------------------- | -| `token` | `Address` | The address of the token on L2. | +| Parameter | Type | Description | +| --------------------- | ---------- | ----------------------------------------------------------- | +| `blockHashOrBlockTag` | `BlockTag` | Block tag for getting the balance on. | +| `includeTxs?` | `boolean` | Whether to fetch transactions that are in block. | ```ts -async l1TokenAddress(token: Address): Promise +async getBlock(blockHashOrBlockTag: BlockTag, includeTxs?: boolean): Promise ``` #### Example ```ts -import { BrowserProvider } from "zksync-ethers"; - +import { BrowserProvider, utils } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -console.log(`L1 token address: ${await provider.l1TokenAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b")}`); +console.log(`Block: ${utils.toJSON(await provider.getBlock("latest", true))}`); ``` -### `getProtocolVersion` +### `getBlockDetails` -Returns the protocol version. +Returns additional ZKsync-specific information about the L2 block. #### Inputs -| Parameter | Type | Description | -|-----------| -------- |---------------------------------| -| `id?` | `number` | Specific version ID (optional). | +| Parameter | Type | Description | +| --------- | -------- | ------------- | +| `number` | `number` | Block number. | ```ts -async getProtocolVersion(id?: number): Promise +async getBlockDetails(number: number): Promise ``` #### Example ```ts -import { BrowserProvider } from "zksync-ethers"; +import { BrowserProvider, utils } from "zksync + +-ethers"; + +const provider = new BrowserProvider(window.ethereum); +console.log(`Block details: ${utils.toJSON(await provider.getBlockDetails(90_000))}`); +``` + +### `getBridgehubContractAddress` + +Returns the Bridgehub smart contract address. + +```ts +async getBridgehubContractAddress(): Promise
+``` + +#### Example +```ts +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -console.log(`Protocol version: ${await provider.getProtocolVersion()}`); +console.log(`Bridgehub: ${await provider.getBridgehubContractAddress()}`); ``` -### `estimateGasL1` +### `getBytecodeByHash` -Returns an estimate of the amount of gas required to submit a transaction from L1 to L2. +Returns bytecode of a contract given by its hash. #### Inputs -| Parameter | Type | Description | -| ------------- | -------------------------------------------------------- | ---------------------- | -| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | +| Parameter | Type | Description | +| -------------- | ----------- | -------------- | +| `bytecodeHash` | `BytesLike` | Bytecode hash. | ```ts -async estimateGasL1(transaction: TransactionRequest): Promise +async getBytecodeByHash(bytecodeHash: BytesLike): Promise ``` #### Example ```ts -import { BrowserProvider } from "zksync-ethers"; - +import { BrowserProvider, utils } from "zksync-ethers"; + +// Bytecode hash can be computed by following these steps: +// const testnetPaymasterBytecode = await provider.getCode(await provider.getTestnetPaymasterAddress()); +// const testnetPaymasterBytecodeHash = ethers.hexlify(utils.hashBytecode(testnetPaymasterBytecode)); + +const testnetPaymasterBytecodeHash = "0x010000f16d2b10ddeb1c32f2c9d222eb1aea0f638ec94a81d4e916c627720e30"; + const provider = new BrowserProvider(window.ethereum); -const gasL1 = await provider.estimateGasL1({ - from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", - to: await provider.getMainContractAddress(), - value: 7_000_000_000, - customData: { - gasPerPubdata: 800, - }, -}); -console.log(`L1 gas: ${BigInt(gasL1)}`); +console.log(`Bytecode: ${await provider.getBytecodeByHash(testnetPaymasterBytecodeHash)}`); ``` -### `estimateFee` +### `getConfirmedTokens` -Returns an estimated fee for a requested transaction. +Returns confirmed tokens bridged to ZKsync Era via the official bridge. #### Inputs -| Parameter | Type | Description | -| ------------- | ------------------------------------------------------------------------------------ | ---------------------- | -| `transaction` | [`TransactionRequest`](https://docs.ethers.org/v6/api/providers/#TransactionRequest) | Transaction request. | +| Parameter | Type | Description | +|-----------| --------- |----------------------------------------------------| +| `start` | `Address` | The token id from which to start. Default 0. | +| `limit` | `Address` | The maximum number of tokens to list. Default 255. | ```ts -async estimateFee(transaction: TransactionRequest): Promise +async getConfirmedTokens(start = 0, limit = 255): Promise ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -const fee = await provider.estimateFee +const tokens = await provider.getConfirmedTokens(); +console.log(`Confirmed tokens: ${utils.toJSON(tokens)}`); +``` -({ - from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", - to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", - value: `0x${BigInt(7_000_000_000).toString(16)}`, -}); -console.log(`Fee: ${utils.toJSON(fee)}`); +### `getDefaultBridgeAddresses` + +Returns the addresses of the default ZKsync Era bridge contracts on both L1 and L2. + +```ts +async getDefaultBridgeAddresses(): Promise<{ + erc20L1: string; + erc20L2: string; + wethL1: string; + wethL2: string; + sharedL1: string; + sharedL2: string; +}> +``` + +#### Example + +```ts +import { BrowserProvider, utils } from "zksync-ethers"; + +const provider = new BrowserProvider(window.ethereum); +const bridgeAddresses = await provider.getDefaultBridgeAddresses(); +console.log(`Default bridges: ${utils.toJSON(bridgeAddresses)}`); ``` ### `getFeeParams` @@ -303,7 +319,7 @@ async getFeeParams(): Promise ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); const feeParams = await provider.getFeeParams(); console.log(`Fee: ${utils.toJSON(feeParams)}`); @@ -321,326 +337,315 @@ async getGasPrice(): Promise ```ts import { BrowserProvider } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); console.log(`Gas price: ${await provider.getGasPrice()}`); ``` -### `getLogProof` +### `getL1BatchBlockRange` -Returns the proof for a transaction's L2 to L1 log. +Returns the range of blocks contained within a batch given by batch number. #### Inputs -| Parameter | Type | Description | -| --------- | ----------- | ---------------------------------------------------------------- | -| `txHash` | `BytesLike` | Hash of the L2 transaction the L2 to L1 log was produced within. | -| `index?` | `number` | The index of the L2 to L1 log in the transaction. | +| Parameter | Type | Description | +| --------------- | -------- | ---------------- | +| `l1BatchNumber` | `number` | L1 batch number. | ```ts -async getLogProof(txHash: BytesLike, index?: number): Promise +async getL1BatchBlockRange(l1BatchNumber: number): Promise<[number, number] | null> ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; -console.log(`Log ${utils.toJSON(await provider.getLogProof(tx, 0))}`); +const l1BatchNumber = await provider.getL1BatchNumber(); +console.log(`L1 batch block range: ${utils.toJSON(await provider.getL1BatchBlockRange(l1BatchNumber))}`); ``` -### `getL1BatchBlockRange` +### `getL1BatchDetails` -Returns the range of blocks contained within a batch given by batch number. +Returns data pertaining to a given batch. #### Inputs -| Parameter | Type | Description | -| --------------- | -------- | ---------------- | -| `l1BatchNumber` | `number` | L1 batch number. | +| Parameter | Type | Description | +| --------- | -------- | ---------------- | +| `number` | `number` | L1 batch number. | ```ts -async getL1BatchBlockRange(l1BatchNumber: number): Promise<[number, number] | null> +async getL1BatchDetails(number: number): Promise ``` #### Example +#### `getL1BatchDetails` + ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); const l1BatchNumber = await provider.getL1BatchNumber(); -console.log(`L1 batch block range: ${utils.toJSON(await provider.getL1BatchBlockRange(l1BatchNumber))}`); -``` - -### `getMainContractAddress` - -Returns the main ZKsync Era smart contract address. - -```ts -async getMainContractAddress(): Promise
-``` - -#### Example - -```ts -import { BrowserProvider } from "zksync-ethers"; - -const provider = new BrowserProvider(window.ethereum); -console.log(`Main contract: ${await provider.getMainContractAddress()}`); +console.log(`L1 batch details: ${utils.toJSON(await provider.getL1BatchDetails(l1BatchNumber))}`); ``` -### `getBridgehubContractAddress` +### `getL1BatchNumber` -Returns the Bridgehub smart contract address. +Returns the latest L1 batch number. ```ts -async getBridgehubContractAddress(): Promise
+async getL1BatchNumber(): Promise ``` #### Example ```ts import { BrowserProvider } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`Bridgehub: ${await provider.getBridgehubContractAddress()}`); -``` - -### `getBaseTokenContractAddress` - -Returns the L1 base token address. - -```ts -async getBaseTokenContractAddress(): Promise
+console.log(`L1 batch number: ${await provider.getL1BatchNumber()}`); ``` -#### Example - -```ts -import { BrowserProvider } from "zksync-ethers"; +### `getLogProof` -const provider = new BrowserProvider(window.ethereum); -console.log(`Base token: ${await provider.getBaseTokenContractAddress()}`); -``` +Returns the proof for a transaction's L2 to L1 log. -### `isEthBasedChain` +#### Inputs -Returns whether the chain is ETH-based. +| Parameter | Type | Description | +| --------- | ----------- | ---------------------------------------------------------------- | +| `txHash` | `BytesLike` | Hash of the L2 transaction the L2 to L1 log was produced within. | +| `index?` | `number` | The index of the L2 to L1 log in the transaction. | ```ts -async isEthBasedChain(): Promise +async getLogProof(txHash: BytesLike, index?: number): Promise ``` #### Example ```ts -import { BrowserProvider } from "zksync-ethers"; - +import { BrowserProvider, utils } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -console.log(`Is ETH based chain: ${await provider.isEthBasedChain()}`); +const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; +console.log(`Log ${utils.toJSON(await provider.getLogProof(tx, 0))}`); ``` -### `isBaseToken` +### `getLogs` -Returns whether the `token` is the base token. +Returns the logs that match the given filter. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ------------------------- | -| `token` | `Address` | The address of the token. | +| Parameter | Type | Description | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | +| `filter` | [`Filter`](https://docs.ethers.org/v6/api/providers/#Filter) or [`FilterByBlockHash`](https://docs.ethers.org/v6/api/providers/#FilterByBlockHash) | Filter query. | ```ts -async isBaseToken(token: Address): Promise +async getLogs(filter: Filter | FilterByBlockHash): Promise ``` #### Example ```ts -import { BrowserProvider } from "zksync-ethers"; - +import { BrowserProvider, utils } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -console.log(`Is base token: ${await provider.isBaseToken("0x5C221E77624690fff6dd741493D735a17716c26B")}`); +console.log(`Logs: ${utils.toJSON(await provider.getLogs({ fromBlock: 0, toBlock: 5, address: utils.L2_ETH_TOKEN_ADDRESS }))}`); ``` -### `getTestnetPaymasterAddress` +### `getMainContractAddress` -Returns the testnet paymaster address if available, or `null`. +Returns the main ZKsync Era smart contract address. ```ts -async getTestnetPaymasterAddress(): Promise
+async getMainContractAddress(): Promise
``` #### Example ```ts import { BrowserProvider } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`); +console.log(`Main contract: ${await provider.getMainContractAddress()}`); ``` -### `getDefaultBridgeAddresses` +### `getProof` -Returns the addresses of the default ZKsync Era bridge contracts on both L1 and L2. +Returns Merkle proofs for one or more storage values at the specified account. + +#### Inputs + +| Parameter | Type | Description | +| --------------- | ---------- | ----------------------------------------------------------------------------------------------- | +| `address` | `Address` | The account to fetch storage values and proofs for. | +| `keys` | `string[]` | Vector of storage keys in the account. | +| `l1BatchNumber` | `number` | Number of the L1 batch specifying the point in time at which the requested values are returned. | ```ts -async getDefaultBridgeAddresses(): Promise<{ - erc20L1: string; - erc20L2: string; - wethL1: string; - wethL2: string; - sharedL1: string; - sharedL2: string; -}> +async getProof(address: Address, keys: string[], l1BatchNumber: number): Promise ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - +import { ethers } from "ethers"; + const provider = new BrowserProvider(window.ethereum); -const bridgeAddresses = await provider.getDefaultBridgeAddresses(); -console.log(`Default bridges: ${utils.toJSON(bridgeAddresses)}`); +const address = "0x082b1BB53fE43810f646dDd71AA2AB201b4C6b04"; + +// Fetching the storage proof for rawNonces storage slot in NonceHolder system contract. +// mapping(uint256 => uint256) internal rawNonces; + +// Ensure the address is a 256-bit number by padding it +// because rawNonces slot uses uint256 for mapping addresses and their nonces. +const addressPadded = ethers.zeroPadValue(address, 32); + +// Convert the slot number to a hex string and pad it to 32 bytes. +const slotPadded = ethers.zeroPadValue(ethers.toBeHex(0), 32); + +// Concatenate the padded address and slot number. +const concatenated = addressPadded + slotPadded.slice(2); // slice to remove '0x' from the slotPadded + +// Hash the concatenated string using Keccak-256. +const storageKey = ethers.keccak256(concatenated); + +const l1BatchNumber = await provider.getL1BatchNumber(); +const proof = await provider.getProof(address, [storageKey], l1BatchNumber); +console.log(`Proof: ${utils.toJSON(proof)}`); ``` -### `getAllAccountBalances` +### `getProtocolVersion` -Returns all balances for confirmed tokens given by an account address. +Returns the protocol version. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ---------------- | -| `address` | `Address` | Account address. | +| Parameter | Type | Description | +|-----------| -------- |---------------------------------| +| `id?` | `number` | Specific version ID (optional). | ```ts -async getAllAccountBalances(address: Address): Promise +async getProtocolVersion(id?: number): Promise ``` #### Example ```ts -import { BrowserProvider, utils } from "zksync-ethers"; - +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -const balances = await provider.getAllAccountBalances("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); -console.log(`All balances: ${utils.toJSON(balances)}`); +console.log(`Protocol version: ${await provider.getProtocolVersion()}`); ``` -### `getConfirmedTokens` +### `getRawBlockTransactions` -Returns confirmed tokens bridged to ZKsync Era via the official bridge. +Returns data of transactions in a block. #### Inputs -| Parameter | Type | Description | -|-----------| --------- |----------------------------------------------------| -| `start` | `Address` | The token id from which to start. Default 0. | -| `limit` | `Address` | The maximum number of tokens to list. Default 255. | +| Parameter | Type | Description | +| --------- | -------- | ------------- | +| `number` | `number` | Block number. | ```ts -async getConfirmedTokens(start = 0, limit = 255): Promise +async getRawBlockTransactions(number: number): Promise ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -const tokens = await provider.getConfirmedTokens(); -console.log(`Confirmed tokens: ${utils.toJSON(tokens)}`); +console.log(`Raw block transactions: ${utils.toJSON(await provider.getRawBlockTransactions(90_000))}`); ``` -### `l1ChainId` +### `getSigner` -Returns the L1 chain ID. +Returns a signer object for the provider. -```ts -async l1ChainId(): Promise -``` +#### Inputs -#### Example +| Parameter | Type | Description | +| --------- | --------- | ---------------- | +| `address?` | `Address` | Account address. | ```ts -import { BrowserProvider } from "zksync-ethers"; - -const provider = new BrowserProvider(window.ethereum); -const l1ChainId = await provider.l1ChainId(); -console.log(`All balances: ${l1ChainId}`); +async getSigner(address?: Address): Promise ``` -### `getL1BatchNumber` - -Returns the latest L1 batch number. +#### Example ```ts -async getL1BatchNumber(): Promise +import { BrowserProvider, Wallet } from "zksync-ethers"; + +const provider = new BrowserProvider(window.ethereum); +const signer = await provider.getSigner(); + +// Verify that signer matches the expected wallet address. +console.log(`Signer address: ${await signer.getAddress()}`); ``` #### Example ```ts import { BrowserProvider } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`L1 batch number: ${await provider.getL1BatchNumber()}`); +console.log(`L2 token address: ${await provider.l2TokenAddress("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` -### `getL1BatchDetails` - -Returns data pertaining to a given batch. - -#### Inputs +### `getTestnetPaymasterAddress` -| Parameter | Type | Description | -| --------- | -------- | ---------------- | -| `number` | `number` | L1 batch number. | +Returns the testnet paymaster address if available, or `null`. ```ts -async getL1BatchDetails(number: number): Promise +async getTestnetPaymasterAddress(): Promise
``` #### Example -#### `getL1BatchDetails` - ```ts -import { BrowserProvider, utils } from "zksync-ethers"; - +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -const l1BatchNumber = await provider.getL1BatchNumber(); -console.log(`L1 batch details: ${utils.toJSON(await provider.getL1BatchDetails(l1BatchNumber))}`); +console.log(`Testnet paymaster: ${await provider.getTestnetPaymasterAddress()}`); ``` -### `getBlockDetails` +### `getTransaction` -Returns additional ZKsync-specific information about the L2 block. +Returns the transaction for the given transaction hash. #### Inputs -| Parameter | Type | Description | -| --------- | -------- | ------------- | -| `number` | `number` | Block number. | +| Parameter | Type | Description | +| --------- | -------- | ----------------- | +| `txHash` | `string` | Transaction hash. | ```ts -async getBlockDetails(number: number): Promise +async getTransaction(txHash: string): Promise ``` #### Example ```ts -import { BrowserProvider, utils } from "zksync - --ethers"; - +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -console.log(`Block details: ${utils.toJSON(await provider.getBlockDetails(90_000))}`); + +const TX_HASH = ""; +const tx = await provider.getTransaction(TX_HASH); + +// Wait until the transaction is processed by the server. +await tx.wait(); +// Wait until the transaction is finalized. +await tx.waitFinalize(); ``` ### `getTransactionDetails` @@ -661,133 +666,128 @@ async getTransactionDetails(txHash: BytesLike): Promise ```ts import { BrowserProvider, utils } from "zksync-ethers"; - + const provider = new BrowserProvider(window.ethereum); - + const TX_HASH = ""; console.log(`Transaction details: ${utils.toJSON(await provider.getTransactionDetails(TX_HASH))}`); ``` -### `getBytecodeByHash` +### `getTransactionReceipt` -Returns bytecode of a contract given by its hash. +Returns the transaction receipt for the given transaction hash. #### Inputs -| Parameter | Type | Description | -| -------------- | ----------- | -------------- | -| `bytecodeHash` | `BytesLike` | Bytecode hash. | +| Parameter | Type | Description | +| --------- | -------- | ----------------- | +| `txHash` | `string` | Transaction hash. | ```ts -async getBytecodeByHash(bytecodeHash: BytesLike): Promise +async getTransactionReceipt(txHash: string): Promise ``` #### Example ```ts import { BrowserProvider, utils } from "zksync-ethers"; - -// Bytecode hash can be computed by following these steps: -// const testnetPaymasterBytecode = await provider.getCode(await provider.getTestnetPaymasterAddress()); -// const testnetPaymasterBytecodeHash = ethers.hexlify(utils.hashBytecode(testnetPaymasterBytecode)); - -const testnetPaymasterBytecodeHash = "0x010000f16d2b10ddeb1c32f2c9d222eb1aea0f638ec94a81d4e916c627720e30"; - + const provider = new BrowserProvider(window.ethereum); -console.log(`Bytecode: ${await provider.getBytecodeByHash(testnetPaymasterBytecodeHash)}`); +const TX_HASH = ""; +console.log(`Transaction receipt: ${utils.toJSON(await provider.getTransactionReceipt(TX_HASH))}`); ``` -### `getRawBlockTransactions` +### `isBaseToken` -Returns data of transactions in a block. +Returns whether the `token` is the base token. #### Inputs -| Parameter | Type | Description | -| --------- | -------- | ------------- | -| `number` | `number` | Block number. | +| Parameter | Type | Description | +| --------- | --------- | ------------------------- | +| `token` | `Address` | The address of the token. | ```ts -async getRawBlockTransactions(number: number): Promise +async isBaseToken(token: Address): Promise ``` #### Example ```ts -import { BrowserProvider, utils } from "zksync-ethers"; - +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -console.log(`Raw block transactions: ${utils.toJSON(await provider.getRawBlockTransactions(90_000))}`); +console.log(`Is base token: ${await provider.isBaseToken("0x5C221E77624690fff6dd741493D735a17716c26B")}`); ``` -### `getProof` - -Returns Merkle proofs for one or more storage values at the specified account. - -#### Inputs +### `isEthBasedChain` -| Parameter | Type | Description | -| --------------- | ---------- | ----------------------------------------------------------------------------------------------- | -| `address` | `Address` | The account to fetch storage values and proofs for. | -| `keys` | `string[]` | Vector of storage keys in the account. | -| `l1BatchNumber` | `number` | Number of the L1 batch specifying the point in time at which the requested values are returned. | +Returns whether the chain is ETH-based. ```ts -async getProof(address: Address, keys: string[], l1BatchNumber: number): Promise +async isEthBasedChain(): Promise ``` #### Example ```ts -import { BrowserProvider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -const address = "0x082b1BB53fE43810f646dDd71AA2AB201b4C6b04"; - -// Fetching the storage proof for rawNonces storage slot in NonceHolder system contract. -// mapping(uint256 => uint256) internal rawNonces; +console.log(`Is ETH based chain: ${await provider.isEthBasedChain()}`); +``` -// Ensure the address is a 256-bit number by padding it -// because rawNonces slot uses uint256 for mapping addresses and their nonces. -const addressPadded = ethers.zeroPadValue(address, 32); +### `l1ChainId` -// Convert the slot number to a hex string and pad it to 32 bytes. -const slotPadded = ethers.zeroPadValue(ethers.toBeHex(0), 32); +Returns the L1 chain ID. -// Concatenate the padded address and slot number. -const concatenated = addressPadded + slotPadded.slice(2); // slice to remove '0x' from the slotPadded +```ts +async l1ChainId(): Promise +``` -// Hash the concatenated string using Keccak-256. -const storageKey = ethers.keccak256(concatenated); +#### Example -const l1BatchNumber = await provider.getL1BatchNumber(); -const proof = await provider.getProof(address, [storageKey], l1BatchNumber); -console.log(`Proof: ${utils.toJSON(proof)}`); +```ts +import { BrowserProvider } from "zksync-ethers"; + +const provider = new BrowserProvider(window.ethereum); +const l1ChainId = await provider.l1ChainId(); +console.log(`All balances: ${l1ChainId}`); ``` -### `getSigner` +### `l1TokenAddress` -Returns a signer object for the provider. +Returns the L1 token address equivalent for a given L2 token address. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ---------------- | -| `address?` | `Address` | Account address. | +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `token` | `Address` | The address of the token on L2. | ```ts -async getSigner(address?: Address): Promise +async l1TokenAddress(token: Address): Promise ``` #### Example ```ts -import { BrowserProvider, Wallet } from "zksync-ethers"; - +import { BrowserProvider } from "zksync-ethers"; + const provider = new BrowserProvider(window.ethereum); -const signer = await provider.getSigner(); +console.log(`L1 token address: ${await provider.l1TokenAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b")}`); +``` -// Verify that signer matches the expected wallet address. -console.log(`Signer address: ${await signer.getAddress()}`); +### `l2TokenAddress` + +Returns the L2 token address equivalent for a given L1 token address. + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `token` | `Address` | The address of the token on L1. | + +```ts +async l2TokenAddress(token: Address): Promise ``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/01.wallet.md b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/01.wallet.md index 65145015..0684627d 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/01.wallet.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/01.wallet.md @@ -6,18 +6,24 @@ tags: ["zksync", "wallet", "integration", "creation", "management"] The Wallet module provides functionalities for integrating, creating, and managing wallets within the ZKsync ecosystem. -### `constructor` +### `approveERC20` + +Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. #### Inputs -| Parameter | Type | Description | -| ------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | -| `privateKey` | `string` or [`ethers.SigningKey`](https://docs.ethers.org/v6/api/crypto/#SigningKey) | The private key of the Ethereum account. | -| `providerL2?` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) | A ZKsync node provider. Needed for interaction with ZKsync. | -| `providerL1?` | [`ethers.Provider`](https://docs.ethers.org/v6/api/providers/#Provider) | An Ethereum node provider. Needed for interaction with L1. | +| Parameter | Type | Description | +| ------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| `token` | `Address` | The Ethereum address of the token. | +| `amount` | `BigNumberish` | The amount of the token to be approved. | +| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -constructor(privateKey: string | ethers.SigningKey, providerL2?: Provider, providerL1?: ethers.Provider) +async approveERC20( + token: Address, + amount: BigNumberish, + overrides?: ethers.Overrides & { bridgeAddress?: Address } +): Promise ``` #### Example @@ -25,31 +31,33 @@ constructor(privateKey: string | ethers.SigningKey, providerL2?: Provider, provi ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 txHandle = await wallet.approveERC20(tokenL1, "10000000"); + +await txHandle.wait(); ``` -::callout{icon="i-heroicons-exclamation-triangle" color="amber"} -For development and testing, it is recommended to use burner wallets. Avoid using real private keys to prevent security risks. -:: - -### `fromMnemonic` +### `claimFailedDeposit` -Creates a `Wallet` with the `provider` as L1 provider and a private key that is built from the `mnemonic` passphrase. +The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. +If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` +method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. #### Inputs -| Parameter | Type | Description | -| ----------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------- | -| `mnemonic` | `string` | The mnemonic of the private key. | -| `provider?` | [`ethers.Provider`](https://docs.ethers.org/v6/api/providers/#Provider) | An Ethereum node provider. Needed for interaction with L1. | +| Parameter | Type | Description | +| ----------- | --------- | ---------------------------------------------- | +| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | ```ts -static fromMnemonic(mnemonic: string, provider?: ethers.Provider): Wallet +async claimFailedDeposit(depositHash: BytesLike): Promise ``` #### Example @@ -57,60 +65,15 @@ static fromMnemonic(mnemonic: string, provider?: ethers.Provider): Wallet ```ts 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 PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); -const wallet = Wallet.fromMnemonic(MNEMONIC, ethProvider); -``` - -### `fromEncryptedJson` - -Creates a `Wallet` from encrypted `json` file using provided `password`. - -#### Inputs - -| Parameter | Type | Description | -| ----------- | ------------------------ | -------------------------------------------------------------------------------------------------------------- | -| `json` | `string` | Encrypted json file. | -| `password` | `string` or `Uint8Array` | Password for encrypted json file. | -| `callback?` | `ProgressCallback` | If callback is provided, it is called periodically during decryption so that any UI can be updated. | - -```ts -static async fromEncryptedJson(json: string, password: string | Uint8Array, callback? : ProgressCallback): Promise -``` - -#### Example - -```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import * as fs from "fs"; - -const wallet = await Wallet.fromEncryptedJson(fs.readFileSync("wallet.json", "utf8"), "password"); -``` - -### `fromEncryptedJsonSync` - -Creates a `Wallet` from encrypted `json` file using provided `password`. - -#### Inputs - -| Parameter | Type | Description | -| ---------- | ------------------------ | --------------------------------- | -| `json` | `string` | Encrypted json file. | -| `password` | `string` or `Uint8Array` | Password for encrypted json file. | - -```ts -static fromEncryptedJsonSync(json: string, password: string | Uint8Array): Wallet -``` - -#### Example - -```ts -import { Wallet } from "zksync-ethers"; -import * as fs from "fs"; - -const wallet = Wallet.fromEncryptedJsonSync(fs.readFileSync("tests/files/wallet.json", "utf8"), "password"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const FAILED_DEPOSIT_HASH = ""; +const claimFailedDepositHandle = await wallet.claimFailedDeposit(FAILED_DEPOSIT_HASH); ``` ### `connect` @@ -132,10 +95,10 @@ Wallet.connect(provider:Provider): Wallet ```ts import { Wallet, Provider, types } from "zksync-ethers"; - + const PRIVATE_KEY = ""; const unconnectedWallet = new Wallet(PRIVATE_KEY); - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const wallet = unconnectedWallet.connect(provider); ``` @@ -165,10 +128,10 @@ Wallet.connectToL1(provider: ethers.Provider): Wallet ```ts import { Wallet } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; const unconnectedWallet = new Wallet(PRIVATE_KEY); - + const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = unconnectedWallet.connectToL1(ethProvider); ``` @@ -179,12 +142,18 @@ It is possible to chain `connect` and `connectToL1` methods: const wallet = unconnectedWallet.connect(zkSyncProvider).connectToL1(ethProvider); ``` -### `getMainContract` +### `constructor` -Returns `Contract` wrapper of the ZKsync smart contract. +#### Inputs + +| Parameter | Type | Description | +| ------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | +| `privateKey` | `string` or [`ethers.SigningKey`](https://docs.ethers.org/v6/api/crypto/#SigningKey) | The private key of the Ethereum account. | +| `providerL2?` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) | A ZKsync node provider. Needed for interaction with ZKsync. | +| `providerL1?` | [`ethers.Provider`](https://docs.ethers.org/v6/api/providers/#Provider) | An Ethereum node provider. Needed for interaction with L1. | ```ts -async getMainContract(): Promise +constructor(privateKey: string | ethers.SigningKey, providerL2?: Provider, providerL1?: ethers.Provider) ``` #### Example @@ -192,129 +161,219 @@ async getMainContract(): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - -console.log(`Main contract: ${await wallet.getMainContract()}`); ``` -### `getBridgehubContract` +::callout{icon="i-heroicons-exclamation-triangle" color="amber"} +For development and testing, it is recommended to use burner wallets. Avoid using real private keys to prevent security risks. +:: -Returns `Contract` wrapper of the Bridgehub smart contract. +### `deposit` + +Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. +The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the +specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). +In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` +can be enabled to perform token approval. +If there are already enough approved tokens for the L1 bridge, token approval will be skipped. +To check the amount of approved tokens for a specific bridge, +use the [`allowanceL1`](/sdk/js/ethers/api/v6/accounts/wallet#getallowancel1) method. + +#### Inputs + +| Parameter | Type | Description | +|-------------------------------------| ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveBaseOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | ```ts -async getBridgehubContract(): Promise +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 ``` #### Example +Deposit ETH on ETH-based chain. + ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); -``` - -### `getL1BridgeContracts` - -Returns L1 bridge contracts. - -```ts -async getL1BridgeContracts(): Promise<{ - erc20: IL1ERC20Bridge; - weth: IL1ERC20Bridge; - shared: IL1SharedBridge; -}> + +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. ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); -``` - -### `getL2BridgeContracts` - -Returns L2 bridge contracts. - -```ts -async getL2BridgeContracts(): Promise<{ - erc20: IL2Bridge; - weth: IL2Bridge; - shared: IL2Bridge; -}> + +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. ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); -``` - -### `getAddress` - -Returns the wallet address. - -```ts -async getAddress(): Promise
; + +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. ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); +``` -console.log(`Address: ${await wallet.getAddress()}`); +Deposit non-base token on non-ETH-based chain. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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(); ``` -### `getBalance` +### `estimateGasDeposit` -Returns the amount of the token the `Wallet` has. +Estimates the amount of gas required for a deposit transaction on L1 network. +Gas of approving ERC20 token is not included in estimation. #### Inputs -| Parameter | Type | Description | -| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | -| `token?` | `Address` | The address of the token. ETH by default. | -| `blockTag` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Parameter | Type | Description | +| -------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +async estimateGasDeposit(transaction: + token: Address; + amount: BigNumberish; + to?: Address; + operatorTip?: BigNumberish; + bridgeAddress?: Address; + customBridgeData?: BytesLike; + l2GasLimit?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.Overrides; + }): Promise ``` #### Example @@ -322,56 +381,82 @@ async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +estimateGasRequestExecute(transaction: { + contractAddress: Address; + calldata: string; + l2GasLimit?: BigNumberish; + mintValue?: BigNumberish; + l2Value?: BigNumberish; + factoryDeps?: BytesLike[]; + operatorTip?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: Overrides; +}): Promise ``` #### Example ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - +const CONTRACT_ADDRESS = ""; + 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)}`); + +const gas = await wallet.estimateGasRequestExecute({ + contractAddress: await provider.getMainContractAddress(), + calldata: "0x", + l2Value: 7_000_000_000, +}); +console.log(`Gas: ${gas}`); ``` -### `getAllBalances` +### `ethWallet` -Returns all balances for confirmed tokens given by an account address. +You can get an `ethers.Wallet` object with the same private key with `ethWallet()` method. ```ts -async getAllBalances(): Promise +ethWallet(): ethers.Wallet ``` #### Example @@ -379,28 +464,30 @@ async getAllBalances(): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); + +const ethWallet = wallet.ethWallet(); ``` -### `getNonce` +### `finalizeWithdrawal` -Returns account's nonce number. +Proves the inclusion of the L2 -> L1 withdrawal message. #### Inputs -| Parameter | Type | Description | -| ----------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Name | Type | Description | +| ---------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | +| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getNonce(blockTag?: BlockTag): Promise +async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0, overrides?: ethers.Overrides): Promise ``` #### Example @@ -408,22 +495,32 @@ async getNonce(blockTag?: BlockTag): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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.getNonce()}`); + +const WITHDRAWAL_HASH = ""; +const finalizeWithdrawHandle = await wallet.finalizeWithdrawal(WITHDRAWAL_HASH); ``` -### `getDeploymentNonce` +### `finalizeWithdrawalParams` -Returns account's deployment nonce number. +Returns the [parameters](/sdk/js/ethers/api/v6/types#finalizewithdrawalparams) required for +finalizing a withdrawal +from the withdrawal transaction's log on the L1 network. + +#### Inputs + +| Name | Type | Description | +| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | ```ts -async getDeploymentNonce(): Promise +async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -431,86 +528,79 @@ async getDeploymentNonce(): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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()}`); + +const WITHDRAWAL_HASH = ""; +const params = await wallet.finalizeWithdrawalParams(WITHDRAWAL_HASH); ``` -### `ethWallet` +### `fromEncryptedJson` -You can get an `ethers.Wallet` object with the same private key with `ethWallet()` method. +Creates a `Wallet` from encrypted `json` file using provided `password`. + +#### Inputs + +| Parameter | Type | Description | +| ----------- | ------------------------ | -------------------------------------------------------------------------------------------------------------- | +| `json` | `string` | Encrypted json file. | +| `password` | `string` or `Uint8Array` | Password for encrypted json file. | +| `callback?` | `ProgressCallback` | If callback is provided, it is called periodically during decryption so that any UI can be updated. | ```ts -ethWallet(): ethers.Wallet +static async fromEncryptedJson(json: string, password: string | Uint8Array, callback? : ProgressCallback): Promise ``` #### Example ```ts import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); +import * as fs from "fs"; + +const wallet = await Wallet.fromEncryptedJson(fs.readFileSync("wallet.json", "utf8"), "password"); ``` -### `l2TokenAddress` - -Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. +### `fromEncryptedJsonSync` -::callout{icon="i-heroicons-exclamation-triangle" color="amber"} -Only works for tokens bridged on default ZKsync Era bridges. -:: +Creates a `Wallet` from encrypted `json` file using provided `password`. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ------------------------------- | -| `token` | `Address` | The address of the token on L1. | +| Parameter | Type | Description | +| ---------- | ------------------------ | --------------------------------- | +| `json` | `string` | Encrypted json file. | +| `password` | `string` or `Uint8Array` | Password for encrypted json file. | ```ts -async l2TokenAddress(token: Address): Promise +static fromEncryptedJsonSync(json: string, password: string | Uint8Array): Wallet ``` #### Example ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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)}`); +import { Wallet } from "zksync-ethers"; +import * as fs from "fs"; + +const wallet = Wallet.fromEncryptedJsonSync(fs.readFileSync("tests/files/wallet.json", "utf8"), "password"); ``` -### `populateTransaction` +### `fromMnemonic` -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. +Creates a `Wallet` with the `provider` as L1 provider and a private key that is built from the `mnemonic` passphrase. -| Parameter | Type | Description | -| ------------- | ----------------------------------------------------- | -------------------- | -| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | +#### Inputs + +| Parameter | Type | Description | +| ----------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `mnemonic` | `string` | The mnemonic of the private key. | +| `provider?` | [`ethers.Provider`](https://docs.ethers.org/v6/api/providers/#Provider) | An Ethereum node provider. Needed for interaction with L1. | ```ts -async populateTransaction(transaction: TransactionRequest): Promise +static fromMnemonic(mnemonic: string, provider?: ethers.Provider): Wallet ``` #### Example @@ -518,34 +608,19 @@ async populateTransaction(transaction: TransactionRequest): Promise +async getAddress(): Promise
; ``` #### Example @@ -553,35 +628,22 @@ async signTransaction(transaction: TransactionRequest): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); -const wallet = new Wallet(PRIVATE_KEY, provider); - -const recipient = Wallet.createRandom(); - -const tx = await wallet.signTransaction({ - type: utils.EIP712_TX_TYPE, - to: recipient.address, - value: ethers.parseEther("1"), -}); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +console.log(`Address: ${await wallet.getAddress()}`); ``` -### `sendTransaction` - -Broadcast the transaction to the network. -Throws an error when `tx.from` is mismatched from the private key. - -#### Inputs +### `getAllBalances` -| Parameter | Type | Description | -| --------- | ----------------------------------------------------- | -------------------- | -| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | +Returns all balances for confirmed tokens given by an account address. ```ts -async sendTransaction(tx: TransactionRequest): Promise +async getAllBalances(): Promise ``` #### Example @@ -589,173 +651,65 @@ async sendTransaction(tx: TransactionRequest): Promise ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); -const wallet = new Wallet(PRIVATE_KEY, provider); - -const recipient = Wallet.createRandom(); - -const tx = await wallet.sendTransaction({ - type: utils.EIP712_TX_TYPE, - to: recipient.address, - value: ethers.parseEther("1"), -}); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const allBalances = await wallet.getAllBalances(); ``` -### `transfer` +### `getAllowanceL1` -For convenience, the `Wallet` class has `transfer` method, which can transfer `ETH` or any `ERC20` -token within the same interface. +Returns the amount of approved tokens for a specific L1 bridge. #### Inputs -| Parameter | Type | Description | -| ------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | -| `transaction.to` | `Address` | The address of the recipient. | -| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | -| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | -| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | - -```ts -async transfer(transaction: { - to: Address; - amount: BigNumberish; - token?: Address; - paymasterParams?: PaymasterParams; - overrides?: ethers.Overrides; -}): Promise -``` - -#### Examples - -Transfer ETH. +| Parameter | Type | Description | +| ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `token` | `Address` | The Ethereum address of the token. | +| `bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge, either `L1EthBridge` or `L1Erc20Bridge`. | +| `blockTag?` | `BlockTag` | In which block an allowance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; - -const PRIVATE_KEY = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const wallet = new Wallet(PRIVATE_KEY, provider); - -const recipient = Wallet.createRandom(); - -const transferTx = await wallet.transfer({ - to: recipient.address, - amount: ethers.parseEther("0.01"), -}); - -const receipt = await transferTx.wait(); - -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); +async getAllowanceL1( + token: Address, + bridgeAddress?: Address, + blockTag?: ethers.BlockTag +): Promise ``` -Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. +#### Example ```ts import { Wallet, Provider, utils } from "zksync-ethers"; - -const 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 recipient = Wallet.createRandom(); - -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}`); -``` - -Transfer token. - -```ts -import { Wallet, Provider, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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}`); -``` - -Transfer token using paymaster to facilitate fee payment with an ERC20 token. - -```ts -import { Wallet, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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}`); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +console.log(`Token allowance: ${await wallet.getAllowanceL1(tokenL1)}`); ``` -### `getAllowanceL1` +### `getBalance` -Returns the amount of approved tokens for a specific L1 bridge. +Returns the amount of the token the `Wallet` has. #### Inputs -| Parameter | Type | Description | -| ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -| `token` | `Address` | The Ethereum address of the token. | -| `bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge, either `L1EthBridge` or `L1Erc20Bridge`. | -| `blockTag?` | `BlockTag` | In which block an allowance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Parameter | Type | Description | +| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | +| `token?` | `Address` | The address of the token. ETH by default. | +| `blockTag` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async getAllowanceL1( - token: Address, - bridgeAddress?: Address, - blockTag?: ethers.BlockTag -): Promise +async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise ``` #### Example @@ -763,35 +717,31 @@ async getAllowanceL1( ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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)}`); + +const tokenL2 = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; + +console.log(`Token balance: ${await wallet.getBalance(tokenL2)}`); ``` -### `approveERC20` +### `getBalanceL1` -Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. +Returns the amount of the token the `Wallet` has on Ethereum. #### Inputs -| Parameter | Type | Description | -| ------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | -| `token` | `Address` | The Ethereum address of the token. | -| `amount` | `BigNumberish` | The amount of the token to be approved. | -| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| Parameter | Type | Description | +| ----------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | +| `token?` | `Address` | The address of the token. ETH by default. | +| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async approveERC20( - token: Address, - amount: BigNumberish, - overrides?: ethers.Overrides & { bridgeAddress?: Address } -): Promise +async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise ``` #### Example @@ -799,17 +749,16 @@ async approveERC20( ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 txHandle = await wallet.approveERC20(tokenL1, "10000000"); - -await txHandle.wait(); + +console.log(`Token balance: ${await wallet.getBalanceL1(tokenL1)}`); ``` ### `getBaseCost` @@ -837,13 +786,13 @@ async getBaseCost(params: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 })}`); ``` @@ -860,22 +809,22 @@ async getBaseToken(): Promise ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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()}`); ``` -### `isETHBasedChain` +### `getBridgehubContract` -Returns whether the chain is ETH-based. +Returns `Contract` wrapper of the Bridgehub smart contract. ```ts -async isETHBasedChain(): Promise +async getBridgehubContract(): Promise ``` #### Example @@ -883,14 +832,37 @@ async isETHBasedChain(): Promise ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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(); +``` -console.log(`Is ETH-based chain: ${await wallet.isETHBasedChain()}`); +### `getDeploymentNonce` + +Returns account's deployment nonce number. + +```ts +async getDeploymentNonce(): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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()}`); ``` ### `getDepositAllowanceParams` @@ -915,7 +887,7 @@ async getDepositAllowanceParams( token: Address; allowance: BigNumberish; }[] -> +> ``` #### Example @@ -925,17 +897,17 @@ Get allowance parameters for depositing token on ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const token = ""; const amount = 5; const approveParams = await wallet.getDepositAllowanceParams(token, amount); - + await ( await wallet.approveERC20( approveParams[0].token, @@ -949,17 +921,17 @@ Get allowance parameters for depositing ETH on non-ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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, @@ -973,17 +945,17 @@ Get allowance parameters for depositing base token on non-ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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, @@ -997,24 +969,24 @@ Get allowance parameters for depositing non-base token on non-ETH-based chain. ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const ethProvider = ethers.getDefaultProvider("sepolia"); const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); - + const 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, @@ -1023,174 +995,6 @@ await ( ).wait(); ``` -### `deposit` - -Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. -The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the -specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). -In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` -can be enabled to perform token approval. -If there are already enough approved tokens for the L1 bridge, token approval will be skipped. -To check the amount of approved tokens for a specific bridge, -use the [`allowanceL1`](/sdk/js/ethers/api/v6/accounts/wallet#getallowancel1) method. - -#### Inputs - -| Parameter | Type | Description | -|-------------------------------------| ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveBaseOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | - -```ts -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 -``` - -#### Example - -Deposit ETH on ETH-based chain. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); -``` - -Deposit token on ETH-based chain. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); -``` - -Deposit ETH on non-ETH-based chain. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); -``` - -Deposit base token on non-ETH-based chain. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); -``` - -Deposit non-base token on non-ETH-based chain. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - -const 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(); -``` - ### `getDepositTx` Returns populated deposit transaction. @@ -1230,13 +1034,13 @@ async getDepositTx(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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, @@ -1244,39 +1048,30 @@ const tx = await wallet.getDepositTx({ }); ``` -### `estimateGasDeposit` +### `getFullRequiredDepositFee` -Estimates the amount of gas required for a deposit transaction on L1 network. -Gas of approving ERC20 token is not included in estimation. +Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 fee [`FullDepositFee`](/sdk/js/ethers/api/v6/types#fulldepositfee). #### Inputs -| Parameter | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| Parameter | Type | Description | +| -------------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async estimateGasDeposit(transaction: +async getFullRequiredDepositFee(transaction: { token: Address; - amount: BigNumberish; to?: Address; - operatorTip?: BigNumberish; bridgeAddress?: Address; customBridgeData?: BytesLike; - l2GasLimit?: BigNumberish; gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; overrides?: ethers.Overrides; - }): Promise +}): Promise ``` #### Example @@ -1284,45 +1079,31 @@ async estimateGasDeposit(transaction: ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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({ + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +const fee = await wallet.getFullRequiredDepositFee({ token: tokenL1, - amount: "10000000", + to: await wallet.getAddress(), }); -console.log(`Gas: ${gas}`); +console.log(`Fee: ${fee}`); ``` -### `getFullRequiredDepositFee` - -Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 fee [`FullDepositFee`](/sdk/js/ethers/api/v6/types#fulldepositfee). - -#### Inputs +### `getL1BridgeContracts` -| Parameter | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns L1 bridge contracts. ```ts -async getFullRequiredDepositFee(transaction: { - token: Address; - to?: Address; - bridgeAddress?: Address; - customBridgeData?: BytesLike; - gasPerPubdataByte?: BigNumberish; - overrides?: ethers.Overrides; -}): Promise +async getL1BridgeContracts(): Promise<{ + erc20: IL1ERC20Bridge; + weth: IL1ERC20Bridge; + shared: IL1SharedBridge; +}> ``` #### Example @@ -1330,35 +1111,26 @@ async getFullRequiredDepositFee(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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}`); + +const l1BridgeContracts = await wallet.getL1BridgeContracts(); ``` -### `claimFailedDeposit` - -The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. -If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` -method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. - -#### Inputs +### `getL2BridgeContracts` -| Parameter | Type | Description | -| ----------- | --------- | ---------------------------------------------- | -| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | +Returns L2 bridge contracts. ```ts -async claimFailedDeposit(depositHash: BytesLike): Promise +async getL2BridgeContracts(): Promise<{ + erc20: IL2Bridge; + weth: IL2Bridge; + shared: IL2Bridge; +}> ``` #### Example @@ -1366,142 +1138,22 @@ async claimFailedDeposit(depositHash: BytesLike): Promise -``` - -#### Examples - -Withdraw ETH. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; - -const 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, -}); -``` - -Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; - -const 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(), - }), -}); -``` - -Withdraw token. - -```ts -import { Wallet, Provider, types } from "zksync-ethers"; - -const 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, -}); -``` - -Withdraw token using paymaster to facilitate fee payment with an ERC20 token. - -```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; - -const 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_000, - paymasterParams: utils.getPaymasterParams(paymaster, { - type: "ApprovalBased", - token: token, - minimalAllowance: 1, - innerInput: new Uint8Array(), - }), -}); + +const l2BridgeContracts = await wallet.getL2BridgeContracts(); ``` -### `finalizeWithdrawal` - -Proves the inclusion of the L2 -> L1 withdrawal message. - -#### Inputs +### `getMainContract` -| Name | Type | Description | -| ---------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | -| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns `Contract` wrapper of the ZKsync smart contract. ```ts -async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0, overrides?: ethers.Overrides): Promise +async getMainContract(): Promise ``` #### Example @@ -1509,30 +1161,28 @@ async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0, overrides ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 = ""; -const finalizeWithdrawHandle = await wallet.finalizeWithdrawal(WITHDRAWAL_HASH); + +console.log(`Main contract: ${await wallet.getMainContract()}`); ``` -### `isWithdrawalFinalized` +### `getNonce` -Returns whether the withdrawal transaction is finalized on the L1 network. +Returns account's nonce number. #### Inputs -| Name | Type | Description | -| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | +| Parameter | Type | Description | +| ----------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | +| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise +async getNonce(blockTag?: BlockTag): Promise ``` #### Example @@ -1540,48 +1190,51 @@ async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promi ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 = ""; -const isFinalized = await wallet.isWithdrawalFinalized(WITHDRAWAL_HASH); + +console.log(`Nonce: ${await wallet.getNonce()}`); ``` -### `finalizeWithdrawalParams` +### `getPriorityOpConfirmation` -Returns the [parameters](/sdk/js/ethers/api/v6/types#finalizewithdrawalparams) required for -finalizing a withdrawal -from the withdrawal transaction's log on the L1 network. +Returns the transaction confirmation data that is part of `L2->L1` message. #### Inputs -| Name | Type | Description | -| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | +| Name | Type | Description | +|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | ```ts -async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise +async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ + l1BatchNumber: number; + l2MessageIndex: number; + l2TxNumberInBlock: number; + proof: string[] +}> ``` #### Example ```ts -import { Wallet, Provider, utils } from "zksync-ethers"; +import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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 = ""; -const params = await wallet.finalizeWithdrawalParams(WITHDRAWAL_HASH); +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))}`); ``` ### `getRequestExecuteAllowanceParams` @@ -1622,19 +1275,19 @@ async getRequestExecuteAllowanceParams(transaction: { ```ts import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const 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( @@ -1644,17 +1297,17 @@ await ( ).wait(); ``` -### `requestExecute` +### `getRequestExecuteTx` -Request execution of L2 transaction from L1. +Returns populated request execute transaction. #### Inputs | Name | Type | Description | -| -------------------------------- |--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| -------------------------------- | ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `transaction.contractAddress` | `Address` | The L2 contract to be called. | | `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.l2GasLimit` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | | `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | | `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | | `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | @@ -1664,7 +1317,7 @@ Request execution of L2 transaction from L1. | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async requestExecute(transaction: { +async getRequestExecuteTx(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; @@ -1675,7 +1328,7 @@ async requestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; -}): Promise +}): Promise ``` #### Example @@ -1683,84 +1336,152 @@ async requestExecute(transaction: { ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; const 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({ + +const tx = await wallet.getRequestExecuteTx({ contractAddress: await provider.getMainContractAddress(), calldata: "0x", l2Value: 7_000_000_000, }); -await tx.wait(); ``` -### `getRequestExecuteTx` +### `isETHBasedChain` -Returns populated request execute transaction. +Returns whether the chain is ETH-based. + +```ts +async isETHBasedChain(): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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()}`); +``` + +### `isWithdrawalFinalized` + +Returns whether the withdrawal transaction is finalized on the L1 network. #### Inputs -| Name | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `transaction.contractAddress` | `Address` | The L2 contract to be called. | -| `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | -| `transaction.l2GasLimit` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | -| `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | -| `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| Name | Type | Description | +| ---------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | ```ts -async getRequestExecuteTx(transaction: { - contractAddress: Address; - calldata: string; - l2GasLimit?: BigNumberish; - mintValue?: BigNumberish; - l2Value?: BigNumberish; - factoryDeps?: BytesLike[]; - operatorTip?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: Overrides; -}): Promise +async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { Wallet, Provider, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; -const CONTRACT_ADDRESS = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const WITHDRAWAL_HASH = ""; +const isFinalized = await wallet.isWithdrawalFinalized(WITHDRAWAL_HASH); +``` + +### `l2TokenAddress` + +Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. + +::callout{icon="i-heroicons-exclamation-triangle" color="amber"} +Only works for tokens bridged on default ZKsync Era bridges. +:: + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `token` | `Address` | The address of the token on L1. | +```ts +async l2TokenAddress(token: Address): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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)}`); +``` -const tx = await wallet.getRequestExecuteTx({ - contractAddress: await provider.getMainContractAddress(), - calldata: "0x", - l2Value: 7_000_000_000, +### `populateTransaction` + +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. + +| Parameter | Type | Description | +| ------------- | ----------------------------------------------------- | -------------------- | +| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | + +```ts +async populateTransaction(transaction: TransactionRequest): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const recipient = Wallet.createRandom(); + +const tx = wallet.populateTransaction({ + to: recipient.address, + amount: ethers.parseEther("0.01"), }); ``` -### `estimateGasRequestExecute` +### `requestExecute` -Estimates the amount of gas required for a request execute transaction. +Request execution of L2 transaction from L1. #### Inputs | Name | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| -------------------------------- |--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `transaction.contractAddress` | `Address` | The L2 contract to be called. | | `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | @@ -1773,7 +1494,7 @@ Estimates the amount of gas required for a request execute transaction. | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -estimateGasRequestExecute(transaction: { +async requestExecute(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; @@ -1784,7 +1505,7 @@ estimateGasRequestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; -}): Promise +}): Promise ``` #### Example @@ -1792,55 +1513,334 @@ estimateGasRequestExecute(transaction: { ```ts import { Wallet, Provider, types, utils } from "zksync-ethers"; import { ethers } from "ethers"; - + const PRIVATE_KEY = ""; const 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({ + +const tx = await wallet.requestExecute({ contractAddress: await provider.getMainContractAddress(), calldata: "0x", l2Value: 7_000_000_000, }); -console.log(`Gas: ${gas}`); +await tx.wait(); ``` -### `getPriorityOpConfirmation` +### `sendTransaction` -Returns the transaction confirmation data that is part of `L2->L1` message. +Broadcast the transaction to the network. +Throws an error when `tx.from` is mismatched from the private key. #### Inputs -| Name | Type | Description | -|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | +| Parameter | Type | Description | +| --------- | ----------------------------------------------------- | -------------------- | +| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | ```ts -async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ - l1BatchNumber: number; - l2MessageIndex: number; - l2TxNumberInBlock: number; - proof: string[] -}> +async sendTransaction(tx: TransactionRequest): Promise ``` #### Example ```ts -import { Wallet, Provider, types, utils } from "zksync-ethers"; +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider); + +const recipient = Wallet.createRandom(); + +const tx = await wallet.sendTransaction({ + type: utils.EIP712_TX_TYPE, + to: recipient.address, + value: ethers.parseEther("1"), +}); +``` + +### `signTransaction` + +Signs the transaction and serializes it to be ready to be broadcast to the network. +Throws an error when `transaction.from` is mismatched from the private key. + +#### Inputs + +| Parameter | Type | Description | +| ------------- | ----------------------------------------------------- | -------------------- | +| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | + +```ts +async signTransaction(transaction: TransactionRequest): Promise +``` + +#### Example + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider("sepolia"); +const wallet = new Wallet(PRIVATE_KEY, provider); + +const recipient = Wallet.createRandom(); + +const tx = await wallet.signTransaction({ + type: utils.EIP712_TX_TYPE, + to: recipient.address, + value: ethers.parseEther("1"), +}); +``` + +### `transfer` + +For convenience, the `Wallet` class has `transfer` method, which can transfer `ETH` or any `ERC20` +token within the same interface. + +#### Inputs + +| Parameter | Type | Description | +| ------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| `transaction.to` | `Address` | The address of the recipient. | +| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | +| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | +| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async transfer(transaction: { + to: Address; + amount: BigNumberish; + token?: Address; + paymasterParams?: PaymasterParams; + overrides?: ethers.Overrides; +}): Promise +``` + +#### Examples + +Transfer ETH. + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const wallet = new Wallet(PRIVATE_KEY, provider); + +const recipient = Wallet.createRandom(); + +const transferTx = await wallet.transfer({ + to: recipient.address, + amount: ethers.parseEther("0.01"), +}); + +const receipt = await transferTx.wait(); + +console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); +``` + +Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. + +```ts +import { Wallet, Provider, utils } from "zksync-ethers"; + +const 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 recipient = Wallet.createRandom(); + +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}`); +``` + +Transfer token. + +```ts +import { Wallet, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; + +const 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}`); +``` + +Transfer token using paymaster to facilitate fee payment with an ERC20 token. + +```ts +import { Wallet, Provider, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const 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}`); +``` + +### `withdraw` + +Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 +network to the target account on L1 network. + +#### Inputs + +| Parameter | Type | Description | +| ------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | +| `transaction.to?` | `Address` | The address of the recipient on L1. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | +| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L2 `gasLimit`, `gasPrice`, `value`, etc. | +```ts +async withdraw(transaction: { + token: Address; + amount: BigNumberish; + to?: Address; + bridgeAddress?: Address; + paymasterParams?: PaymasterParams; + overrides?: ethers.Overrides; +}): Promise +``` + +#### Examples + +Withdraw ETH. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + const 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, +}); +``` +Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + +const 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(), + }), +}); +``` -// 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))}`); +Withdraw token. + +```ts +import { Wallet, Provider, types } from "zksync-ethers"; + +const 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, +}); +``` + +Withdraw token using paymaster to facilitate fee payment with an ERC20 token. + +```ts +import { Wallet, Provider, types, utils } from "zksync-ethers"; + +const 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_000, + paymasterParams: utils.getPaymasterParams(paymaster, { + type: "ApprovalBased", + token: token, + minimalAllowance: 1, + innerInput: new Uint8Array(), + }), +}); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/02.signer.md b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/02.signer.md index 0fb6f71f..bff959be 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/02.signer.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/02.signer.md @@ -15,6 +15,25 @@ const browserProvider = new BrowserProvider(window.ethereum); const signer = Signer.from(await browserProvider.getSigner(), Number((await browserProvider.getNetwork()).chainId), Provider.getDefaultProvider(types.Network.Sepolia)); ``` +### `getAllBalances` + +Returns all token balances of the account. + +```ts +async getAllBalances(): Promise +``` + +#### Example + +```ts +import { BrowserProvider, Provider, types } from "zksync-ethers"; + +const browserProvider = new BrowserProvider(window.ethereum); +const signer = Signer.from(await browserProvider.getSigner(), Number((await browserProvider.getNetwork()).chainId), Provider.getDefaultProvider(types.Network.Sepolia)); + +const allBalances = await signer.getAllBalances(); +``` + ### `getBalance` Returns the amount of the token the `Signer` has. @@ -56,25 +75,6 @@ const token = "0x6a4Fb925583F7D4dF82de62d98107468aE846FD1"; console.log(`Token balance: ${await signer.getBalance(token)}`); ``` -### `getAllBalances` - -Returns all token balances of the account. - -```ts -async getAllBalances(): Promise -``` - -#### Example - -```ts -import { BrowserProvider, Provider, types } from "zksync-ethers"; - -const browserProvider = new BrowserProvider(window.ethereum); -const signer = Signer.from(await browserProvider.getSigner(), Number((await browserProvider.getNetwork()).chainId), Provider.getDefaultProvider(types.Network.Sepolia)); - -const allBalances = await signer.getAllBalances(); -``` - ### `getDeploymentNonce` Returns the deployment nonce of the account. diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/03.l1signer.md b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/03.l1signer.md index ed5173d0..0c6bcc77 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/03.l1signer.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/03.l1signer.md @@ -18,12 +18,24 @@ const zksyncProvider = Provider.getDefaultProvider(types.Network.Sepolia); const signer = L1Signer.from(provider.getSigner(), zksyncProvider); ``` -### `getMainContract` +### `approveERC20` -Returns the main ZKsync Era smart contract address. +Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. + +#### Inputs + +| Parameter | Type | Description | +| ------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| `token` | `Address` | The Ethereum address of the token. | +| `amount` | `BigNumberish` | The amount of the token to be approved. | +| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getMainContract(): Promise +async approveERC20( + token: Address, + amount: BigNumberish, + overrides?: ethers.Overrides & { bridgeAddress?: Address } +): Promise ``` #### Example @@ -31,20 +43,28 @@ async getMainContract(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const mainContract = await signer.getMainContract(); -console.log(mainContract.address); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +await signer.approveERC20(tokenL1, 5); ``` -### `getBridgehubContract` +### `claimFailedDeposit` -Returns `Contract` wrapper of the Bridgehub smart contract. +The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. +If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` +method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. + +#### Inputs + +| Parameter | Type | Description | +| ----------- | --------- | ---------------------------------------------- | +| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | ```ts -async getBridgehubContract(): Promise +async claimFailedDeposit(depositHash: BytesLike): Promise ``` #### Example @@ -52,99 +72,312 @@ async getBridgehubContract(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const FAILED_DEPOSIT_HASH = ""; +const claimFailedDepositHandle = await signer.claimFailedDeposit(FAILED_DEPOSIT_HASH); +``` + +### `deposit` +Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. +The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the +specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). +In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` +can be enabled to perform token approval. +If there are already enough approved tokens for the L1 bridge, token approval will be skipped. +To check the amount of approved tokens for a specific bridge, +use the [`allowanceL1`](/sdk/js/ethers/api/v6/accounts/l1signer#getallowancel1) method. + +#### Inputs + +| Parameter | Type | Description | +|-------------------------------------| ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.approveBaseOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | + +```ts +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 +``` + +#### Example + +Deposit ETH on ETH-based chain. + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - -const bridgehub = await signer.getBridgehubContract(); + +await signer.deposit({ + token: utils.ETH_ADDRESS, + amount: 10_000_000n, +}); ``` -### `getL1BridgeContracts` - -Returns L1 bridge contracts. +Deposit token on ETH-based chain. ```ts -async getL1BridgeContracts(): Promise<{ - erc20: IL1ERC20Bridge; - weth: IL1ERC20Bridge; - shared: IL1SharedBridge; -}> +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from( + await browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +await signer.deposit({ + token: tokenL1, + amount: 10_000_000n, + approveERC20: true, +}); ``` -#### Example +Deposit ETH on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from( + await browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +await signer.deposit({ + token: utils.ETH_ADDRESS, + amount: 10_000_000, + approveBaseERC20: true, +}); +``` +Deposit base token on non-ETH-based chain. + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); +const signer = L1Signer.from( + await browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +await signer.deposit({ + token: await signer.getBaseToken(), + amount: 10_000_000, + approveERC20: true, // or approveBaseERC20: true +}); +``` -const l1BridgeContracts = await signer.getL1BridgeContracts(); +Deposit non-base token on non-ETH-based chain. + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from( + await browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +await signer.deposit({ + token: tokenL1, + amount: 10_000_000, + approveERC20: true, + approveBaseERC20: true, +}); ``` -### `getBalanceL1` +### `estimateGasDeposit` -Returns the amount of the token the `L1Signer` has on Ethereum. +Estimates the amount of gas required for a deposit transaction on L1 network. +Gas of approving ERC20 token is not included in estimation. #### Inputs -| Parameter | Type | Description | -| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | -| `token?` | `Address` | The address of the token. ETH by default. | -| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | +| Parameter | Type | Description | +| -------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | +| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise +async estimateGasDeposit(transaction: + token: Address; + amount: BigNumberish; + to?: Address; + operatorTip?: BigNumberish; + bridgeAddress?: Address; + customBridgeData?: BytesLike; + l2GasLimit?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: ethers.Overrides; + }): Promise ``` #### Example -Get ETH balance. - ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; +const gas = await signer.estimateGasDeposit({ + token: tokenL1, + amount: 10_000_000n, +}); +console.log(`Gas: ${gas}`); +``` -console.log(await signer.getBalanceL1()); +### `estimateGasRequestExecute` + +Estimates the amount of gas required for a request execute transaction. + +#### Inputs + +| Name | Type | Description | +| -------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.contractAddress?` | `Address` | The L2 contract to be called. | +| `transaction.calldata?` | `BytesLike` | The input of the L2 transaction. | +| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | +| `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | +| `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | +| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | +| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async estimateGasRequestExecute(transaction: { + contractAddress: Address; + calldata: string; + l2GasLimit?: BigNumberish; + mintValue?: BigNumberish; + l2Value?: BigNumberish; + factoryDeps?: BytesLike[]; + operatorTip?: BigNumberish; + gasPerPubdataByte?: BigNumberish; + refundRecipient?: Address; + overrides?: Overrides; +}): Promise ``` -Get token balance. +#### Example ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); +const signer = L1Signer.from( + await browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +const gas = await signer.estimateGasRequestExecute({ + contractAddress: await signer.providerL2.getMainContractAddress(), + calldata: "0x", + l2Value: 7_000_000_000, +}); +console.log(`Gas: ${gas}`); +``` -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; +### `finalizeWithdrawal` -console.log(await signer.getBalanceL1(tokenL1)); +Proves the inclusion of the L2 -> L1 withdrawal message. + +#### Inputs + +| Name | Type | Description | +| ---------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | +| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0, overrides?: ethers.Overrides): Promise ``` -### `l2TokenAddress` +#### Example -Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const WITHDRAWAL_HASH = ""; +const finalizeWithdrawHandle = await signer.finalizeWithdrawal(WITHDRAWAL_HASH); +``` -::callout{icon="i-heroicons-exclamation-triangle" color="amber"} -Only works for tokens bridged on default ZKsync Era bridges. -:: +### `finalizeWithdrawalParams` + +Returns the [parameters](/sdk/js/ethers/api/v6/types#finalizewithdrawalparams) required for +finalizing a withdrawal +from the withdrawal transaction's log on the L1 network. #### Inputs -| Parameter | Type | Description | -| --------- | --------- | ------------------------------- | -| `token` | `Address` | The address of the token on L1. | +| Name | Type | Description | +| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | ```ts -async l2TokenAddress(token: Address): Promise +async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise ``` #### Example @@ -152,13 +385,12 @@ async l2TokenAddress(token: Address): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; - -console.log(`Token L2 address: ${await signer.l2TokenAddress(tokenL1)}`); + +const WITHDRAWAL_HASH = ""; +const params = await signer.finalizeWithdrawalParams(WITHDRAWAL_HASH); ``` ### `getAllowanceL1` @@ -186,45 +418,55 @@ async getAllowanceL1( ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; console.log(`Token allowance: ${await signer.getAllowanceL1(tokenL1)}`); ``` -### `approveERC20` +### `getBalanceL1` -Bridging ERC20 tokens from Ethereum requires approving the tokens to the ZKsync Ethereum smart contract. +Returns the amount of the token the `L1Signer` has on Ethereum. #### Inputs -| Parameter | Type | Description | -| ------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | -| `token` | `Address` | The Ethereum address of the token. | -| `amount` | `BigNumberish` | The amount of the token to be approved. | -| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +| Parameter | Type | Description | +| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | +| `token?` | `Address` | The address of the token. ETH by default. | +| `blockTag?` | `BlockTag` | In which block a balance should be checked on. `committed`, i.e. the latest processed one is the default option. | ```ts -async approveERC20( - token: Address, - amount: BigNumberish, - overrides?: ethers.Overrides & { bridgeAddress?: Address } -): Promise +async getBalanceL1(token?: Address, blockTag?: BlockTag): Promise ``` #### Example +Get ETH balance. + ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +console.log(await signer.getBalanceL1()); +``` -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; -await signer.approveERC20(tokenL1, 5); +Get token balance. + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; + +console.log(await signer.getBalanceL1(tokenL1)); ``` ### `getBaseCost` @@ -252,10 +494,10 @@ async getBaseCost(params: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + console.log(`Base cost: ${await signer.getBaseCost({ gasLimit: 100_000 })}`); ``` @@ -272,22 +514,22 @@ async getBaseToken(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + console.log(`Base token: ${await signer.getBaseToken()}`); ``` -### `isETHBasedChain` +### `getBridgehubContract` -Returns whether the chain is ETH-based. +Returns `Contract` wrapper of the Bridgehub smart contract. ```ts -async isETHBasedChain(): Promise +async getBridgehubContract(): Promise ``` #### Example @@ -295,14 +537,14 @@ async isETHBasedChain(): Promise ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - -console.log(`Is ETH-based chain: ${await signer.isETHBasedChain()}`); + +const bridgehub = await signer.getBridgehubContract(); ``` ### `getDepositAllowanceParams` @@ -327,7 +569,7 @@ async getDepositAllowanceParams( token: Address; allowance: BigNumberish; }[] -> +> ``` #### Example @@ -337,17 +579,17 @@ Get allowance parameters for depositing token on ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = ""; const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); - + await ( await signer.approveERC20( approveParams[0].token, @@ -361,13 +603,13 @@ Get allowance parameters for depositing ETH on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = utils.LEGACY_ETH_ADDRESS; const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); @@ -384,13 +626,13 @@ Get allowance parameters for depositing base token on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = await signer.getBaseToken(); const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); @@ -407,24 +649,24 @@ Get allowance parameters for depositing non-base token on non-ETH-based chain. ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const token = ""; const amount = 5; const approveParams = await signer.getDepositAllowanceParams(token, amount); - + await ( await signer.approveERC20( approveParams[0].token, approveParams[0].allowance ) ).wait(); - + await ( await signer.approveERC20( approveParams[1].token, @@ -433,154 +675,6 @@ await ( ).wait(); ``` -### `deposit` - -Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. -The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the -specified L1 bridge (default one or the one defined in `transaction.bridgeAddress`). -In this case, depending on is the chain ETH-based or not `transaction.approveERC20` or `transaction.approveBaseERC20` -can be enabled to perform token approval. -If there are already enough approved tokens for the L1 bridge, token approval will be skipped. -To check the amount of approved tokens for a specific bridge, -use the [`allowanceL1`](/sdk/js/ethers/api/v6/accounts/l1signer#getallowancel1) method. - -#### Inputs - -| Parameter | Type | Description | -|-------------------------------------| ------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.approveBaseOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | - -```ts -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 -``` - -#### Example - -Deposit ETH on ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from( - await browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -await signer.deposit({ - token: utils.ETH_ADDRESS, - amount: 10_000_000n, -}); -``` - -Deposit token on ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from( - await browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; -await signer.deposit({ - token: tokenL1, - amount: 10_000_000n, - approveERC20: true, -}); -``` - -Deposit ETH on non-ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from( - await browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -await signer.deposit({ - token: utils.ETH_ADDRESS, - amount: 10_000_000, - approveBaseERC20: true, -}); -``` - -Deposit base token on non-ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from( - await browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -await signer.deposit({ - token: await signer.getBaseToken(), - amount: 10_000_000, - approveERC20: true, // or approveBaseERC20: true -}); -``` - -Deposit non-base token on non-ETH-based chain. - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from( - await browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; -await signer.deposit({ - token: tokenL1, - amount: 10_000_000, - approveERC20: true, - approveBaseERC20: true, -}); -``` - ### `getDepositTx` Returns populated deposit transaction. @@ -620,10 +714,10 @@ async getDepositTx(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; const tx = await signer.getDepositTx({ token: tokenL1, @@ -631,58 +725,6 @@ const tx = await signer.getDepositTx({ }); ``` -### `estimateGasDeposit` - -Estimates the amount of gas required for a deposit transaction on L1 network. -Gas of approving ERC20 token is not included in estimation. - -#### Inputs - -| Parameter | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token to deposit. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to deposit. | -| `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | -| `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | - -```ts -async estimateGasDeposit(transaction: - token: Address; - amount: BigNumberish; - to?: Address; - operatorTip?: BigNumberish; - bridgeAddress?: Address; - customBridgeData?: BytesLike; - l2GasLimit?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.Overrides; - }): Promise -``` - -#### Example - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; -const gas = await signer.estimateGasDeposit({ - token: tokenL1, - amount: 10_000_000n, -}); -console.log(`Gas: ${gas}`); -``` - ### `getFullRequiredDepositFee` Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 fee [`FullDepositFee`](/sdk/js/ethers/api/v6/types#fulldepositfee). @@ -714,61 +756,28 @@ async getFullRequiredDepositFee(transaction: { ```ts import { Provider, L1Signer, Wallet, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - + const tokenL1 = "0x56E69Fa1BB0d1402c89E3A4E3417882DeA6B14Be"; const fee = await signer.getFullRequiredDepositFee({ token: tokenL1, - to: Wallet.createRandom().address, -}); -console.log(`Fee: ${fee}`); -``` - -### `claimFailedDeposit` - -The `claimFailedDeposit` method withdraws funds from the initiated deposit, which failed when finalizing on L2. -If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` -method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error. - -#### Inputs - -| Parameter | Type | Description | -| ----------- | --------- | ---------------------------------------------- | -| depositHash | `bytes32` | The L2 transaction hash of the failed deposit. | - -```ts -async claimFailedDeposit(depositHash: BytesLike): Promise -``` - -#### Example - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const FAILED_DEPOSIT_HASH = ""; -const claimFailedDepositHandle = await signer.claimFailedDeposit(FAILED_DEPOSIT_HASH); + to: Wallet.createRandom().address, +}); +console.log(`Fee: ${fee}`); ``` -### `finalizeWithdrawal` - -Proves the inclusion of the L2 -> L1 withdrawal message. - -#### Inputs +### `getL1BridgeContracts` -| Name | Type | Description | -| ---------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | -| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns L1 bridge contracts. ```ts -async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0, overrides?: ethers.Overrides): Promise +async getL1BridgeContracts(): Promise<{ + erc20: IL1ERC20Bridge; + weth: IL1ERC20Bridge; + shared: IL1SharedBridge; +}> ``` #### Example @@ -776,27 +785,19 @@ async finalizeWithdrawal(withdrawalHash: BytesLike, index: number = 0, overrides ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const WITHDRAWAL_HASH = ""; -const finalizeWithdrawHandle = await signer.finalizeWithdrawal(WITHDRAWAL_HASH); + +const l1BridgeContracts = await signer.getL1BridgeContracts(); ``` -### `isWithdrawalFinalized` - -Returns whether the withdrawal transaction is finalized on the L1 network. - -#### Inputs +### `getMainContract` -| Name | Type | Description | -| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | +Returns the main ZKsync Era smart contract address. ```ts -async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise +async getMainContract(): Promise ``` #### Example @@ -804,29 +805,32 @@ async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promi ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const WITHDRAWAL_HASH = ""; -const isFinalized = await signer.isWithdrawalFinalized(WITHDRAWAL_HASH); + +const mainContract = await signer.getMainContract(); +console.log(mainContract.address); ``` -### `finalizeWithdrawalParams` +### `getPriorityOpConfirmation` -Returns the [parameters](/sdk/js/ethers/api/v6/types#finalizewithdrawalparams) required for -finalizing a withdrawal -from the withdrawal transaction's log on the L1 network. +Returns the transaction confirmation data that is part of `L2->L1` message. #### Inputs -| Name | Type | Description | -| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | +| Name | Type | Description | +|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | ```ts -async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Promise +async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ + l1BatchNumber: number; + l2MessageIndex: number; + l2TxNumberInBlock: number; + proof: string[] +}> ``` #### Example @@ -834,12 +838,17 @@ async finalizeWithdrawalParams(withdrawalHash: BytesLike, index: number = 0): Pr ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); - -const WITHDRAWAL_HASH = ""; -const params = await signer.finalizeWithdrawalParams(WITHDRAWAL_HASH); +const signer = L1Signer.from( + await browserProvider.getSigner(), + Provider.getDefaultProvider(types.Network.Sepolia) +); + +// Any L2 -> L1 transaction can be used. +// In this case, withdrawal transaction is used. +const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; +console.log(`Confirmation data: ${utils.toJSON(await signer.getPriorityOpConfirmation(tx, 0))}`); ``` ### `getRequestExecuteAllowanceParams` @@ -880,19 +889,19 @@ async getRequestExecuteAllowanceParams(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - + const tx = { contractAddress: await signer.getAddress(), calldata: '0x', l2Value: 7_000_000_000, }; - + const approveParams = await signer.getRequestExecuteAllowanceParams(tx); await ( await signer.approveERC20( @@ -902,17 +911,17 @@ await ( ).wait(); ``` -### `requestExecute` +### `getRequestExecuteTx` -Request execution of L2 transaction from L1. +Returns populated deposit transaction. #### Inputs | Name | Type | Description | -| -------------------------------- |--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `transaction.contractAddress` | `Address` | The L2 contract to be called. | -| `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | -| `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | +| -------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transaction.contractAddress?` | `Address` | The L2 contract to be called. | +| `transaction.calldata?` | `BytesLike` | The input of the L2 transaction. | +| `transaction.l2GasLimit` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | | `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | | `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | | `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | @@ -922,18 +931,18 @@ Request execution of L2 transaction from L1. | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async requestExecute(transaction: { +async getRequestExecuteTx(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; mintValue?: BigNumberish; l2Value?: BigNumberish; - factoryDeps?: BytesLike[]; + factoryDeps?: ethers.BytesLike[]; operatorTip?: BigNumberish; gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; - overrides?: Overrides; -}): Promise + overrides?: ethers.Overrides; +}): Promise ``` #### Example @@ -941,52 +950,26 @@ async requestExecute(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - -await signer.requestExecute({ + +const tx = await signer.getRequestExecuteTx({ contractAddress: await signer.providerL2.getMainContractAddress(), calldata: "0x", l2Value: 7_000_000_000, }); ``` -### `getRequestExecuteTx` - -Returns populated deposit transaction. - -#### Inputs +### `isETHBasedChain` -| Name | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.contractAddress?` | `Address` | The L2 contract to be called. | -| `transaction.calldata?` | `BytesLike` | The input of the L2 transaction. | -| `transaction.l2GasLimit` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | -| `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | -| `transaction.factoryDeps?` | `ethers.BytesLike[]` | An array of L2 bytecodes that will be marked as known on L2. | -| `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | -| `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive `l2Value`. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | +Returns whether the chain is ETH-based. ```ts -async getRequestExecuteTx(transaction: { - contractAddress: Address; - calldata: string; - l2GasLimit?: BigNumberish; - mintValue?: BigNumberish; - l2Value?: BigNumberish; - factoryDeps?: ethers.BytesLike[]; - operatorTip?: BigNumberish; - gasPerPubdataByte?: BigNumberish; - refundRecipient?: Address; - overrides?: ethers.Overrides; -}): Promise +async isETHBasedChain(): Promise ``` #### Example @@ -994,30 +977,86 @@ async getRequestExecuteTx(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); + +console.log(`Is ETH-based chain: ${await signer.isETHBasedChain()}`); +``` -const tx = await signer.getRequestExecuteTx({ - contractAddress: await signer.providerL2.getMainContractAddress(), - calldata: "0x", - l2Value: 7_000_000_000, -}); +### `isWithdrawalFinalized` + +Returns whether the withdrawal transaction is finalized on the L1 network. + +#### Inputs + +| Name | Type | Description | +| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0). | + +```ts +async isWithdrawalFinalized(withdrawalHash: BytesLike, index: number = 0): Promise ``` -### `estimateGasRequestExecute` +#### Example -Estimates the amount of gas required for a request execute transaction. +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const WITHDRAWAL_HASH = ""; +const isFinalized = await signer.isWithdrawalFinalized(WITHDRAWAL_HASH); +``` + +### `l2TokenAddress` + +Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address. + +::callout{icon="i-heroicons-exclamation-triangle" color="amber"} +Only works for tokens bridged on default ZKsync Era bridges. +:: + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `token` | `Address` | The address of the token on L1. | + +```ts +async l2TokenAddress(token: Address): Promise +``` + +#### Example + +```ts +import { Provider, L1Signer, types } from "zksync-ethers"; +import { ethers } from "ethers"; + +const browserProvider = new ethers.BrowserProvider(window.ethereum); +const signer = L1Signer.from(await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia)); + +const tokenL1 = "0x5C221E77624690fff6dd741493D735a17716c26B"; + +console.log(`Token L2 address: ${await signer.l2TokenAddress(tokenL1)}`); +``` + +### `requestExecute` + +Request execution of L2 transaction from L1. #### Inputs | Name | Type | Description | -| -------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `transaction.contractAddress?` | `Address` | The L2 contract to be called. | -| `transaction.calldata?` | `BytesLike` | The input of the L2 transaction. | +| -------------------------------- |--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `transaction.contractAddress` | `Address` | The L2 contract to be called. | +| `transaction.calldata` | `BytesLike` | The input of the L2 transaction. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | | `transaction.mintValue?` | `BigNumberish` | The amount of base token that needs to be minted on non-ETH-based L2.. | | `transaction.l2Value?` | `BigNumberish` | `msg.value` of L2 transaction. | @@ -1028,7 +1067,7 @@ Estimates the amount of gas required for a request execute transaction. | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async estimateGasRequestExecute(transaction: { +async requestExecute(transaction: { contractAddress: Address; calldata: string; l2GasLimit?: BigNumberish; @@ -1039,7 +1078,7 @@ async estimateGasRequestExecute(transaction: { gasPerPubdataByte?: BigNumberish; refundRecipient?: Address; overrides?: Overrides; -}): Promise +}): Promise ``` #### Example @@ -1047,55 +1086,16 @@ async estimateGasRequestExecute(transaction: { ```ts import { Provider, L1Signer, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const browserProvider = new ethers.BrowserProvider(window.ethereum); const signer = L1Signer.from( await browserProvider.getSigner(), Provider.getDefaultProvider(types.Network.Sepolia) ); - -const gas = await signer.estimateGasRequestExecute({ + +await signer.requestExecute({ contractAddress: await signer.providerL2.getMainContractAddress(), calldata: "0x", l2Value: 7_000_000_000, }); -console.log(`Gas: ${gas}`); -``` - -### `getPriorityOpConfirmation` - -Returns the transaction confirmation data that is part of `L2->L1` message. - -#### Inputs - -| Name | Type | Description | -|----------| ----------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `txHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index?` | `number` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0. | - -```ts -async getPriorityOpConfirmation(txHash: string, index: number = 0): Promise<{ - l1BatchNumber: number; - l2MessageIndex: number; - l2TxNumberInBlock: number; - proof: string[] -}> -``` - -#### Example - -```ts -import { Provider, L1Signer, types } from "zksync-ethers"; -import { ethers } from "ethers"; - -const browserProvider = new ethers.BrowserProvider(window.ethereum); -const signer = L1Signer.from( - await browserProvider.getSigner(), - Provider.getDefaultProvider(types.Network.Sepolia) -); - -// Any L2 -> L1 transaction can be used. -// In this case, withdrawal transaction is used. -const tx = "0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e"; -console.log(`Confirmation data: ${utils.toJSON(await signer.getPriorityOpConfirmation(tx, 0))}`); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/06.eip712signer.md b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/06.eip712signer.md index 862747d6..f88fa9f5 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/06.eip712signer.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/06.eip712signer.md @@ -7,34 +7,12 @@ tags: ["zksync", "ethers.js", "blockchain", "EIP712", "smart contracts"] This class provides support for an EIP712 transaction. The methods of this class are mostly used internally. -### `getSignInput` - -Generates the EIP-712 typed data from provided transaction. Optional fields are populated by zero values. - -#### Inputs - -| Parameter | Type | Description | -| ------------- | ----------------------------------------------------- | -------------------- | -| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | - -```ts -static getSignInput(transaction: TransactionRequest) -``` +### `getDomain` -#### Example +Returns the EIP712 domain. ```ts -const tx = EIP712Signer.getSignInput({ - type: utils.EIP712_TX_TYPE, - to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", - value: BigInt(7_000_000), - from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", - nonce: 0, - chainId: BigInt(270), - gasPrice: BigInt(250_000_000), - gasLimit: BigInt(21_000), - customData: {}, -}); +async getDomain(): Promise ``` ### `sign` @@ -65,10 +43,32 @@ Generates the signed digest of an Ethereum transaction using EIP-712. static getSignedDigest(transaction: TransactionRequest): ethers.BytesLike ``` -### `getDomain` +### `getSignInput` -Returns the EIP712 domain. +Generates the EIP-712 typed data from provided transaction. Optional fields are populated by zero values. + +#### Inputs + +| Parameter | Type | Description | +| ------------- | ----------------------------------------------------- | -------------------- | +| `transaction` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | Transaction request. | ```ts -async getDomain(): Promise +static getSignInput(transaction: TransactionRequest) +``` + +#### Example + +```ts +const tx = EIP712Signer.getSignInput({ + type: utils.EIP712_TX_TYPE, + to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", + value: BigInt(7_000_000), + from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + nonce: 0, + chainId: BigInt(270), + gasPrice: BigInt(250_000_000), + gasLimit: BigInt(21_000), + customData: {}, +}); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/07.smartaccount.md b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/07.smartaccount.md index a84c5896..0102af10 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/07.smartaccount.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/01.accounts/07.smartaccount.md @@ -12,62 +12,62 @@ It is compatible with [ethers.ContractFactory](https://docs.ethers.org/v6/api/co as well as with [ethers.Contract](https://docs.ethers.org/v6/api/contract/#Contract) for interacting with contracts/accounts using provided ABI along with custom transaction signing logic. -### `constructor` +### `connect` -Creates a `SmartAccount` instance with provided `signer` and `provider`. -By default, uses [`signPayloadWithECDSA`](/sdk/js/ethers/api/v6/utilities/smart-account-utils#signpayloadwithecdsa) and [`populateTransactionECDSA`](/sdk/js/ethers/api/v6/utilities/smart-account-utils#populatetransactionecdsa). +Creates a new instance of `SmartAccount` connected to a provider or detached +from any provider if `null` is provided. #### Inputs -| Parameter | Type | Description | -| ----------- | ----------------------------------------------------- | ----------------------------------------------------------------------- | -| `signer` | [`SmartAccountSigner`](/sdk/js/ethers/api/v6/types#smartaccountsigner) | Contains necessary properties for signing payloads. | -| `provider?` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) or `null` | The provider to connect to. Can be `null` for offline usage. | +| Parameter | Type | Description | +| ---------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `provider` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) or `null` | The provider to connect the `SmartAccount` to. If `null`, the `SmartAccount` will be detached from any provider. | ```ts -constructor(signer: SmartAccountSigner, provider?: null | Provider) +connect(provider: null | Provider): SmartAccount ``` #### Example ```ts -import { SmartAccount, Provider, types } from "zksync-ethers"; - +import { Wallet, Provider, types } from "zksync-ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); -const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); + +const sepoliaProvider = Provider.getDefaultProvider(types.Network.Sepolia); +const sepoliaAccount = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, sepoliaProvider); + +const mainnetProvider = Provider.getDefaultProvider(types.Network.Mainnet); +const mainnetAccount = sepoliaAccount.connect(mainnetProvider); ``` -### `connect` +### `constructor` -Creates a new instance of `SmartAccount` connected to a provider or detached -from any provider if `null` is provided. +Creates a `SmartAccount` instance with provided `signer` and `provider`. +By default, uses [`signPayloadWithECDSA`](/sdk/js/ethers/api/v6/utilities/smart-account-utils#signpayloadwithecdsa) and [`populateTransactionECDSA`](/sdk/js/ethers/api/v6/utilities/smart-account-utils#populatetransactionecdsa). #### Inputs -| Parameter | Type | Description | -| ---------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -| `provider` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) or `null` | The provider to connect the `SmartAccount` to. If `null`, the `SmartAccount` will be detached from any provider. | +| Parameter | Type | Description | +| ----------- | ----------------------------------------------------- | ----------------------------------------------------------------------- | +| `signer` | [`SmartAccountSigner`](/sdk/js/ethers/api/v6/types#smartaccountsigner) | Contains necessary properties for signing payloads. | +| `provider?` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) or `null` | The provider to connect to. Can be `null` for offline usage. | ```ts -connect(provider: null | Provider): SmartAccount +constructor(signer: SmartAccountSigner, provider?: null | Provider) ``` #### Example ```ts -import { Wallet, Provider, types } from "zksync-ethers"; - +import { SmartAccount, Provider, types } from "zksync-ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - -const sepoliaProvider = Provider.getDefaultProvider(types.Network.Sepolia); -const sepoliaAccount = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, sepoliaProvider); - -const mainnetProvider = Provider.getDefaultProvider(types.Network.Mainnet); -const mainnetAccount = sepoliaAccount.connect(mainnetProvider); + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); ``` ### `getAddress` @@ -82,65 +82,65 @@ getAddress(): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const address = await account.getAddress(); ``` -### `getBalance` - -Returns the balance of the account. - -#### Inputs +### `getAllBalances` -| Parameter | Type | Description | -| ---------- | ---------- | -------------------------------------------------------------------------------- | -| `token?` | `Address` | The token address to query balance for. Defaults to the native token. | -| `blockTag` | `BlockTag` | The block tag to get the balance at. Defaults to `committed`. | +Returns all token balances of the account. ```ts -async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise +async getAllBalances(): Promise ``` #### Example ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const balance = await account.getBalance(); + +const balances = await account.getAllBalances(); ``` -### `getAllBalances` +### `getBalance` -Returns all token balances of the account. +Returns the balance of the account. + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ---------- | -------------------------------------------------------------------------------- | +| `token?` | `Address` | The token address to query balance for. Defaults to the native token. | +| `blockTag` | `BlockTag` | The block tag to get the balance at. Defaults to `committed`. | ```ts -async getAllBalances(): Promise +async getBalance(token?: Address, blockTag: BlockTag = 'committed'): Promise ``` #### Example ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const balances = await account.getAllBalances(); + +const balance = await account.getBalance(); ``` ### `getDeploymentNonce` @@ -155,13 +155,13 @@ async getDeploymentNonce(): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const nonce = await account.getDeploymentNonce(); ``` @@ -186,13 +186,13 @@ async populateTransaction(tx: TransactionRequest): Promise ```ts import { SmartAccount, Provider, types, utils } from "zksync-ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const populatedTx = await account.populateTransaction({ type: utils.EIP712_TX_TYPE, to: "", @@ -200,21 +200,19 @@ const populatedTx = await account.populateTransaction({ }); ``` -### `signTransaction` +### `sendTransaction` -Signs the transaction `tx` using the provided [`PayloadSigner`](/sdk/js/ethers/api/v6/types#payloadsigner) function, -returning the fully signed transaction. The `populateTransaction` method -is called first to ensure that all necessary properties for the transaction to be valid -have been populated. +Sends `tx` to the Network. The `signTransaction` +is called first to ensure transaction is properly signed. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------------------------------------------- | ---------------------------------------- | -| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | The transaction that needs to be signed. | +| Parameter | Type | Description | +| --------- | ----------------------------------------------------- | -------------------------------------- | +| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | The transaction that needs to be sent. | ```ts -async signTransaction(tx: TransactionRequest): Promise +async sendTransaction(tx: TransactionRequest): Promise ``` #### Example @@ -222,32 +220,31 @@ async signTransaction(tx: TransactionRequest): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const signedTx = await account.signTransaction({ + +const signedTx = await account.sendTransaction({ to: "", value: ethers.parseEther("1"), }); ``` -### `sendTransaction` +### `signMessage` -Sends `tx` to the Network. The `signTransaction` -is called first to ensure transaction is properly signed. +Signs a `message` using the provided [`PayloadSigner`](/sdk/js/ethers/api/v6/types#payloadsigner) function. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------------------------------------------- | -------------------------------------- | -| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | The transaction that needs to be sent. | +| Parameter | Type | Description | +| --------- | ------------------------ | ------------------------------------ | +| `message` | `string` or `Uint8Array` | The message that needs to be signed. | ```ts -async sendTransaction(tx: TransactionRequest): Promise +signMessage(message: string | Uint8Array): Promise ``` #### Example @@ -255,31 +252,31 @@ async sendTransaction(tx: TransactionRequest): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const signedTx = await account.sendTransaction({ - to: "", - value: ethers.parseEther("1"), -}); + +const signedMessage = await account.signMessage("Hello World!"); ``` -### `signMessage` +### `signTransaction` -Signs a `message` using the provided [`PayloadSigner`](/sdk/js/ethers/api/v6/types#payloadsigner) function. +Signs the transaction `tx` using the provided [`PayloadSigner`](/sdk/js/ethers/api/v6/types#payloadsigner) function, +returning the fully signed transaction. The `populateTransaction` method +is called first to ensure that all necessary properties for the transaction to be valid +have been populated. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------ | ------------------------------------ | -| `message` | `string` or `Uint8Array` | The message that needs to be signed. | +| Parameter | Type | Description | +| --------- | ----------------------------------------------------- | ---------------------------------------- | +| `tx` | [`TransactionRequest`](/sdk/js/ethers/api/v6/types#transactionrequest) | The transaction that needs to be signed. | ```ts -signMessage(message: string | Uint8Array): Promise +async signTransaction(tx: TransactionRequest): Promise ``` #### Example @@ -287,14 +284,17 @@ signMessage(message: string | Uint8Array): Promise ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - -const signedMessage = await account.signMessage("Hello World!"); + +const signedTx = await account.signTransaction({ + to: "", + value: ethers.parseEther("1"), +}); ``` ### `signTypedData` @@ -322,13 +322,13 @@ async signTypedData( ```ts import { SmartAccount, Provider, types } from "zksync-ethers"; import { ethers } from "ethers"; - + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount({ address: ADDRESS, secret: PRIVATE_KEY }, provider); - + const signedTypedData = await account.signTypedData( { name: "Example", version: "1", chainId: 270 }, { @@ -341,75 +341,79 @@ const signedTypedData = await account.signTypedData( ); ``` -### `withdraw` +### `transfer` -Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 -network to the target account on L1 network. +Transfer ETH or any ERC20 token within the same interface. #### Inputs -| Parameter | Type | Description | -| ------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | -| `transaction.token` | `Address` | The address of the token. `ETH` by default. | -| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | -| `transaction.to?` | `Address` | The address of the recipient on L1. | -| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | -| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass l2 `gasLimit`, `gasPrice`, `value`, etc. | +| Parameter | Type | Description | +| ------------------------------ | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | +| `transaction.to` | `Address` | The address of the recipient. | +| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | +| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | +| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass l2 `gasLimit`,
`gasPrice`, `value`, etc. | ```ts -async withdraw(transaction: { - token: Address; +async transfer(transaction: { + to: Address; amount: BigNumberish; - to?: Address; - bridgeAddress?: Address; + token ? : Address; paymasterParams?: PaymasterParams; - overrides?: ethers.Overrides; -}): Promise + overrides ? : ethers.Overrides; +}): Promise ``` #### Examples -Withdraw ETH. +Transfer ETH. ```ts -import { SmartAccount, Provider, types, utils } from "zksync-ethers"; - +import { SmartAccount, Wallet, Provider, types } from "zksync-ethers"; +import { ethers } from "ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const withdrawTx = await account.withdraw({ + +const transferTx = await account.transfer({ token: utils.ETH_ADDRESS, - amount: 10_000_000n, + 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}`); ``` -Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. +Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. ```ts -import { SmartAccount, Provider, types, utils } from "zksync-ethers"; - +import { SmartAccount, Wallet, Provider, utils } from "zksync-ethers"; +import { ethers } from "ethers"; + const ADDRESS = "
"; const 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 account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const withdrawTx = await account.withdraw({ - token: utils.ETH_ADDRESS, - amount: 10_000_000n, + +const transferTx = await account.transfer({ + to: Wallet.createRandom().address, + amount: ethers.parseEther("0.01"), paymasterParams: utils.getPaymasterParams(paymaster, { type: "ApprovalBased", token: token, @@ -417,81 +421,81 @@ const withdrawTx = await account.withdraw({ innerInput: new Uint8Array(), }), }); + +const receipt = await transferTx.wait(); + +console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` -### `transfer` +### `withdraw` -Transfer ETH or any ERC20 token within the same interface. +Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 +network to the target account on L1 network. #### Inputs -| Parameter | Type | Description | -| ------------------------------ | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | -| `transaction.to` | `Address` | The address of the recipient. | -| `transaction.amount` | `BigNumberish` | The amount of the token to transfer. | -| `transaction.token?` | `Address` | The address of the token. `ETH` by default. | -| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | -| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass l2 `gasLimit`,
`gasPrice`, `value`, etc. | +| Parameter | Type | Description | +| ------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| `transaction.token` | `Address` | The address of the token. `ETH` by default. | +| `transaction.amount` | `BigNumberish` | The amount of the token to withdraw. | +| `transaction.to?` | `Address` | The address of the recipient on L1. | +| `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. | +| `transaction.paymasterParams?` | [`PaymasterParams`](/sdk/js/ethers/api/v6/types#paymasterparams) | Paymaster parameters. | +| `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass l2 `gasLimit`, `gasPrice`, `value`, etc. | ```ts -async transfer(transaction: { - to: Address; +async withdraw(transaction: { + token: Address; amount: BigNumberish; - token ? : Address; + to?: Address; + bridgeAddress?: Address; paymasterParams?: PaymasterParams; - overrides ? : ethers.Overrides; -}): Promise + overrides?: ethers.Overrides; +}): Promise ``` #### Examples -Transfer ETH. +Withdraw ETH. ```ts -import { SmartAccount, Wallet, Provider, types } from "zksync-ethers"; -import { ethers } from "ethers"; - +import { SmartAccount, Provider, types, utils } from "zksync-ethers"; + const ADDRESS = "
"; const PRIVATE_KEY = ""; - + const provider = Provider.getDefaultProvider(types.Network.Sepolia); const account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const transferTx = await account.transfer({ + +const withdrawTx = await account.withdraw({ token: utils.ETH_ADDRESS, - to: Wallet.createRandom().address, - amount: ethers.parseEther("0.01"), + amount: 10_000_000n, }); - -const receipt = await transferTx.wait(); - -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` -Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. +Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. ```ts -import { SmartAccount, Wallet, Provider, utils } from "zksync-ethers"; -import { ethers } from "ethers"; - +import { SmartAccount, Provider, types, utils } from "zksync-ethers"; + const ADDRESS = "
"; const 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 account = new SmartAccount( {address: ADDRESS, secret: PRIVATE_KEY}, provider ); - -const transferTx = await account.transfer({ - to: Wallet.createRandom().address, - amount: ethers.parseEther("0.01"), + +const withdrawTx = await account.withdraw({ + token: utils.ETH_ADDRESS, + amount: 10_000_000n, paymasterParams: utils.getPaymasterParams(paymaster, { type: "ApprovalBased", token: token, @@ -499,8 +503,4 @@ const transferTx = await account.transfer({ innerInput: new Uint8Array(), }), }); - -const receipt = await transferTx.wait(); - -console.log(`The sum of ${receipt.value} ETH was transferred to ${receipt.to}`); ``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/00.utils.md b/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/00.utils.md index 6dd96106..b8cb0b87 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/00.utils.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/00.utils.md @@ -237,7 +237,6 @@ const REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT = 800; ``` ## Functions - ### `applyL1ToL2Alias` Converts the address that submitted a transaction to the inbox on L1 to the `msg.sender` viewed on L2. @@ -290,18 +289,6 @@ Throws an error if it is not. async function checkBaseCost(baseCost: ethers.BigNumberish, value: ethers.BigNumberish | Promise): Promise; ``` -### Example - -```ts -const baseCost = 100; -const value = 99; -try { - await utils.checkBaseCost(baseCost, value); -} catch (e) { - // e.message = `The base cost of performing the priority operation is higher than the provided value parameter for the transaction: baseCost: ${baseCost}, provided value: ${value}`, -} -``` - ### `create2Address` Generates a future-proof contract address using salt plus bytecode which allows determination of an address before deployment. @@ -435,21 +422,6 @@ Returns the calldata sent by an L1 ERC20 bridge to its L2 counterpart during tok async function getERC20BridgeCalldata(l1TokenAddress: string, l1Sender: string, l2Receiver: string, amount: BigNumberish, bridgeData: BytesLike): Promise; ``` -### `getL2HashFromPriorityOp` - -Returns the hash of the L2 priority operation from a given transaction receipt and L2 address. - -#### Inputs - -| Parameter | Type | Description | -| --------------- | --------------------------- | ------------------------------------ | -| `txReceipt` | `ethers.TransactionReceipt` | Receipt of the L1 transaction. | -| `zkSyncAddress` | `Address` | Address of ZKsync Era main contract. | - -```ts -function getL2HashFromPriorityOp(txReceipt: ethers.TransactionReceipt, zkSyncAddress: Address): string; -``` - ### `getHashedL2ToL1Msg` Returns a keccak encoded message with a given sender address and block number from the L1 messenger contract. @@ -474,6 +446,21 @@ const withdrawETHMessageHash = utils.getHashedL2ToL1Msg("0x36615Cf349d7F6344891B // withdrawETHMessageHash = "0xd8c80ecb64619e343f57c3b133c6c6d8dd0572dd3488f1ca3276c5b7fd3a938d" ``` +### `getL2HashFromPriorityOp` + +Returns the hash of the L2 priority operation from a given transaction receipt and L2 address. + +#### Inputs + +| Parameter | Type | Description | +| --------------- | --------------------------- | ------------------------------------ | +| `txReceipt` | `ethers.TransactionReceipt` | Receipt of the L1 transaction. | +| `zkSyncAddress` | `Address` | Address of ZKsync Era main contract. | + +```ts +function getL2HashFromPriorityOp(txReceipt: ethers.TransactionReceipt, zkSyncAddress: Address): string; +``` + ### `hashBytecode` Returns the hash of given bytecode. @@ -523,7 +510,7 @@ function isAddressEq(a: Address, b: Address): boolean ```ts import { Wallet, utils } from "zksync-ethers"; - + utils.isAddressEq("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", "0x36615cf349d7f6344891b1e7ca7c72883f5dc049") // true ``` @@ -551,15 +538,15 @@ function isECDSASignatureCorrect(address: string, msgHash: string, signature: Si ```ts import { Wallet, utils } from "zksync-ethers"; - + const ADDRESS = ""; const PRIVATE_KEY = ""; - + const message = "Hello, world!"; const signature = await new Wallet(PRIVATE_KEY).signMessage(message); // ethers.Wallet can be used as well // const signature = await new ethers.Wallet(PRIVATE_KEY).signMessage(message); - + const isValidSignature = await utils.isECDSASignatureCorrect(ADDRESS, message, signature); // isValidSignature = true ``` @@ -638,16 +625,16 @@ async function isMessageSignatureCorrect(provider: Provider, address: string, me ```ts import { Wallet, utils, Provider } from "zksync-ethers"; - + const ADDRESS = ""; const PRIVATE_KEY = ""; const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const message = "Hello, world!"; const signature = await new Wallet(PRIVATE_KEY).signMessage(message); // ethers.Wallet can be used as well // const signature = await new ethers.Wallet(PRIVATE_KEY).signMessage(message); - + const isValidSignature = await utils.isMessageSignatureCorrect(provider, ADDRESS, message, signature); // isValidSignature = true ``` @@ -701,11 +688,11 @@ async function isTypedDataSignatureCorrect( ```ts import { Wallet, utils, Provider, EIP712Signer } from "zksync-ethers"; - + const ADDRESS = ""; const PRIVATE_KEY = ""; const provider = Provider.getDefaultProvider(types.Network.Sepolia); - + const tx: types.TransactionRequest = { type: 113, chainId: 270, @@ -713,14 +700,14 @@ const tx: types.TransactionRequest = { to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", value: BigInt(7_000_000), }; - + const eip712Signer = new EIP712Signer( new Wallet(PRIVATE_KEY), // or new ethers.Wallet(PRIVATE_KEY), Number((await provider.getNetwork()).chainId) ); - + const signature = await eip712Signer.sign(tx); - + const isValidSignature = await utils.isTypedDataSignatureCorrect(provider, ADDRESS, await eip712Signer.getDomain(), utils.EIP712_TYPES, EIP712Signer.getSignInput(tx), signature); // isValidSignature = true ``` @@ -739,37 +726,6 @@ Parses an EIP712 transaction from a payload. function parseEip712(payload: ethers.BytesLike): TransactionLike; ``` -### Example - -```ts -import { types } from "zksync-ethers"; - -const serializedTx = - "0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0"; -const tx: types.TransactionLike = utils.parseEip712(serializedTx); -/* -tx: types.TransactionLike = { - type: 113, - nonce: 0, - maxPriorityFeePerGas: BigInt(0), - maxFeePerGas: BigInt(0), - gasLimit: BigInt(0), - to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", - value: BigInt(1000000), - data: "0x", - chainId: BigInt(270), - from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", - customData: { - gasPerPubdata: BigInt(50000), - factoryDeps: [], - customSignature: "0x", - paymasterParams: null, - }, - hash: "0x9ed410ce33179ac1ff6b721060605afc72d64febfe0c08cacab5a246602131ee", -}; - */ -``` - ### `serializeEip712` Serializes an EIP712 transaction and include a signature if it is provided. Throws an error if: @@ -797,7 +753,7 @@ Serialize EIP712 transaction without signature. ```ts const serializedTx = utils.serializeEip712({ chainId: 270, from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" }, null); - + // serializedTx = "0x71ea8080808080808082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0" ``` @@ -805,7 +761,7 @@ Serialize EIP712 transaction with signature. ```ts const signature = ethers.Signature.from("0x73a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aaf87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a"); - + const serializedTx = utils.serializeEip712( { chainId: 270, @@ -832,6 +788,29 @@ Common sleep function that pauses execution for a number of milliseconds. function sleep(millis: number); ``` +### `toJSON` + +Creates a JSON string from an object, including support for serializing bigint types. + +```ts +function toJSON(object: any): string; +``` + +#### Inputs + +| Parameter | Type | Description | +|-----------|------|-------------| +| `object` | any | Any object. | + +#### Example + +```ts +import { utils } from "zksync-ethers"; + +const json = utils.toJSON({gasLimit: 1_000n}) +// {"gasLimit": 1000} +``` + ### `undoL1ToL2Alias` Converts and returns the `msg.sender` viewed on L2 to the address that submitted a transaction to the inbox on L1. @@ -858,25 +837,45 @@ const l1ContractAddress = utils.undoL1ToL2Alias(l2ContractAddress); See also [`applyl1tol2alias`](#applyl1tol2alias). :: -### `toJSON` - -Creates a JSON string from an object, including support for serializing bigint types. +### Example ```ts -function toJSON(object: any): string; +const baseCost = 100; +const value = 99; +try { + await utils.checkBaseCost(baseCost, value); +} catch (e) { + // e.message = `The base cost of performing the priority operation is higher than the provided value parameter for the transaction: baseCost: ${baseCost}, provided value: ${value}`, +} ``` -#### Inputs - -| Parameter | Type | Description | -|-----------|------|-------------| -| `object` | any | Any object. | - -#### Example +### Example ```ts -import { utils } from "zksync-ethers"; - -const json = utils.toJSON({gasLimit: 1_000n}) -// {"gasLimit": 1000} +import { types } from "zksync-ethers"; + +const serializedTx = + "0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0"; +const tx: types.TransactionLike = utils.parseEip712(serializedTx); +/* +tx: types.TransactionLike = { + type: 113, + nonce: 0, + maxPriorityFeePerGas: BigInt(0), + maxFeePerGas: BigInt(0), + gasLimit: BigInt(0), + to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618", + value: BigInt(1000000), + data: "0x", + chainId: BigInt(270), + from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + customData: { + gasPerPubdata: BigInt(50000), + factoryDeps: [], + customSignature: "0x", + paymasterParams: null, + }, + hash: "0x9ed410ce33179ac1ff6b721060605afc72d64febfe0c08cacab5a246602131ee", +}; + */ ``` diff --git a/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/02.smart-account-utils.md b/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/02.smart-account-utils.md index 3fba22a3..8a525ec2 100644 --- a/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/02.smart-account-utils.md +++ b/content/sdk/10.js/00.ethers/05.api/20.v6/04.utilities/02.smart-account-utils.md @@ -8,6 +8,91 @@ This module provides utilities for signing transactions with ECDSA private keys ## Functions +### `populateTransactionECDSA` + +Populates missing properties meant for signing using an ECDSA private key: + +- Populates `from` using the address derived from the ECDSA private key. +- Populates `nonce` via `provider.getTransactionCount(tx.from, "pending")`. +- Populates `gasLimit` via `provider.estimateGas(tx)`. If `tx.from` is not EOA, the estimation is done with address + derived from the ECDSA private key. +- Populates `chainId` via `provider.getNetwork()`. +- Populates `type` with `utils.EIP712_TX_TYPE`. +- Populates `value` by converting to `bigint` if set, otherwise to `0n`. +- Populates `data` with `0x`. +- Populates `customData` with `{factoryDeps=[], gasPerPubdata=utils.DEFAULT_GAS_PER_PUBDATA_LIMIT}`. + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ------------------------------------------------------------------------------------ |---------------------------------------------------| +| `tx` | `BytesLike` | The transaction that needs to be populated. | +| `secret` | `string` or [`ethers.SigningKey`](https://docs.ethers.org/v6/api/crypto/#SigningKey) | The ECDSA private key. | +| `provider` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) | The provider which fetches data from the network. | + +```ts +const populateTransactionECDSA: TransactionBuilder = async (tx, secret: string | SigningKey, provider) +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const PRIVATE_KEY = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); + +const populatedTx = await utils.populateTransactionECDSA( + { + chainId: 270, + to: "", + value: 7_000_000_000, + }, + PRIVATE_KEY, + provider +); +``` + +### `populateTransactionMultisigECDSA` + +Populates missing properties meant for signing using multiple ECDSA private keys. +It uses [`populateTransactionECDSA`](#populatetransactionecdsa), where the address +of the first ECDSA key is set as the `secret` argument. + +#### Inputs + +| Parameter | Type | Description | +| ---------- | ---------------------------------------------------------------------------------------- |-------------------------------------------------------------------------| +| `tx` | `BytesLike` | The transaction that needs to be populated. | +| `secret` | `string[]` or [`ethers.SigningKey[]`](https://docs.ethers.org/v6/api/crypto/#SigningKey) | The list of the ECDSA private keys used for populating the transaction. | +| `provider` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) | The provider which fetches data from the network. | + +```ts +const populateTransactionMultisigECDSA: TransactionBuilder = async (tx, secret: string[] | SigningKey[], provider) +``` + +#### Example + +```ts +import { Provider, types, utils } from "zksync-ethers"; + +const PRIVATE_KEY1 = ""; +const PRIVATE_KEY2 = ""; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); + +const populatedTx = await utils.populateTransactionMultisigECDSA( + { + chainId: 270, + to: "", + value: 7_000_000_000, + }, + [PRIVATE_KEY1, PRIVATE_KEY2], + provider +); +``` + ### `signPayloadWithECDSA` Signs the `payload` using an ECDSA private key. @@ -156,88 +241,3 @@ const typedDataHash = TypedDataEncoder.hash( ); const result = await utils.signPayloadWithMultipleECDSA(typedDataHash, [PRIVATE_KEY1, PRIVATE_KEY2]); ``` - -## `populateTransactionECDSA` - -Populates missing properties meant for signing using an ECDSA private key: - -- Populates `from` using the address derived from the ECDSA private key. -- Populates `nonce` via `provider.getTransactionCount(tx.from, "pending")`. -- Populates `gasLimit` via `provider.estimateGas(tx)`. If `tx.from` is not EOA, the estimation is done with address - derived from the ECDSA private key. -- Populates `chainId` via `provider.getNetwork()`. -- Populates `type` with `utils.EIP712_TX_TYPE`. -- Populates `value` by converting to `bigint` if set, otherwise to `0n`. -- Populates `data` with `0x`. -- Populates `customData` with `{factoryDeps=[], gasPerPubdata=utils.DEFAULT_GAS_PER_PUBDATA_LIMIT}`. - -#### Inputs - -| Parameter | Type | Description | -| ---------- | ------------------------------------------------------------------------------------ |---------------------------------------------------| -| `tx` | `BytesLike` | The transaction that needs to be populated. | -| `secret` | `string` or [`ethers.SigningKey`](https://docs.ethers.org/v6/api/crypto/#SigningKey) | The ECDSA private key. | -| `provider` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) | The provider which fetches data from the network. | - -```ts -const populateTransactionECDSA: TransactionBuilder = async (tx, secret: string | SigningKey, provider) -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const PRIVATE_KEY = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); - -const populatedTx = await utils.populateTransactionECDSA( - { - chainId: 270, - to: "", - value: 7_000_000_000, - }, - PRIVATE_KEY, - provider -); -``` - -## `populateTransactionMultisigECDSA` - -Populates missing properties meant for signing using multiple ECDSA private keys. -It uses [`populateTransactionECDSA`](#populatetransactionecdsa), where the address -of the first ECDSA key is set as the `secret` argument. - -#### Inputs - -| Parameter | Type | Description | -| ---------- | ---------------------------------------------------------------------------------------- |-------------------------------------------------------------------------| -| `tx` | `BytesLike` | The transaction that needs to be populated. | -| `secret` | `string[]` or [`ethers.SigningKey[]`](https://docs.ethers.org/v6/api/crypto/#SigningKey) | The list of the ECDSA private keys used for populating the transaction. | -| `provider` | [`Provider`](/sdk/js/ethers/api/v6/providers/provider) | The provider which fetches data from the network. | - -```ts -const populateTransactionMultisigECDSA: TransactionBuilder = async (tx, secret: string[] | SigningKey[], provider) -``` - -#### Example - -```ts -import { Provider, types, utils } from "zksync-ethers"; - -const PRIVATE_KEY1 = ""; -const PRIVATE_KEY2 = ""; - -const provider = Provider.getDefaultProvider(types.Network.Sepolia); - -const populatedTx = await utils.populateTransactionMultisigECDSA( - { - chainId: 270, - to: "", - value: 7_000_000_000, - }, - [PRIVATE_KEY1, PRIVATE_KEY2], - provider -); -``` diff --git a/content/sdk/20.go/02.api/00.clients/01.baseclient.md b/content/sdk/20.go/02.api/00.clients/01.baseclient.md index 2124bccd..8c266ed2 100644 --- a/content/sdk/20.go/02.api/00.clients/01.baseclient.md +++ b/content/sdk/20.go/02.api/00.clients/01.baseclient.md @@ -8,64 +8,94 @@ The `BaseClient` is the primary implementation of the `Client` interface. It fac interaction with the ZKsync Era RPC API, providing the necessary methods to perform various blockchain operations. The `BaseClient` leverages both Ethereum RPC methods and ZKsync-specific functionalities to offer a comprehensive toolset for developers. +### `AllAccountBalances` -### `Init` +Returns all balances for confirmed tokens given by an account address. -`Dial` connects a client to the given URL. +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------- | ---------------- | +| `ctx` | `context.Context` | Context. | +| `address` | `common.Address` | Account address. | ```go -func Dial(rawUrl string) (Client, error) +AllAccountBalances(ctx context.Context, address common.Address) (map[common.Address]*big.Int, error) ``` -`DialContext` connects a client to the given URL with context. +#### Example ```go -func DialContext(ctx context.Context, rawUrl string) (Client, error) +// Paymaster on testnet +paymaster := common.HexToAddress("0x8f0ea1312da29f17eabeb2f484fd3c112cccdd63") +balances, err := client.AllAccountBalances(context.Background(), paymaster) +if err != nil { + log.Panic(err) +} +fmt.Printf("Balances: %+v\n", balances) ``` -`NewClient` creates a client that uses the given RPC client. +### `BaseTokenContractAddress` + +Returns the L1 base token address. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -func NewClient(c *rpc.Client) Client +BaseTokenContractAddress(ctx context.Context) (common.Address, error) ``` #### Example ```go -ZkSyncEraProvider := "https://testnet.era.zksync.dev" -ZkSyncEraWSProvider := "ws://testnet.era.zksync.dev:3051" - -// Connect to ZKsync network -client, err := clients.DialBase(ZkSyncEraProvider) +address, err := client.BaseTokenContractAddress(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -defer client.Close() +fmt.Println("Base token address: ", address) +``` -// Connect to ZKsync network using Web Socket -wsClient, err := clients.DialBase(ZkSyncEraWSProvider) +### `BlockDetails` + +Returns additional ZKsync Era-specific information about the L2 block. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------- | ---------------- | +| `ctx` | `context.Context` | Context. | +| `block` | `uint32` | L2 block number. | + +```go +BlockDetails(ctx context.Context, block uint32) (*zkTypes.BlockDetails, error) +``` + +#### Example + +```go +blockDetails, err := client.BlockDetails(context.Background(), 90000) if err != nil { - log.Panic(err) + log.Panic(err) } -defer wsClient.Close() +fmt.Printf("Block details: %+v\n", *blockDetails) ``` -### `FilterLogsL2` +### `BridgeContracts` -Executes a log filter operation, blocking during execution, and returns all the results in one batch. This method is -a replacement for `FilterLogs` because the returned `types.Log` type does not contain additional data specific to L2, -as found in [`Log`](/sdk/go/api/types#log). The `FilterLogs` method is kept in order to be compatible with `bind.ContractBackend`, -and this method can be used, but additional L2 data won't be retrieved. +Returns the addresses of the default ZKsync Era bridge contracts on both L1 and L2. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------------------------------------------------------------------------------ | ------------------------ | -| `ctx` | `context.Context` | Context. | -| `query` | [`ethereum.FilterQuery`](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.12.0#FilterQuery) | Filter query parameters. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -FilterLogsL2(ctx context.Context, query ethereum.FilterQuery) ([]zkTypes.Log, error) +BridgeContracts(ctx context.Context) (*zkTypes.BridgeContracts, error) ``` #### Example @@ -75,72 +105,87 @@ contracts, err := client.BridgeContracts(context.Background()) if err != nil { log.Panic(err) } -zkLogs, err := client.FilterLogsL2(context.Background(), ethereum.FilterQuery{ - FromBlock: big.NewInt(0), - ToBlock: big.NewInt(1000), - Addresses: []common.Address{contracts.L2Erc20DefaultBridge}, -}) -if err != nil { - log.Panic(err) -} +fmt.Println("Bridge contracts: ", contracts) +``` -for _, l := range zkLogs { - fmt.Println("Log address:", l.Address.Hex()) - fmt.Println("Log data:", l.Data) - fmt.Println("L1 batch number: ", l.L1BatchNumber) +### `BridgehubContractAddress` + +Returns the Bridgehub smart contract address. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | + +```go +BridgehubContractAddress(ctx context.Context) (common.Address, error) +``` + +#### Example + +```go +address, err := client.BridgehubContractAddress(context.Background()) +if err != nil { + log.Panic() } +fmt.Println("Bridgehub address: ", address) ``` -### `SubscribeFilterLogsL2` +### `BytecodeByHash` -Creates a background log filtering operation, returning a subscription immediately, which can be used to stream the -found events. This method is a replacement for `SubscribeFilterLogs` because the returned `types.Log` type does not -contain additional data specific to L2, as found -in [`Log`](/sdk/go/api/types#log). The `SubscribeFilterLogs` method is -kept in order to be compatible with `bind.ContractBackend`, and this method can be used, but additional L2 data -won't be retrieved. +returns bytecode of a contract given by its hash. #### Inputs -| Parameter | Type | Description | -| --------- | --------------------------------------------------------------------------------------------- | -------------------------- | -| `ctx` | `context.Context` | Context. | -| `query` | [`ethereum.FilterQuery`](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.12.0#FilterQuery) | Filter query parameters. | -| `ch` | [`chan<- zkTypes.Log`](/sdk/go/api/types#log) | Channel that receives Log. | +| Parameter | Type | Description | +|----------------| ----------------- |----------------| +| `ctx` | `context.Context` | Context. | +| `bytecodeHash` | `common.Hash` | Bytecode hash. | ```go -SubscribeFilterLogsL2(ctx context.Context, query ethereum.FilterQuery, ch chan<- zkTypes.Log) (ethereum.Subscription, error) +BytecodeByHash(ctx context.Context, bytecodeHash common.Hash) ([]byte, error) ``` #### Example ```go -contracts, err := client.BridgeContracts(context.Background()) +testnetPaymaster, err := client.TestnetPaymaster(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } - -filterLogs := make(chan zkTypes.Log) -sub, err := wsClient.SubscribeFilterLogsL2(context.Background(), ethereum.FilterQuery{ - FromBlock: big.NewInt(0), - ToBlock: big.NewInt(1000), - Addresses: []common.Address{contracts.L2Erc20DefaultBridge}, -}, filterLogs) +testnetPaymasterBytecode, err := client.CodeAt(context.Background(), testnetPaymaster, nil) if err != nil { - log.Panic(err) + log.Panic(err) } -defer sub.Unsubscribe() - -for { - select { - case err := <-sub.Err(): - log.Println(err) - break - case l := <-filterLogs: - fmt.Println("Address: ", l.Address) - fmt.Println("Data", l.Data) - } + +testnetPaymasterBytecodeHash, err := utils.HashBytecode(testnetPaymasterBytecode) +if err != nil { + log.Panic(err) } + +bytecode, err := client.BytecodeByHash(context.Background(), common.BytesToHash(testnetPaymasterBytecodeHash)) +if err != nil { + log.Panic(err) +} +fmt.Println("Bytecode: ", bytecode) +``` + +### `CallContractAtHashL2` + +Almost the same as [`CallContractL2`](#callcontractl2) except that it selects the block by block hash instead of +block height. + +#### Inputs + +| Parameter | Type | Description | +| ----------- | ---------------------------------------- | ---------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | +| `blockHash` | `common.Hash` | Block hash. | + +```go +CallContractAtHashL2(ctx context.Context, msg zkTypes.CallMsg, blockHash common.Hash) ([]byte, error) ``` ### `CallContractL2` @@ -165,71 +210,94 @@ CallContractL2(ctx context.Context, msg zkTypes.CallMsg, blockNumber *big.Int) ( ```go // The Crown token on testnet TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") - + tokenAbi, err := erc20.IERC20MetaData.GetAbi() if err != nil { - log.Panic(err) + log.Panic(err) } symbolCalldata, err := tokenAbi.Pack("symbol") if err != nil { - log.Panic(err) + log.Panic(err) } - + result, err := client.CallContractL2(context.Background(), types.CallMsg{ - CallMsg: ethereum.CallMsg{ - To: &TokenAddress, - Data: symbolCalldata, - }, + CallMsg: ethereum.CallMsg{ + To: &TokenAddress, + Data: symbolCalldata, + }, }, nil) if err != nil { - log.Panic(err) + log.Panic(err) } unpack, err := tokenAbi.Unpack("symbol", result) if err != nil { - log.Panic(err) + log.Panic(err) } symbol := *abi.ConvertType(unpack[0], new(string)).(*string) fmt.Println("Symbol: ", symbol) ``` -### `CallContractAtHashL2` +### `ConfirmedTokens` -Almost the same as [`CallContractL2`](#callcontractl2) except that it selects the block by block hash instead of -block height. +Returns {address, symbol, name, and decimal} information of all tokens within a range of ids given by +parameters from and limit. #### Inputs -| Parameter | Type | Description | -| ----------- | ---------------------------------------- | ---------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | -| `blockHash` | `common.Hash` | Block hash. | +| Parameter | Type | Description | +| --------- | ----------------- | ---------------------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `from` | `uint32` | The token id from which to start returning the information about the tokens. | +| `limit` | `limit` | The number of tokens to be returned from the API. | ```go -CallContractAtHashL2(ctx context.Context, msg zkTypes.CallMsg, blockHash common.Hash) ([]byte, error) +ConfirmedTokens(ctx context.Context, from uint32, limit uint8) ([]*zkTypes.Token, error) ``` -### `PendingCallContractL2` +#### Example -Almost the same as [`CallContractL2`](#callcontractl2) except that the state seen by the contract call is the -pending state. +```go +// get first 255 tokens +tokens, err := client.ConfirmedTokens(context.Background(), 0, 255) +if err != nil { + log.Panic(err) +} + +for _, token := range tokens { + fmt.Printf("%+v\n", *token) +} +``` + +### `ContractAccountInfo` + +Returns the version of the supported account abstraction and nonce ordering from a given contract address. #### Inputs -| Parameter | Type | Description | -| --------- | ---------------------------------------- | ---------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `address` | `common.Address` | Contract address. | ```go -PendingCallContractL2(ctx context.Context, msg zkTypes.CallMsg) ([]byte, error) +ContractAccountInfo(ctx context.Context, address common.Address) (*zkTypes.ContractAccountInfo, error) ``` -### `EstimateGasL2` +#### Example -Tries to estimate the gas needed to execute an EIP-712 transaction based on the current pending state of -the backend blockchain. There is no guarantee that this is the true gas limit requirement as other -transactions may be added or removed by miners, but it should provide a basis for setting a reasonable default. +```go +// Paymaster for Crown token on testnet +PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") +accountInfo, err := client.ContractAccountInfo(context.Background(), PaymasterAddress) +if err != nil { + log.Panic() +} +fmt.Printf("Account info: %+v\n", accountInfo) +``` + +### `EstimateFee` + +Returns the fee for the transaction. #### Inputs @@ -239,70 +307,77 @@ transactions may be added or removed by miners, but it should provide a basis fo | `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | ```go -EstimateGasL2(ctx context.Context, msg zkTypes.CallMsg) (uint64, error) +EstimateFee(ctx context.Context, tx zkTypes.CallMsg) (*zkTypes.Fee, error) ``` #### Example ```go -// The Crown token on testnet -TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") -// Paymaster for Crown token on testnet -PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") -ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") - -abi, err := erc20.IERC20MetaData.GetAbi() +from := common.HexToAddress("") +to := common.HexToAddress("") +fee, err := client.EstimateFee(context.Background(), zkTypes.CallMsg{ + CallMsg: ethereum.CallMsg{ + From: from, + To: &to, + Value: big.NewInt(7_000_000_000), + }, +}) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Printf("Fee: %+v\n", *fee) +``` -// Encode transfer function from token contract -calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7)) -if err != nil { - log.Panic(err) -} +### `EstimateGasL1` -// Create paymaster parameters with encoded paymaster input -paymasterParams, err := utils.GetPaymasterParams( - PaymasterAddress, - &zkTypes.ApprovalBasedPaymasterInput{ - Token: TokenAddress, - MinimalAllowance: big.NewInt(1), - InnerInput: []byte{}, - }) -if err != nil { - log.Panic(err) -} +Estimates the amount of gas required to submit a transaction from L1 to L2. -gas, err := client.EstimateGasL2(context.Background(), zkTypes.CallMsg{ - CallMsg: ethereum.CallMsg{ - To: &TokenAddress, - Data: calldata, - }, - Meta: &zkTypes.Eip712Meta{ - PaymasterParams: paymasterParams, - }, -}) +#### Inputs + +| Parameter | Type | Description | +| --------- | ---------------------------------------- | ---------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | + +```go +EstimateGasL1(ctx context.Context, tx zkTypes.CallMsg) (uint64, error) +``` + +#### Example + +```go +account := common.HexToAddress("
") +gas, err := client.EstimateGasL1(context.Background(), zkTypes.CallMsg{ + CallMsg: ethereum.CallMsg{ + From: account, + To: &account, + Value: big.NewInt(7_000_000_000), + }, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.RequiredL1ToL2GasPerPubdataLimit.Int64()), + }, +}) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Gas: ", gas) ``` -### `SendRawTransaction` +### `EstimateGasL2` -Injects a signed raw transaction into the pending pool for execution. -Is meant to be used for sending EIP-712 transaction. +Tries to estimate the gas needed to execute an EIP-712 transaction based on the current pending state of +the backend blockchain. There is no guarantee that this is the true gas limit requirement as other +transactions may be added or removed by miners, but it should provide a basis for setting a reasonable default. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ---------------- | -| `ctx` | `context.Context` | Context. | -| `tx` | `[]byte` | Raw transaction. | +| Parameter | Type | Description | +| --------- | ---------------------------------------- | ---------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | ```go -SendRawTransaction(ctx context.Context, tx []byte) (common.Hash, error) +EstimateGasL2(ctx context.Context, msg zkTypes.CallMsg) (uint64, error) ``` #### Example @@ -313,246 +388,245 @@ TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F" // Paymaster for Crown token on testnet PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") - -w, err := accounts.NewWallet(common.Hex2Bytes(), &client, nil) -if err != nil { - log.Panic(err) -} - + abi, err := erc20.IERC20MetaData.GetAbi() if err != nil { - log.Panic(err) + log.Panic(err) } - -// Encode mint function from token contract + +// Encode transfer function from token contract calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7)) if err != nil { - log.Panic(err) + log.Panic(err) } - + // Create paymaster parameters with encoded paymaster input paymasterParams, err := utils.GetPaymasterParams( - PaymasterAddress, - &zkTypes.ApprovalBasedPaymasterInput{ - Token: TokenAddress, - MinimalAllowance: big.NewInt(1), - InnerInput: []byte{}, - }) + PaymasterAddress, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: TokenAddress, + MinimalAllowance: big.NewInt(1), + InnerInput: []byte{}, + }) if err != nil { - log.Panic(err) + log.Panic(err) } - -hash, err := w.SendTransaction(context.Background(), &accounts.Transaction{ - To: &TokenAddress, - Data: calldata, - Meta: &zkTypes.Eip712Meta{ - PaymasterParams: paymasterParams, - }, + +gas, err := client.EstimateGasL2(context.Background(), zkTypes.CallMsg{ + CallMsg: ethereum.CallMsg{ + To: &TokenAddress, + Data: calldata, + }, + Meta: &zkTypes.Eip712Meta{ + PaymasterParams: paymasterParams, + }, }) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Tx: ", hash) +fmt.Println("Gas: ", gas) ``` -### `WaitMined` +### `EstimateGasTransfer` -Waits for transaction to be mined on the L2. It stops waiting when the context is canceled. +Estimates the amount of gas required for a transfer transaction. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `txHash` | `common.Hash` | Transaction hash. | +| Parameter | Type | Description | +| --------- | -------------------------------------------------- | -------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`TransferCallMsg`](/sdk/go/api/accounts/types#transfercallmsg) | Contains parameters for transfer call. | ```go -WaitMined(ctx context.Context, txHash common.Hash) (*zkTypes.Receipt, error) +EstimateGasTransfer(ctx context.Context, msg TransferCallMsg) (uint64, error) ``` #### Example ```go -// Create wallet -w, err := accounts.NewWallet(common.Hex2Bytes(), &client, nil) -if err != nil { - log.Panic(err) -} - -tx, err := w.Transfer(accounts.TransferTransaction{ - To: common.HexToAddress(
), - Amount: big.NewInt(7_000_000_000), - Token: utils.EthAddress, +gas, err := client.EstimateGasTransfer(context.Background(), clients.TransferCallMsg{ + From: common.HexToAddress(""), + To: common.HexToAddress(""), + Amount: big.NewInt(7_000_000_000), + Token: utils.EthAddress, }) if err != nil { - log.Panic(err) -} - -// Wait for transaction to be mined on L2 network -_, err = client.WaitMined(context.Background(), tx.Hash()) -if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("Gas: ", gas) ``` -### `WaitFinalized` +### `EstimateGasWithdraw` -Waits for tx to be finalized on the L2. It stops waiting when the context is canceled. +Estimates the amount of gas required for a withdrawal transaction. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `txHash` | `common.Hash` | Transaction hash. | +| Parameter | Type | Description | +| --------- | ------------------------------------------------------ | ---------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`WithdrawalCallMsg`](/sdk/go/api/accounts/types#withdrawalcallmsg) | Contains parameters for withdrawal call. | ```go -WaitFinalized(ctx context.Context, txHash common.Hash) (*zkTypes.Receipt, error) +EstimateGasWithdraw(ctx context.Context, msg WithdrawalCallMsg) (uint64, error) ``` #### Example ```go -// Create wallet -w, err := accounts.NewWallet(common.Hex2Bytes(), &client, nil) -if err != nil { - log.Panic(err) -} - -tx, err := w.Transfer(accounts.TransferTransaction{ - To: common.HexToAddress(
), - Amount: big.NewInt(7_000_000_000), - Token: utils.EthAddress, +gas, err := client.EstimateGasWithdraw(context.Background(), clients.WithdrawalCallMsg{ + From: common.HexToAddress(""), + To: common.HexToAddress(""), + Amount: big.NewInt(7_000_000_000), + Token: utils.EthAddress, }) if err != nil { - log.Panic(err) -} - -// Wait for transaction to be finalized on L2 network -_, err = client.WaitFinalized(context.Background(), tx.Hash()) -if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("Gas: ", gas) ``` -### `BridgehubContractAddress` +### `EstimateL1ToL2Execute` -Returns the Bridgehub smart contract address. +Estimates the amount of gas required for an L1 to L2 execute operation. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +| --------- | ------------------------------------------- | ---------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/accounts/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | ```go -BridgehubContractAddress(ctx context.Context) (common.Address, error) +EstimateL1ToL2Execute(ctx context.Context, msg zkTypes.CallMsg) (uint64, error) ``` #### Example ```go -address, err := client.BridgehubContractAddress(context.Background()) +account := common.HexToAddress("
") +gas, err := client.EstimateL1ToL2Execute(context.Background(), zkTypes.CallMsg{ + CallMsg: ethereum.CallMsg{ + From: account, + To: &account, + Value: big.NewInt(7_000_000_000), + }, +}) if err != nil { - log.Panic() + log.Panic(err) } -fmt.Println("Bridgehub address: ", address) +fmt.Println("Gas: ", gas) ``` -### `MainContractAddress` +### `FilterLogsL2` -Returns the address of the ZKsync Era contract. +Executes a log filter operation, blocking during execution, and returns all the results in one batch. This method is +a replacement for `FilterLogs` because the returned `types.Log` type does not contain additional data specific to L2, +as found in [`Log`](/sdk/go/api/types#log). The `FilterLogs` method is kept in order to be compatible with `bind.ContractBackend`, +and this method can be used, but additional L2 data won't be retrieved. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +| --------- | ------------------------------------------------------------------------------------------------ | ------------------------ | +| `ctx` | `context.Context` | Context. | +| `query` | [`ethereum.FilterQuery`](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.12.0#FilterQuery) | Filter query parameters. | ```go -MainContractAddress(ctx context.Context) (common.Address, error) +FilterLogsL2(ctx context.Context, query ethereum.FilterQuery) ([]zkTypes.Log, error) ``` #### Example ```go -address, err := client.MainContractAddress(context.Background()) +contracts, err := client.BridgeContracts(context.Background()) if err != nil { - log.Panic() + log.Panic(err) +} +zkLogs, err := client.FilterLogsL2(context.Background(), ethereum.FilterQuery{ + FromBlock: big.NewInt(0), + ToBlock: big.NewInt(1000), + Addresses: []common.Address{contracts.L2Erc20DefaultBridge}, +}) +if err != nil { + log.Panic(err) +} + +for _, l := range zkLogs { + fmt.Println("Log address:", l.Address.Hex()) + fmt.Println("Log data:", l.Data) + fmt.Println("L1 batch number: ", l.L1BatchNumber) } -fmt.Println("Main contract address: ", address) ``` -### `TestnetPaymaster` - -Returns the testnet paymaster address if available, or `nil`. - -#### Inputs +### `Init` -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +`Dial` connects a client to the given URL. ```go -TestnetPaymaster(ctx context.Context) (common.Address, error) +func Dial(rawUrl string) (Client, error) ``` -#### Example +`DialContext` connects a client to the given URL with context. ```go -address, err := client.TestnetPaymaster(context.Background()) -if err != nil { - log.Panic() -} -fmt.Println("Testnet paymaster address: ", address) +func DialContext(ctx context.Context, rawUrl string) (Client, error) ``` -### `BridgeContracts` - -Returns the addresses of the default ZKsync Era bridge contracts on both L1 and L2. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +`NewClient` creates a client that uses the given RPC client. ```go -BridgeContracts(ctx context.Context) (*zkTypes.BridgeContracts, error) +func NewClient(c *rpc.Client) Client ``` #### Example ```go -contracts, err := client.BridgeContracts(context.Background()) +ZkSyncEraProvider := "https://testnet.era.zksync.dev" +ZkSyncEraWSProvider := "ws://testnet.era.zksync.dev:3051" + +// Connect to ZKsync network +client, err := clients.DialBase(ZkSyncEraProvider) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Bridge contracts: ", contracts) +defer client.Close() + +// Connect to ZKsync network using Web Socket +wsClient, err := clients.DialBase(ZkSyncEraWSProvider) +if err != nil { + log.Panic(err) +} +defer wsClient.Close() ``` -### `BaseTokenContractAddress` +### `IsBaseToken` -Returns the L1 base token address. +returns whether the token is the base token. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +|-----------|-------------------|----------------| +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | Token address. | ```go -BaseTokenContractAddress(ctx context.Context) (common.Address, error) +IsBaseToken(ctx context.Context, token common.Address) (bool, error) ``` #### Example ```go -address, err := client.BaseTokenContractAddress(context.Background()) +isBaseToken, err := client.IsBaseToken( + context.Background(), + common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") + ) if err != nil { log.Panic(err) } -fmt.Println("Base token address: ", address) +fmt.Println("Is base token: ", isBaseToken) ``` ### `IsEthBasedChain` @@ -579,86 +653,57 @@ if err != nil { fmt.Println("Is ETH-based chain: ", isEthBased) ``` -### `IsBaseToken` +### `L1BatchBlockRange` -returns whether the token is the base token. +Returns the range of blocks contained within a batch given by batch number. #### Inputs -| Parameter | Type | Description | -|-----------|-------------------|----------------| -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | Token address. | +| Parameter | Type | Description | +| --------------- | ----------------- | ---------------- | +| `ctx` | `context.Context` | Context. | +| `l1BatchNumber` | `*big.Int` | L1 batch number. | ```go -IsBaseToken(ctx context.Context, token common.Address) (bool, error) +L1BatchBlockRange(ctx context.Context, l1BatchNumber *big.Int) (*BlockRange, error) ``` #### Example ```go -isBaseToken, err := client.IsBaseToken( - context.Background(), - common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") - ) +batchBlockRange, err := client.L1BatchBlockRange(context.Background(), big.NewInt(83277)) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Is base token: ", isBaseToken) +fmt.Printf("Batch block range: %+v\n", *batchBlockRange) ``` -### `ContractAccountInfo` +### `L1BatchDetails` -Returns the version of the supported account abstraction and nonce ordering from a given contract address. +Returns data pertaining to a given batch. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `address` | `common.Address` | Contract address. | +| Parameter | Type | Description | +| --------------- | ----------------- | ---------------- | +| `ctx` | `context.Context` | Context. | +| `l1BatchNumber` | `*big.Int` | L1 batch number. | ```go -ContractAccountInfo(ctx context.Context, address common.Address) (*zkTypes.ContractAccountInfo, error) +L1BatchDetails(ctx context.Context, l1BatchNumber *big.Int) (*zkTypes.BatchDetails, error) ``` #### Example ```go -// Paymaster for Crown token on testnet -PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") -accountInfo, err := client.ContractAccountInfo(context.Background(), PaymasterAddress) +batchDetails, err := client.L1BatchDetails(context.Background(), big.NewInt(83277)) if err != nil { - log.Panic() + log.Panic(err) } -fmt.Printf("Account info: %+v\n", accountInfo) +fmt.Printf("Batch details: %+v\n", *batchDetails) ``` -### `L1ChainID` - -Returns the chain id of the underlying L1. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | - -```go -L1ChainID(ctx context.Context) (*big.Int, error) -``` - -#### Example - -```go -l1ChainID, err := client.L1ChainID(context.Background()) -if err != nil { - log.Panic() -} -fmt.Println("L1 chain ID: ", l1ChainID) -``` - -### `L1BatchNumber` +### `L1BatchNumber` Returns the latest L1 batch number. @@ -677,179 +722,125 @@ L1BatchNumber(ctx context.Context) (*big.Int, error) ```go l1BatchNumber, err := client.L1BatchNumber(context.Background()) if err != nil { - log.Panic() + log.Panic() } fmt.Println("L1 chain ID: ", l1BatchNumber) ``` -### `L1BatchBlockRange` - -Returns the range of blocks contained within a batch given by batch number. - -#### Inputs - -| Parameter | Type | Description | -| --------------- | ----------------- | ---------------- | -| `ctx` | `context.Context` | Context. | -| `l1BatchNumber` | `*big.Int` | L1 batch number. | - -```go -L1BatchBlockRange(ctx context.Context, l1BatchNumber *big.Int) (*BlockRange, error) -``` - -#### Example - -```go -batchBlockRange, err := client.L1BatchBlockRange(context.Background(), big.NewInt(83277)) -if err != nil { - log.Panic(err) -} -fmt.Printf("Batch block range: %+v\n", *batchBlockRange) -``` - -### `L1BatchDetails` +### `L1ChainID` -Returns data pertaining to a given batch. +Returns the chain id of the underlying L1. #### Inputs -| Parameter | Type | Description | -| --------------- | ----------------- | ---------------- | -| `ctx` | `context.Context` | Context. | -| `l1BatchNumber` | `*big.Int` | L1 batch number. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -L1BatchDetails(ctx context.Context, l1BatchNumber *big.Int) (*zkTypes.BatchDetails, error) +L1ChainID(ctx context.Context) (*big.Int, error) ``` #### Example ```go -batchDetails, err := client.L1BatchDetails(context.Background(), big.NewInt(83277)) +l1ChainID, err := client.L1ChainID(context.Background()) if err != nil { - log.Panic(err) + log.Panic() } -fmt.Printf("Batch details: %+v\n", *batchDetails) +fmt.Println("L1 chain ID: ", l1ChainID) ``` -### `BlockDetails` +### `L1TokenAddress` -Returns additional ZKsync Era-specific information about the L2 block. +Returns the L1 token address equivalent for a L2 token address as they are not equal. +ETH address is set to zero address. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ---------------- | -| `ctx` | `context.Context` | Context. | -| `block` | `uint32` | L2 block number. | +| Parameter | Type | Description | +|-----------| ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | L2 token address. | ```go -BlockDetails(ctx context.Context, block uint32) (*zkTypes.BlockDetails, error) +L1TokenAddress(ctx context.Context, token common.Address) (common.Address, error) ``` #### Example ```go -blockDetails, err := client.BlockDetails(context.Background(), 90000) +l2DAI := common.HexToAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b") +l1DAI, err := client.L1TokenAddress(context.Background(), l2DAI) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Printf("Block details: %+v\n", *blockDetails) +fmt.Println("L2 DAI address: ", l1DAI) ``` -### `TransactionDetails` +### `L2TokenAddress` -Returns data from a specific transaction given by the transaction hash. +Returns the L2 token address equivalent for a L1 token address as they are not equal. +ETH address is set to zero address. #### Inputs | Parameter | Type | Description | -| --------- | ----------------- | ----------------- | +|-----------| ----------------- | ----------------- | | `ctx` | `context.Context` | Context. | -| `txHash` | `common.Hash` | Transaction hash. | +| `token` | `common.Address` | L1 token address. | ```go -TransactionDetails(ctx context.Context, txHash common.Hash) (*zkTypes.TransactionDetails, error) +L2TokenAddress(ctx context.Context, token common.Address) (common.Address, error) ``` #### Example ```go -txHash := common.HexToHash("0x7765b9d5ace5798ab4c1cdd246bbf934cfbf17011dceba844adf207de5bc0a39") -txDetails, err := client.TransactionDetails(context.Background(), txHash) +l1DAI := common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") +l2DAI, err := client.L2TokenAddress(context.Background(), l1DAI) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Printf("Transaction details: %+v\n", *txDetails) +fmt.Println("L2 DAI address: ", l2DAI) ``` -### `BytecodeByHash` +### `L2TransactionFromPriorityOp` -returns bytecode of a contract given by its hash. +Returns transaction on L2 network from transaction receipt on L1 network. #### Inputs -| Parameter | Type | Description | -|----------------| ----------------- |----------------| -| `ctx` | `context.Context` | Context. | -| `bytecodeHash` | `common.Hash` | Bytecode hash. | +| Parameter | Type | Description | +| ------------- | ----------------- | ----------------------- | +| `ctx` | `context.Context` | Context. | +| `l1TxReceipt` | `*types.Receipt` | L1 transaction receipt. | ```go -BytecodeByHash(ctx context.Context, bytecodeHash common.Hash) ([]byte, error) +L2TransactionFromPriorityOp(ctx context.Context, l1TxReceipt *types.Receipt) (*zkTypes.TransactionResponse, error) ``` #### Example ```go -testnetPaymaster, err := client.TestnetPaymaster(context.Background()) -if err != nil { - log.Panic(err) -} -testnetPaymasterBytecode, err := client.CodeAt(context.Background(), testnetPaymaster, nil) -if err != nil { - log.Panic(err) -} - -testnetPaymasterBytecodeHash, err := utils.HashBytecode(testnetPaymasterBytecode) -if err != nil { - log.Panic(err) -} - -bytecode, err := client.BytecodeByHash(context.Background(), common.BytesToHash(testnetPaymasterBytecodeHash)) +// Connect to Ethereum network +ethClient, err := ethclient.Dial("https://rpc.ankr.com/eth_sepolia") if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Bytecode: ", bytecode) -``` - -### `RawBlockTransactions` - -Returns data of transactions in a block. - -#### Inputs - -| Parameter | Type | Description | -|-----------|-------------------|---------------| -| `ctx` | `context.Context` | Context. | -| `number` | `uin64` | Block number. | - -```go -RawBlockTransactions(ctx context.Context, number uint64) ([]zkTypes.RawBlockTransaction, error) -``` - -#### Example - -```go -blockNumber, err := client.BlockNumber(context.Background()) +defer ethClient.Close() + +txHash := common.HexToHash("0xcca5411f3e514052f4a4ae1c2020badec6e0998adb52c09959c5f5ff15fba3a8") +l1Receipt, err := ethClient.TransactionReceipt(context.Background(), txHash) if err != nil { - log.Panic(err) + log.Panic(err) } - -rawBlockTransactions, err := client.RawBlockTransactions(context.Background(), blockNumber) + +l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Raw block transactions: ", rawBlockTransactions) +fmt.Printf("L2 transaction: %+v\n", l2Tx) ``` ### `LogProof` @@ -874,47 +865,49 @@ LogProof(ctx context.Context, txHash common.Hash, logIndex int) (*zkTypes.Messag txHash := common.HexToHash("0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e") logProof, err := client.LogProof(context.Background(), txHash, 0) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Printf("Log proof: %+v\n", *logProof) ``` -### `L2TransactionFromPriorityOp` +### `MainContractAddress` -Returns transaction on L2 network from transaction receipt on L1 network. +Returns the address of the ZKsync Era contract. #### Inputs -| Parameter | Type | Description | -| ------------- | ----------------- | ----------------------- | -| `ctx` | `context.Context` | Context. | -| `l1TxReceipt` | `*types.Receipt` | L1 transaction receipt. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -L2TransactionFromPriorityOp(ctx context.Context, l1TxReceipt *types.Receipt) (*zkTypes.TransactionResponse, error) +MainContractAddress(ctx context.Context) (common.Address, error) ``` #### Example ```go -// Connect to Ethereum network -ethClient, err := ethclient.Dial("https://rpc.ankr.com/eth_sepolia") +address, err := client.MainContractAddress(context.Background()) if err != nil { - log.Panic(err) + log.Panic() } -defer ethClient.Close() +fmt.Println("Main contract address: ", address) +``` -txHash := common.HexToHash("0xcca5411f3e514052f4a4ae1c2020badec6e0998adb52c09959c5f5ff15fba3a8") -l1Receipt, err := ethClient.TransactionReceipt(context.Background(), txHash) -if err != nil { - log.Panic(err) -} +### `PendingCallContractL2` -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) -if err != nil { - log.Panic(err) -} -fmt.Printf("L2 transaction: %+v\n", l2Tx) +Almost the same as [`CallContractL2`](#callcontractl2) except that the state seen by the contract call is the +pending state. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ---------------------------------------- | ---------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | + +```go +PendingCallContractL2(ctx context.Context, msg zkTypes.CallMsg) ([]byte, error) ``` ### `PriorityOpConfirmation` @@ -944,337 +937,343 @@ PriorityOpConfirmation(ctx context.Context, txHash common.Hash, index int) (*zkT txHash := common.HexToHash("0x2a1c6c74b184965c0cb015aae9ea134fd96215d2e4f4979cfec12563295f610e") l1Receipt, err := client.PriorityOpConfirmation(context.Background(), txHash, 0) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Printf("Confirmation data: %+v\n", *l2Tx) ``` -### `ConfirmedTokens` +### `Proof` -Returns {address, symbol, name, and decimal} information of all tokens within a range of ids given by -parameters from and limit. +Returns Merkle proofs for one or more storage values at the specified account along with a +Merkle proof of their authenticity. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ---------------------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `from` | `uint32` | The token id from which to start returning the information about the tokens. | -| `limit` | `limit` | The number of tokens to be returned from the API. | +| Parameter | Type | Description | +| --------------- | ----------------- | ----------------------------------------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `address` | `common.Address` | The account to fetch storage values and proofs for. | +| `keys` | `common.Hahs` | Vector of storage keys in the account. | +| `l1BatchNumber` | `*big.Int` | Number of the L1 batch specifying the point in time at which the requested values are returned. | ```go -ConfirmedTokens(ctx context.Context, from uint32, limit uint8) ([]*zkTypes.Token, error) +Proof(ctx context.Context, address common.Address, keys []common.Hash, l1BatchNumber *big.Int) (*zkTypes.StorageProof, error) ``` #### Example ```go -// get first 255 tokens -tokens, err := client.ConfirmedTokens(context.Background(), 0, 255) +// Fetching the storage proof for rawNonces storage slot in NonceHolder system contract. +// mapping(uint256 => uint256) internal rawNonces; + +baseClient, ok := client.(*clients.BaseClient) +if !ok { + log.Panic("casting could not be performed") +} + +address := common.HexToAddress("
") + +// Ensure the address is a 256-bit number by padding it +// because rawNonces slot uses uint256 for mapping addresses and their nonces. +addressPadded := common.LeftPadBytes(address.Bytes(), 32) + +// Convert the slot number to a hex string and pad it to 32 bytes +slotBytes := common.Hex2Bytes("0x00") // slot with index 0 +slotPadded := common.LeftPadBytes(slotBytes, 32) + +// Concatenate the padded address and slot number +concatenated := append(addressPadded, slotPadded...) +storageKey := crypto.Keccak256(concatenated) + +l1BatchNumber, err := client.L1BatchNumber(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } - -for _, token := range tokens { - fmt.Printf("%+v\n", *token) + +storageProof, err := baseClient.Proof( + context.Background(), + utils.NonceHolderAddress, + []common.Hash{common.BytesToHash(storageKey)}, + l1BatchNumber) +if err != nil { + log.Panic(err) } ``` -### `L2TokenAddress` +### `RawBlockTransactions` -Returns the L2 token address equivalent for a L1 token address as they are not equal. -ETH address is set to zero address. +Returns data of transactions in a block. #### Inputs -| Parameter | Type | Description | -|-----------| ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | L1 token address. | +| Parameter | Type | Description | +|-----------|-------------------|---------------| +| `ctx` | `context.Context` | Context. | +| `number` | `uin64` | Block number. | ```go -L2TokenAddress(ctx context.Context, token common.Address) (common.Address, error) +RawBlockTransactions(ctx context.Context, number uint64) ([]zkTypes.RawBlockTransaction, error) ``` #### Example ```go -l1DAI := common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") -l2DAI, err := client.L2TokenAddress(context.Background(), l1DAI) +blockNumber, err := client.BlockNumber(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("L2 DAI address: ", l2DAI) -``` - -### `L1TokenAddress` - -Returns the L1 token address equivalent for a L2 token address as they are not equal. -ETH address is set to zero address. - -#### Inputs - -| Parameter | Type | Description | -|-----------| ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | L2 token address. | - -```go -L1TokenAddress(ctx context.Context, token common.Address) (common.Address, error) -``` - -#### Example - -```go -l2DAI := common.HexToAddress("0x3e7676937A7E96CFB7616f255b9AD9FF47363D4b") -l1DAI, err := client.L1TokenAddress(context.Background(), l2DAI) + +rawBlockTransactions, err := client.RawBlockTransactions(context.Background(), blockNumber) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("L2 DAI address: ", l1DAI) +fmt.Println("Raw block transactions: ", rawBlockTransactions) ``` -### `AllAccountBalances` +### `SendRawTransaction` -Returns all balances for confirmed tokens given by an account address. +Injects a signed raw transaction into the pending pool for execution. +Is meant to be used for sending EIP-712 transaction. #### Inputs | Parameter | Type | Description | | --------- | ----------------- | ---------------- | | `ctx` | `context.Context` | Context. | -| `address` | `common.Address` | Account address. | +| `tx` | `[]byte` | Raw transaction. | ```go -AllAccountBalances(ctx context.Context, address common.Address) (map[common.Address]*big.Int, error) +SendRawTransaction(ctx context.Context, tx []byte) (common.Hash, error) ``` #### Example ```go -// Paymaster on testnet -paymaster := common.HexToAddress("0x8f0ea1312da29f17eabeb2f484fd3c112cccdd63") -balances, err := client.AllAccountBalances(context.Background(), paymaster) +// The Crown token on testnet +TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") +// Paymaster for Crown token on testnet +PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") +ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") + +w, err := accounts.NewWallet(common.Hex2Bytes(), &client, nil) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Printf("Balances: %+v\n", balances) -``` - -### `EstimateFee` - -Returns the fee for the transaction. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ---------------------------------------- | ---------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | - -```go -EstimateFee(ctx context.Context, tx zkTypes.CallMsg) (*zkTypes.Fee, error) -``` - -#### Example - -```go -from := common.HexToAddress("") -to := common.HexToAddress("") -fee, err := client.EstimateFee(context.Background(), zkTypes.CallMsg{ - CallMsg: ethereum.CallMsg{ - From: from, - To: &to, - Value: big.NewInt(7_000_000_000), - }, + +abi, err := erc20.IERC20MetaData.GetAbi() +if err != nil { + log.Panic(err) +} + +// Encode mint function from token contract +calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7)) +if err != nil { + log.Panic(err) +} + +// Create paymaster parameters with encoded paymaster input +paymasterParams, err := utils.GetPaymasterParams( + PaymasterAddress, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: TokenAddress, + MinimalAllowance: big.NewInt(1), + InnerInput: []byte{}, + }) +if err != nil { + log.Panic(err) +} + +hash, err := w.SendTransaction(context.Background(), &accounts.Transaction{ + To: &TokenAddress, + Data: calldata, + Meta: &zkTypes.Eip712Meta{ + PaymasterParams: paymasterParams, + }, }) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Printf("Fee: %+v\n", *fee) +fmt.Println("Tx: ", hash) ``` -### `EstimateGasL1` +### `SubscribeFilterLogsL2` -Estimates the amount of gas required to submit a transaction from L1 to L2. +Creates a background log filtering operation, returning a subscription immediately, which can be used to stream the +found events. This method is a replacement for `SubscribeFilterLogs` because the returned `types.Log` type does not +contain additional data specific to L2, as found +in [`Log`](/sdk/go/api/types#log). The `SubscribeFilterLogs` method is +kept in order to be compatible with `bind.ContractBackend`, and this method can be used, but additional L2 data +won't be retrieved. #### Inputs -| Parameter | Type | Description | -| --------- | ---------------------------------------- | ---------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | +| Parameter | Type | Description | +| --------- | --------------------------------------------------------------------------------------------- | -------------------------- | +| `ctx` | `context.Context` | Context. | +| `query` | [`ethereum.FilterQuery`](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.12.0#FilterQuery) | Filter query parameters. | +| `ch` | [`chan<- zkTypes.Log`](/sdk/go/api/types#log) | Channel that receives Log. | ```go -EstimateGasL1(ctx context.Context, tx zkTypes.CallMsg) (uint64, error) +SubscribeFilterLogsL2(ctx context.Context, query ethereum.FilterQuery, ch chan<- zkTypes.Log) (ethereum.Subscription, error) ``` #### Example ```go -account := common.HexToAddress("
") -gas, err := client.EstimateGasL1(context.Background(), zkTypes.CallMsg{ - CallMsg: ethereum.CallMsg{ - From: account, - To: &account, - Value: big.NewInt(7_000_000_000), - }, - Meta: &zkTypes.Eip712Meta{ - GasPerPubdata: utils.NewBig(utils.RequiredL1ToL2GasPerPubdataLimit.Int64()), - }, -}) +contracts, err := client.BridgeContracts(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) +} + +filterLogs := make(chan zkTypes.Log) +sub, err := wsClient.SubscribeFilterLogsL2(context.Background(), ethereum.FilterQuery{ + FromBlock: big.NewInt(0), + ToBlock: big.NewInt(1000), + Addresses: []common.Address{contracts.L2Erc20DefaultBridge}, +}, filterLogs) +if err != nil { + log.Panic(err) +} +defer sub.Unsubscribe() + +for { + select { + case err := <-sub.Err(): + log.Println(err) + break + case l := <-filterLogs: + fmt.Println("Address: ", l.Address) + fmt.Println("Data", l.Data) + } } -fmt.Println("Gas: ", gas) ``` -### `EstimateGasTransfer` +### `TestnetPaymaster` -Estimates the amount of gas required for a transfer transaction. +Returns the testnet paymaster address if available, or `nil`. #### Inputs -| Parameter | Type | Description | -| --------- | -------------------------------------------------- | -------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`TransferCallMsg`](/sdk/go/api/accounts/types#transfercallmsg) | Contains parameters for transfer call. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -EstimateGasTransfer(ctx context.Context, msg TransferCallMsg) (uint64, error) +TestnetPaymaster(ctx context.Context) (common.Address, error) ``` #### Example ```go -gas, err := client.EstimateGasTransfer(context.Background(), clients.TransferCallMsg{ - From: common.HexToAddress(""), - To: common.HexToAddress(""), - Amount: big.NewInt(7_000_000_000), - Token: utils.EthAddress, -}) +address, err := client.TestnetPaymaster(context.Background()) if err != nil { - log.Panic(err) + log.Panic() } -fmt.Println("Gas: ", gas) +fmt.Println("Testnet paymaster address: ", address) ``` -### `EstimateGasWithdraw` +### `TransactionDetails` -Estimates the amount of gas required for a withdrawal transaction. +Returns data from a specific transaction given by the transaction hash. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------------------------------------ | ---------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`WithdrawalCallMsg`](/sdk/go/api/accounts/types#withdrawalcallmsg) | Contains parameters for withdrawal call. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `txHash` | `common.Hash` | Transaction hash. | ```go -EstimateGasWithdraw(ctx context.Context, msg WithdrawalCallMsg) (uint64, error) +TransactionDetails(ctx context.Context, txHash common.Hash) (*zkTypes.TransactionDetails, error) ``` #### Example ```go -gas, err := client.EstimateGasWithdraw(context.Background(), clients.WithdrawalCallMsg{ - From: common.HexToAddress(""), - To: common.HexToAddress(""), - Amount: big.NewInt(7_000_000_000), - Token: utils.EthAddress, -}) +txHash := common.HexToHash("0x7765b9d5ace5798ab4c1cdd246bbf934cfbf17011dceba844adf207de5bc0a39") +txDetails, err := client.TransactionDetails(context.Background(), txHash) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Gas: ", gas) +fmt.Printf("Transaction details: %+v\n", *txDetails) ``` -### `EstimateL1ToL2Execute` +### `WaitFinalized` -Estimates the amount of gas required for an L1 to L2 execute operation. +Waits for tx to be finalized on the L2. It stops waiting when the context is canceled. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------------------------- | ---------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`zkTypes.CallMsg`](/sdk/go/api/accounts/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `txHash` | `common.Hash` | Transaction hash. | ```go -EstimateL1ToL2Execute(ctx context.Context, msg zkTypes.CallMsg) (uint64, error) +WaitFinalized(ctx context.Context, txHash common.Hash) (*zkTypes.Receipt, error) ``` #### Example ```go -account := common.HexToAddress("
") -gas, err := client.EstimateL1ToL2Execute(context.Background(), zkTypes.CallMsg{ - CallMsg: ethereum.CallMsg{ - From: account, - To: &account, - Value: big.NewInt(7_000_000_000), - }, +// Create wallet +w, err := accounts.NewWallet(common.Hex2Bytes(), &client, nil) +if err != nil { + log.Panic(err) +} + +tx, err := w.Transfer(accounts.TransferTransaction{ + To: common.HexToAddress(
), + Amount: big.NewInt(7_000_000_000), + Token: utils.EthAddress, }) if err != nil { - log.Panic(err) + log.Panic(err) +} + +// Wait for transaction to be finalized on L2 network +_, err = client.WaitFinalized(context.Background(), tx.Hash()) +if err != nil { + log.Panic(err) } -fmt.Println("Gas: ", gas) ``` -### `Proof` +### `WaitMined` -Returns Merkle proofs for one or more storage values at the specified account along with a -Merkle proof of their authenticity. +Waits for transaction to be mined on the L2. It stops waiting when the context is canceled. #### Inputs -| Parameter | Type | Description | -| --------------- | ----------------- | ----------------------------------------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `address` | `common.Address` | The account to fetch storage values and proofs for. | -| `keys` | `common.Hahs` | Vector of storage keys in the account. | -| `l1BatchNumber` | `*big.Int` | Number of the L1 batch specifying the point in time at which the requested values are returned. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `txHash` | `common.Hash` | Transaction hash. | ```go -Proof(ctx context.Context, address common.Address, keys []common.Hash, l1BatchNumber *big.Int) (*zkTypes.StorageProof, error) +WaitMined(ctx context.Context, txHash common.Hash) (*zkTypes.Receipt, error) ``` #### Example ```go -// Fetching the storage proof for rawNonces storage slot in NonceHolder system contract. -// mapping(uint256 => uint256) internal rawNonces; - -baseClient, ok := client.(*clients.BaseClient) -if !ok { - log.Panic("casting could not be performed") +// Create wallet +w, err := accounts.NewWallet(common.Hex2Bytes(), &client, nil) +if err != nil { + log.Panic(err) } - -address := common.HexToAddress("
") - -// Ensure the address is a 256-bit number by padding it -// because rawNonces slot uses uint256 for mapping addresses and their nonces. -addressPadded := common.LeftPadBytes(address.Bytes(), 32) - -// Convert the slot number to a hex string and pad it to 32 bytes -slotBytes := common.Hex2Bytes("0x00") // slot with index 0 -slotPadded := common.LeftPadBytes(slotBytes, 32) - -// Concatenate the padded address and slot number -concatenated := append(addressPadded, slotPadded...) -storageKey := crypto.Keccak256(concatenated) - -l1BatchNumber, err := client.L1BatchNumber(context.Background()) + +tx, err := w.Transfer(accounts.TransferTransaction{ + To: common.HexToAddress(
), + Amount: big.NewInt(7_000_000_000), + Token: utils.EthAddress, +}) if err != nil { - log.Panic(err) + log.Panic(err) } - -storageProof, err := baseClient.Proof( - context.Background(), - utils.NonceHolderAddress, - []common.Hash{common.BytesToHash(storageKey)}, - l1BatchNumber) + +// Wait for transaction to be mined on L2 network +_, err = client.WaitMined(context.Background(), tx.Hash()) if err != nil { - log.Panic(err) + log.Panic(err) } ``` diff --git a/content/sdk/20.go/02.api/00.clients/02.types.md b/content/sdk/20.go/02.api/00.clients/02.types.md index 0378ba11..a592dd66 100644 --- a/content/sdk/20.go/02.api/00.clients/02.types.md +++ b/content/sdk/20.go/02.api/00.clients/02.types.md @@ -19,18 +19,17 @@ type BlockRange struct { } ``` -### `WithdrawalCallMsg` +### `TransferCallMsg` -Contains parameters for withdrawal call. It can be transformed into an `ethereum.CallMsg` by -encoding the withdrawal parameters with`ToCallMsg` method. +Contains parameters for transfer call. It can be transformed into `ethereum.CallMsg` by encoding +the transfer parameters with `ToCallMsg` method. ```go -type WithdrawalCallMsg struct { - To common.Address // The address of the recipient on L1. - Amount *big.Int // The amount of the token to transfer. - Token common.Address // The address of the token. ETH by default. - BridgeAddress *common.Address // The address of the bridge contract to be used. - From common.Address // The address of the sender. +type TransferCallMsg struct { + To common.Address // The address of the recipient. + Amount *big.Int // The amount of the token to transfer. + Token common.Address // The address of the token. ETH by default. + From common.Address // The address of the sender. Gas uint64 // If 0, the call executes with near-infinite gas. GasPrice *big.Int // Wei <-> gas exchange ratio. @@ -40,20 +39,21 @@ type WithdrawalCallMsg struct { AccessList types.AccessList // EIP-2930 access list. } -func (m *WithdrawalCallMsg) ToCallMsg(defaultL2Bridge *common.Address) (*ethereum.CallMsg, error) +func (m *TransferCallMsg) ToCallMsg() (*ethereum.CallMsg, error) ``` -### `TransferCallMsg` +### `WithdrawalCallMsg` -Contains parameters for transfer call. It can be transformed into `ethereum.CallMsg` by encoding -the transfer parameters with `ToCallMsg` method. +Contains parameters for withdrawal call. It can be transformed into an `ethereum.CallMsg` by +encoding the withdrawal parameters with`ToCallMsg` method. ```go -type TransferCallMsg struct { - To common.Address // The address of the recipient. - Amount *big.Int // The amount of the token to transfer. - Token common.Address // The address of the token. ETH by default. - From common.Address // The address of the sender. +type WithdrawalCallMsg struct { + To common.Address // The address of the recipient on L1. + Amount *big.Int // The amount of the token to transfer. + Token common.Address // The address of the token. ETH by default. + BridgeAddress *common.Address // The address of the bridge contract to be used. + From common.Address // The address of the sender. Gas uint64 // If 0, the call executes with near-infinite gas. GasPrice *big.Int // Wei <-> gas exchange ratio. @@ -63,5 +63,5 @@ type TransferCallMsg struct { AccessList types.AccessList // EIP-2930 access list. } -func (m *TransferCallMsg) ToCallMsg() (*ethereum.CallMsg, error) +func (m *WithdrawalCallMsg) ToCallMsg(defaultL2Bridge *common.Address) (*ethereum.CallMsg, error) ``` diff --git a/content/sdk/20.go/02.api/01.accounts/02.basedeployer.md b/content/sdk/20.go/02.api/01.accounts/02.basedeployer.md index aba81f20..362b2eff 100644 --- a/content/sdk/20.go/02.api/01.accounts/02.basedeployer.md +++ b/content/sdk/20.go/02.api/01.accounts/02.basedeployer.md @@ -47,37 +47,6 @@ if err != nil { fmt.Println("Transaction: ", hash) ``` -### `DeployWithCreate` - -Deploys smart contract using CREATE method. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ------------------------------------------------------- | ------------------------------ | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `tx` | [`CreateTransaction`](/sdk/go/api/accounts/types#createtransaction) | CREATE transaction parameters. | - -```go -DeployWithCreate(auth *TransactOpts, tx CreateTransaction) (common.Hash, error) -``` - -#### Example - -```go -bytecode, err := os.ReadFile("Storage.zbin") -if err != nil { - log.Panic(err) -} - -//Deploy smart contract -hash, err := wallet.DeployWithCreate(nil, accounts.CreateTransaction{Bytecode: bytecode}) -if err != nil { - panic(err) -} -fmt.Println("Transaction: ", hash) -``` - ### `DeployAccount` Deploys smart account using CREATE2 method. @@ -163,3 +132,34 @@ if err != nil { } fmt.Println("Transaction: ", hash) ``` + +### `DeployWithCreate` + +Deploys smart contract using CREATE method. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ------------------------------------------------------- | ------------------------------ | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `tx` | [`CreateTransaction`](/sdk/go/api/accounts/types#createtransaction) | CREATE transaction parameters. | + +```go +DeployWithCreate(auth *TransactOpts, tx CreateTransaction) (common.Hash, error) +``` + +#### Example + +```go +bytecode, err := os.ReadFile("Storage.zbin") +if err != nil { + log.Panic(err) +} + +//Deploy smart contract +hash, err := wallet.DeployWithCreate(nil, accounts.CreateTransaction{Bytecode: bytecode}) +if err != nil { + panic(err) +} +fmt.Println("Transaction: ", hash) +``` diff --git a/content/sdk/20.go/02.api/01.accounts/04.walletl1.md b/content/sdk/20.go/02.api/01.accounts/04.walletl1.md index d2479163..4a3f89ff 100644 --- a/content/sdk/20.go/02.api/01.accounts/04.walletl1.md +++ b/content/sdk/20.go/02.api/01.accounts/04.walletl1.md @@ -7,113 +7,127 @@ tags: ["zksync", "walletL1", "account management", "go", "sdk"] The `WalletL1` class provides functionalities for managing and interacting with accounts on the Layer 1 (L1) network. It includes methods for creating wallets, querying contracts, checking balances, and performing transactions on the Ethereum network. +### `AllowanceL1` -### `Init` - -Creates an instance of WalletL1 associated with the account provided by the raw private key. +Returns the amount of approved tokens for a specific L1 bridge. -```go -func NewWalletL1(rawPrivateKey []byte, clientL1 *ethclient.Client, clientL2 *clients.Client) (*WalletL1, error -``` +#### Inputs -Creates an instance of WalletL1 associated with the account provided by the signer. +| Parameter | Type | Description | +| --------------- | ------------------------------------------------ | --------------- | +| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | +| `token` | `common.Address` | Token address. | +| `bridgeAddress` | `common.Address` | Bridge address. | ```go -NewWalletL1FromSigner(signer *Signer, clientL1 *ethclient.Client, clientL2 *clients.Client) (*WalletL1, error) +AllowanceL1(opts *CallOpts, token common.Address, bridgeAddress common.Address) (*big.Int, error) ``` #### Example ```go -PrivateKey := os.Getenv("PRIVATE_KEY") -ZkSyncEraProvider := "https://sepolia.era.zksync.dev" -EthereumProvider := "https://rpc.ankr.com/eth_sepolia" - -client, err := clients.Dial(ZkSyncEraProvider) -if err != nil { - log.Panic(err) -} -defer client.Close() - -ethClient, err := ethclient.Dial(EthereumProvider) +// The Crown token on testnet +TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") + +contracts, err := client.BridgeContracts(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -defer ethClient.Close() - -wallet, err := accounts.NewWalletL1(common.Hex2Bytes(PrivateKey), &client, ethClient) +bridgeAllowance, err := wallet.AllowanceL1(nil, TokenAddress, contracts.L1Erc20DefaultBridge) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("Bridge allowance: ", bridgeAllowance) ``` -### `MainContract` +### `ApproveERC20` -Returns the ZKsync L1 smart contract. +Approves the specified amount of tokens for the specified L1 bridge. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | L1 token address. | +| `amount` | `*big.Int` | Approval amount. | ```go -MainContract(ctx context.Context) (*zksync.IZkSync, error) +ApproveERC20(auth *TransactOpts, token common.Address, amount *big.Int, bridgeAddress common.Address) (*types.Transaction, error) ``` #### Example ```go -mainContract, err := wallet.MainContract(context.Background()) +// The Crown token on testnet +TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") + +contracts, err := client.BridgeContracts(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } +tx, err := wallet.ApproveERC20(nil, TokenAddress, contracts.L1Erc20DefaultBridge) +if err != nil { + log.Panic(err) +} +fmt.Println("Tx: ", tx.Hash()) ``` -### `BridgehubContract` +### `BalanceL1` -Returns the Bridgehub L1 smart contract. +Returns the balance of the specified token on L1 that can be either ETH or any ERC20 token. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +| --------- | ------------------------------------------------ | -------------- | +| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | +| `token` | `common.Address` | Token address. | ```go -BridgehubContract(_ context.Context) (*bridgehub.IBridgehub, error) +BalanceL1(opts *CallOpts, token common.Address) (*big.Int, error) ``` #### Example ```go -bridgehub, err := wallet.BridgehubContract(context.Background()) +balance, err := wallet.BalanceL1(nil, utils.EthAddress) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("Balance: ", balance) ``` -### `L1BridgeContracts` +### `BaseCost` -Returns L1 bridge contracts. +Returns base cost for L2 transaction. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +| ------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------- | +| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | +| `gasLimit` | `*big.Int` | The gasLimit for the the L2 contract call. | +| `gasPerPubdataByte` | `*big.Int` | The L2 gas price for each published L1 calldata byte. | +| `gasPrice` | `*big.Int` (optional) | The L1 gas price of the L1 transaction that will send the request for an execute call. | ```go -L1BridgeContracts(ctx context.Context) (*zkTypes.L1BridgeContracts, error) +BaseCost(opts *CallOpts, gasLimit, gasPerPubdataByte, gasPrice *big.Int) (*big.Int, error) ``` #### Example ```go -contracts, err := wallet.L1BridgeContracts(context.Background()) +gasPrice, err := client.SuggestGasPrice(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } + +baseCost, err := wallet.BaseCost(nil, big.NewInt(9000), utils.RequiredL1ToL2GasPerPubdataLimit, gasPrice) +if err != nil { + log.Panic(err) +} +fmt.Println("Base cost: ", baseCost) ``` ### `BaseToken` @@ -135,14 +149,14 @@ BaseToken(opts *CallOpts) (common.Address, error) ```go baseToken, err := wallet.BaseToken(nil) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Base token: ", baseToken) ``` -### `IsEthBasedChain` +### `BridgehubContract` -Returns whether the chain is ETH-based. +Returns the Bridgehub L1 smart contract. #### Inputs @@ -151,166 +165,221 @@ Returns whether the chain is ETH-based. | `ctx` | `context.Context` | Context. | ```go -IsEthBasedChain(ctx context.Context) (bool, error) +BridgehubContract(_ context.Context) (*bridgehub.IBridgehub, error) ``` #### Example ```go -isEthBased, err := wallet.IsEthBasedChain(context.Background()) +bridgehub, err := wallet.BridgehubContract(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Is ETH-based chain: ", isEthBased) ``` -### `BalanceL1` +### `ClaimFailedDeposit` -Returns the balance of the specified token on L1 that can be either ETH or any ERC20 token. +Withdraws funds from the initiated deposit, which failed when finalizing on L2. If the deposit L2 transaction has +failed, it sends an L1 transaction calling ClaimFailedDeposit method of the L1 bridge, which results in returning +L1 tokens back to the depositor, otherwise throws the error. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------------------------------ | -------------- | -| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | -| `token` | `common.Address` | Token address. | +| Parameter | Type | Description | +| ------------- | --------------------------------------------------------- | ---------------------------------------------- | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `depositHash` | `common.Hash` | The L2 transaction hash of the failed deposit. | ```go -BalanceL1(opts *CallOpts, token common.Address) (*big.Int, error) +ClaimFailedDeposit(auth *TransactOpts, depositHash common.Hash) (*types.Transaction, error) ``` #### Example ```go -balance, err := wallet.BalanceL1(nil, utils.EthAddress) +failedDepositL2Hash := common.HexToHash("") +cfdTx, err := wallet.ClaimFailedDeposit(nil, failedDepositL2Hash) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Balance: ", balance) +fmt.Println("ClaimFailedDeposit hash: ", cfdTx.Hash) ``` -### `AllowanceL1` +### `Deposit` -Returns the amount of approved tokens for a specific L1 bridge. +Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. +The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the +specified L1 bridge (default one or the one defined in `BridgeAddress`). In this case, depending on is the chain +ETH-based or not `ApproveERC20` or `ApproveBaseERC20` can be enabled to perform token approval. +to perform token approval. If there are already enough approved tokens for the L1 bridge, token approval will be +skipped. To check the amount of approved tokens for a specific bridge, use the [`AllowanceL1`](#allowancel1) method. #### Inputs -| Parameter | Type | Description | -| --------------- | ------------------------------------------------ | --------------- | -| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | -| `token` | `common.Address` | Token address. | -| `bridgeAddress` | `common.Address` | Bridge address. | +| Parameter | Type | Description | +| --------- | --------------------------------------------------------- |--------------------------------| +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `tx` | [`DepositTransaction`](/sdk/go/api/accounts/types#deposittransaction) | Deposit transaction parameters.| ```go -AllowanceL1(opts *CallOpts, token common.Address, bridgeAddress common.Address) (*big.Int, error) +Deposit(auth *TransactOpts, tx DepositTransaction) (*types.Transaction, error) ``` #### Example -```go -// The Crown token on testnet -TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") +Deposit ETH on ETH-based chain. -contracts, err := client.BridgeContracts(context.Background()) +```go +tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ + To: wallet.Address(), + Token: utils.LegacyEthAddress, + Amount: amount, + RefundRecipient: wallet.Address(), +}) if err != nil { - log.Panic(err) + log.Panic(err) } -bridgeAllowance, err := wallet.AllowanceL1(nil, TokenAddress, contracts.L1Erc20DefaultBridge) + +l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Bridge allowance: ", bridgeAllowance) -``` - -### `L2TokenAddress` - -Returns the corresponding address on the L2 network for the token on the L1 network. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | L1 token address. | - -```go -L2TokenAddress(ctx context.Context, token common.Address) (common.Address, error) -``` - -#### Example - -```go -l1DAI := common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") -l2DAI, err := wallet.L2TokenAddress(context.Background(), l1DAI) + +l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) if err != nil { - log.Panic(err) + log.Panic(err) +} + +l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +if err != nil { + log.Panic(err) } -fmt.Println("L2 DAI address: ", l2DAI) ``` -### `ApproveERC20` - -Approves the specified amount of tokens for the specified L1 bridge. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | L1 token address. | -| `amount` | `*big.Int` | Approval amount. | +Deposit token on ETH-based chain. ```go -ApproveERC20(auth *TransactOpts, token common.Address, amount *big.Int, bridgeAddress common.Address) (*types.Transaction, error) +tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ + To: wallet.Address(), + Token: L1Dai, + Amount: amount, + ApproveERC20: true, + RefundRecipient: wallet.Address(), +}) +if err != nil { + log.Panic(err) +} + +l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) +if err != nil { + log.Panic(err) +} + +l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) +if err != nil { + log.Panic(err) +} + +l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +if err != nil { + log.Panic(err) +} ``` -#### Example +Deposit ETH on non-ETH-based chain. ```go -// The Crown token on testnet -TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") - -contracts, err := client.BridgeContracts(context.Background()) +tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ + To: wallet.Address(), + Token: utils.LegacyEthAddress, + Amount: amount, + ApproveBaseERC20: true, + RefundRecipient: wallet.Address(), +}) if err != nil { - log.Panic(err) + log.Panic(err) } -tx, err := wallet.ApproveERC20(nil, TokenAddress, contracts.L1Erc20DefaultBridge) + +l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) +if err != nil { + log.Panic(err) +} + +l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) if err != nil { - log.Panic(err) + log.Panic(err) +} + +l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +if err != nil { + log.Panic(err) } -fmt.Println("Tx: ", tx.Hash()) ``` -### `BaseCost` - -Returns base cost for L2 transaction. - -#### Inputs - -| Parameter | Type | Description | -| ------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------- | -| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | -| `gasLimit` | `*big.Int` | The gasLimit for the the L2 contract call. | -| `gasPerPubdataByte` | `*big.Int` | The L2 gas price for each published L1 calldata byte. | -| `gasPrice` | `*big.Int` (optional) | The L1 gas price of the L1 transaction that will send the request for an execute call. | +Deposit base token on non-ETH-based chain. ```go -BaseCost(opts *CallOpts, gasLimit, gasPerPubdataByte, gasPrice *big.Int) (*big.Int, error) +baseToken, err := wallet.BaseToken(nil) +if err != nil { + log.Panic(err) +} + +tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ + To: wallet.Address(), + Token: baseToken, + Amount: amount, + ApproveBaseERC20: true, + RefundRecipient: wallet.Address(), +}) +if err != nil { + log.Panic(err) +} + +l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) +if err != nil { + log.Panic(err) +} + +l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) +if err != nil { + log.Panic(err) +} + +l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +if err != nil { + log.Panic(err) +} ``` -#### Example +Deposit non-base token on non-ETH-based chain. ```go -gasPrice, err := client.SuggestGasPrice(context.Background()) +tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ + To: wallet.Address(), + Token: L1Dai, + Amount: amount, + ApproveERC20: true, + ApproveBaseERC20: true, + RefundRecipient: wallet.Address(), +}) if err != nil { - log.Panic(err) + log.Panic(err) } - -baseCost, err := wallet.BaseCost(nil, big.NewInt(9000), utils.RequiredL1ToL2GasPerPubdataLimit, gasPrice) + +l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) if err != nil { - log.Panic(err) + log.Panic(err) +} + +l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) +if err != nil { + log.Panic(err) +} + +l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +if err != nil { + log.Panic(err) } -fmt.Println("Base cost: ", baseCost) ``` ### `DepositAllowanceParams` @@ -339,11 +408,11 @@ Get allowance parameters for depositing token on ETH-based chain. ```go msg := accounts.DepositCallMsg{ - Token: common.HexToAddress(""), - To: Receiver, - Amount: big.NewInt(5), + Token: common.HexToAddress(""), + To: Receiver, + Amount: big.NewInt(5), } - + allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) if err != nil { log.Panic(err) @@ -366,11 +435,11 @@ Get allowance parameters for depositing ETH on non-ETH-based chain. ```go msg := accounts.DepositCallMsg{ - Token: utils.LegacyEthAddress, - To: Receiver, - Amount: big.NewInt(7_000_000_000), + Token: utils.LegacyEthAddress, + To: Receiver, + Amount: big.NewInt(7_000_000_000), } - + allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) if err != nil { log.Panic(err) @@ -396,13 +465,13 @@ token, err := wallet.BaseToken(nil) if err != nil { log.Panic(err) } - + msg := accounts.DepositCallMsg{ Token: token, To: Receiver, Amount: big.NewInt(7_000_000_000), } - + allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) if err != nil { log.Panic(err) @@ -425,11 +494,11 @@ Get allowance parameters for depositing non-base token on non-ETH-based chain. ```go msg := accounts.DepositCallMsg{ - Token: common.HexToAddress(""), - To: Receiver, - Amount: big.NewInt(5), + Token: common.HexToAddress(""), + To: Receiver, + Amount: big.NewInt(5), } - + allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) if err != nil { log.Panic(err) @@ -458,230 +527,210 @@ if err != nil { ```go ZkSyncEraProvider := "https://testnet.era.zksync.dev" - + client, err := clients.Dial(ZkSyncEraProvider) if err != nil { - log.Panic(err) + log.Panic(err) } defer client.Close() - + gasPrice, err := client.SuggestGasPrice(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } - + baseCost, err := wallet.BaseCost(nil, big.NewInt(9000), utils.RequiredL1ToL2GasPerPubdataLimit, gasPrice) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Base cost: ", baseCost) ``` -### `Deposit` +### `EstimateCustomBridgeDepositL2Gas` -Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. -The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the -specified L1 bridge (default one or the one defined in `BridgeAddress`). In this case, depending on is the chain -ETH-based or not `ApproveERC20` or `ApproveBaseERC20` can be enabled to perform token approval. -to perform token approval. If there are already enough approved tokens for the L1 bridge, token approval will be -skipped. To check the amount of approved tokens for a specific bridge, use the [`AllowanceL1`](#allowancel1) method. +Used by [`EstimateDefaultBridgeDepositL2Gas`](#estimatedefaultbridgedepositl2gas) to estimate L2 gas +required for token bridging via a custom ERC20 bridge. + +::callout{icon="i-heroicons-information-circle" color="blue"} +See the [default bridges documentation](https://docs.zksync.io/build/developer-reference/bridging-assets#default-bridges) +:: #### Inputs -| Parameter | Type | Description | -| --------- | --------------------------------------------------------- |--------------------------------| -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `tx` | [`DepositTransaction`](/sdk/go/api/accounts/types#deposittransaction) | Deposit transaction parameters.| +| Parameter | Type | Description | +| ------------------- | --------------------------- | -------------------------------- | +| `ctx` | `context.Context` | Context. | +| `l1BridgeAddress` | `common.Address` | L1 bridge address. | +| `l2BridgeAddress` | `common.Address` | L2 bridge address. | +| `token` | `common.Address` | Token address. | +| `amount` | `*big.Int` | Deposit amount. | +| `to` | `common.Address` | Recipient address. | +| `bridgeData` | `[]byte` | Bridge data. | +| `from` | `common.Address` (optional) | Sender address. | +| `gasPerPubdataByte` | `*big.Int` (optional) | Current gas per byte of pubdata. | ```go -Deposit(auth *TransactOpts, tx DepositTransaction) (*types.Transaction, error) +EstimateCustomBridgeDepositL2Gas(ctx context.Context, l1BridgeAddress, l2BridgeAddress, token common.Address, + amount *big.Int, to common.Address, bridgeData []byte, from common.Address, gasPerPubdataByte *big.Int) (uint64, error) ``` #### Example -Deposit ETH on ETH-based chain. - ```go -tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ - To: wallet.Address(), - Token: utils.LegacyEthAddress, - Amount: amount, - RefundRecipient: wallet.Address(), -}) +L1BridgeAddress := common.HexToAddress("") +Token := common.HexToAddress("") +From := common.HexToAddress("") +To := common.HexToAddress("") + +bridge, err := l1bridge.NewIL1Bridge(L1BridgeAddress, ethClient) if err != nil { - log.Panic(err) + log.Panic(err) } - -l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) +l2BridgeAddress, err := bridge.L2Bridge(nil) if err != nil { - log.Panic(err) + log.Panic(err) } - -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) +customBridgeData, err := utils.Erc20DefaultBridgeData(Token, ethClient) if err != nil { - log.Panic(err) + log.Panic(err) } - -l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) + +gas, err := wallet1.EstimateCustomBridgeDepositL2Gas(context.Background(), L1BridgeAddress, l2BridgeAddress, Token, + big.NewInt(7), To, customBridgeData, From, utils.RequiredL1ToL2GasPerPubdataLimit) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("L2 gas: ", gas) ``` -Deposit token on ETH-based chain. - -```go -tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ - To: wallet.Address(), - Token: L1Dai, - Amount: amount, - ApproveERC20: true, - RefundRecipient: wallet.Address(), -}) -if err != nil { - log.Panic(err) -} +### `EstimateDefaultBridgeDepositL2Gas` -l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) -if err != nil { - log.Panic(err) -} +Returns an estimation of L2 gas required for token bridging via the default ERC20 bridge. -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) -if err != nil { - log.Panic(err) -} +::callout{icon="i-heroicons-information-circle" color="blue"} +See the [default bridges documentation](https://docs.zksync.io/build/developer-reference/bridging-assets#default-bridges) +:: -l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) -if err != nil { - log.Panic(err) -} -``` +#### Inputs -Deposit ETH on non-ETH-based chain. +| Parameter | Type | Description | +| ------------------- | --------------------------- | -------------------------------- | +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | Token address. | +| `amount` | `*big.Int` | Deposit amount. | +| `to` | `common.Address` | Recipient address. | +| `from` | `common.Address` (optional) | Sender address. | +| `gasPerPubdataByte` | `*big.Int` (optional) | Current gas per byte of pubdata. | ```go -tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ - To: wallet.Address(), - Token: utils.LegacyEthAddress, - Amount: amount, - ApproveBaseERC20: true, - RefundRecipient: wallet.Address(), -}) -if err != nil { - log.Panic(err) -} - -l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) -if err != nil { - log.Panic(err) -} +EstimateDefaultBridgeDepositL2Gas(ctx context.Context, token common.Address, amount *big.Int, + to, from common.Address, gasPerPubdataByte *big.Int) (uint64, error) +``` -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) -if err != nil { - log.Panic(err) -} +#### Example -l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +```go +Token := common.HexToAddress("") +From := common.HexToAddress("") +To := common.HexToAddress("") +gas, err := wallet1.EstimateDefaultBridgeDepositL2Gas( + context.Background(), Token, big.NewInt(7), To, From, utils.RequiredL1ToL2GasPerPubdataLimit, +) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("L2 gas: ", gas) ``` -Deposit base token on non-ETH-based chain. +/; -```go -baseToken, err := wallet.BaseToken(nil) -if err != nil { - log.Panic(err) -} +### `EstimateGasDeposit` -tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ - To: wallet.Address(), - Token: baseToken, - Amount: amount, - ApproveBaseERC20: true, - RefundRecipient: wallet.Address(), -}) -if err != nil { - log.Panic(err) -} +Estimates the amount of gas required for a deposit transaction on L1 network. Gas of approving ERC20 token is not +included in the estimation. -l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) -if err != nil { - log.Panic(err) -} +#### Inputs -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) -if err != nil { - log.Panic(err) -} +| Parameter | Type | Description | +| --------- | ------------------------------------------------- | ------------------------ | +| `ctx` | `context.Context` | Context. | +| `msg` | [`DepositCallMsg`](/sdk/go/api/accounts/types#depositcallmsg) | Deposit call parameters. | -l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) -if err != nil { - log.Panic(err) -} +```go +EstimateGasDeposit(ctx context.Context, msg DepositCallMsg) (uint64, error) ``` -Deposit non-base token on non-ETH-based chain. +#### Example ```go -tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ - To: wallet.Address(), - Token: L1Dai, - Amount: amount, - ApproveERC20: true, - ApproveBaseERC20: true, - RefundRecipient: wallet.Address(), +depositGas, err := wallet.EstimateGasDeposit(context.Background(), accounts.DepositCallMsg{ + To: wallet.Address(), + Token: utils.EthAddress, + Amount: big.NewInt(7_000_000_000), }) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("Deposit gas: ", depositGas) +``` -l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx) -if err != nil { - log.Panic(err) -} +### `EstimateGasRequestExecute` -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) -if err != nil { - log.Panic(err) -} +Estimates the amount of gas required for a request execute transaction. + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------------------------------------------------------------- | -------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`RequestExecuteCallMsg`](/sdk/go/api/accounts/types#requestexecutecallmsg) | Request execute call parameters. | + +```go +EstimateGasRequestExecute(ctx context.Context, msg RequestExecuteCallMsg) (uint64, error) +``` -l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash) +#### Example + +```go +contractAddress := common.HexToAddress("") +gas, err := wallet.EstimateGasRequestExecute(context.Background(), accounts.RequestExecuteCallMsg{ + ContractAddress: contractAddress, + L2Value: big.NewInt(7_000_000_000), + L2GasLimit: big.NewInt(90_000), + GasPerPubdataByte: utils.RequiredL1ToL2GasPerPubdataLimit, + RefundRecipient: to, +}) if err != nil { - log.Panic(err) + log.Panic(err) } +fmt.Println("Gas: ", gas) ``` -### `EstimateGasDeposit` +### `FinalizeWithdraw` -Estimates the amount of gas required for a deposit transaction on L1 network. Gas of approving ERC20 token is not -included in the estimation. +Proves the inclusion of the L2 -> L1 withdrawal message. #### Inputs -| Parameter | Type | Description | -| --------- | ------------------------------------------------- | ------------------------ | -| `ctx` | `context.Context` | Context. | -| `msg` | [`DepositCallMsg`](/sdk/go/api/accounts/types#depositcallmsg) | Deposit call parameters. | +| Parameter | Type | Description | +| ---------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `withdrawalHash` | `common.Hash` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index` | `int` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. | ```go -EstimateGasDeposit(ctx context.Context, msg DepositCallMsg) (uint64, error) +FinalizeWithdraw(auth *TransactOpts, withdrawalHash common.Hash, index int) (*types.Transaction, error) ``` #### Example ```go -depositGas, err := wallet.EstimateGasDeposit(context.Background(), accounts.DepositCallMsg{ - To: wallet.Address(), - Token: utils.EthAddress, - Amount: big.NewInt(7_000_000_000), -}) +withdrawalHash := common.HexToHash("") +finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawalHash, 0) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Deposit gas: ", depositGas) +fmt.Println("Finalize withdraw transaction: ", finalizeWithdrawTx.Hash()) ``` ### `FullRequiredDepositFee` @@ -703,41 +752,77 @@ FullRequiredDepositFee(ctx context.Context, msg DepositCallMsg) (*FullDepositFee ```go fee, err := wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{ - To: wallet.Address(), - Token: utils.EthAddress, - Amount: big.NewInt(7_000_000_000), + To: wallet.Address(), + Token: utils.EthAddress, + Amount: big.NewInt(7_000_000_000), }) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Printf("Fee: %+v\n", fee) ``` -### `FinalizeWithdraw` +### `Init` -Proves the inclusion of the L2 -> L1 withdrawal message. +Creates an instance of WalletL1 associated with the account provided by the raw private key. + +```go +func NewWalletL1(rawPrivateKey []byte, clientL1 *ethclient.Client, clientL2 *clients.Client) (*WalletL1, error +``` + +Creates an instance of WalletL1 associated with the account provided by the signer. + +```go +NewWalletL1FromSigner(signer *Signer, clientL1 *ethclient.Client, clientL2 *clients.Client) (*WalletL1, error) +``` + +#### Example + +```go +PrivateKey := os.Getenv("PRIVATE_KEY") +ZkSyncEraProvider := "https://sepolia.era.zksync.dev" +EthereumProvider := "https://rpc.ankr.com/eth_sepolia" + +client, err := clients.Dial(ZkSyncEraProvider) +if err != nil { + log.Panic(err) +} +defer client.Close() + +ethClient, err := ethclient.Dial(EthereumProvider) +if err != nil { + log.Panic(err) +} +defer ethClient.Close() + +wallet, err := accounts.NewWalletL1(common.Hex2Bytes(PrivateKey), &client, ethClient) +if err != nil { + log.Panic(err) +} +``` + +### `IsEthBasedChain` + +Returns whether the chain is ETH-based. #### Inputs -| Parameter | Type | Description | -| ---------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `withdrawalHash` | `common.Hash` | Hash of the L2 transaction where the withdrawal was initiated. | -| `index` | `int` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -FinalizeWithdraw(auth *TransactOpts, withdrawalHash common.Hash, index int) (*types.Transaction, error) +IsEthBasedChain(ctx context.Context) (bool, error) ``` #### Example ```go -withdrawalHash := common.HexToHash("") -finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawalHash, 0) +isEthBased, err := wallet.IsEthBasedChain(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Finalize withdraw transaction: ", finalizeWithdrawTx.Hash()) +fmt.Println("Is ETH-based chain: ", isEthBased) ``` ### `IsWithdrawFinalized` @@ -762,101 +847,113 @@ IsWithdrawFinalized(opts *CallOpts, withdrawalHash common.Hash, index int) (bool withdrawalHash := common.HexToHash("") isFinalized, err := wallet.IsWithdrawFinalized(nil, withdrawalHash, 0) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Is withdrawal finalized: ", isFinalized) ``` -### `ClaimFailedDeposit` +### `L1BridgeContracts` -Withdraws funds from the initiated deposit, which failed when finalizing on L2. If the deposit L2 transaction has -failed, it sends an L1 transaction calling ClaimFailedDeposit method of the L1 bridge, which results in returning -L1 tokens back to the depositor, otherwise throws the error. +Returns L1 bridge contracts. #### Inputs -| Parameter | Type | Description | -| ------------- | --------------------------------------------------------- | ---------------------------------------------- | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `depositHash` | `common.Hash` | The L2 transaction hash of the failed deposit. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -ClaimFailedDeposit(auth *TransactOpts, depositHash common.Hash) (*types.Transaction, error) +L1BridgeContracts(ctx context.Context) (*zkTypes.L1BridgeContracts, error) ``` #### Example ```go -failedDepositL2Hash := common.HexToHash("") -cfdTx, err := wallet.ClaimFailedDeposit(nil, failedDepositL2Hash) +contracts, err := wallet.L1BridgeContracts(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("ClaimFailedDeposit hash: ", cfdTx.Hash) ``` -### `RequestExecute` +### `L2TokenAddress` -Request execution of L2 transaction from L1. +Returns the corresponding address on the L2 network for the token on the L1 network. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------------------------------------------------------------- | --------------------------------------- | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `tx` | [`RequestExecuteTransaction`](/sdk/go/api/accounts/types#requestexecutetransaction) | Request execute transaction parameters. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | L1 token address. | ```go -RequestExecute(auth *TransactOpts, tx RequestExecuteTransaction) (*types.Transaction, error) +L2TokenAddress(ctx context.Context, token common.Address) (common.Address, error) ``` #### Example ```go -contractAddress := common.HexToAddress("") -requestExecuteTx, err := wallet.RequestExecute(nil, accounts.RequestExecuteTransaction{ - ContractAddress: contractAddress, - L2Value: big.NewInt(7_000_000_000), - L2GasLimit: big.NewInt(90_000), - GasPerPubdataByte: utils.RequiredL1ToL2GasPerPubdataLimit, - RefundRecipient: to, -}) +l1DAI := common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") +l2DAI, err := wallet.L2TokenAddress(context.Background(), l1DAI) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Request execute tx: ", requestExecuteTx.Hash()) +fmt.Println("L2 DAI address: ", l2DAI) ``` -### `EstimateGasRequestExecute` +### `MainContract` -Estimates the amount of gas required for a request execute transaction. +Returns the ZKsync L1 smart contract. #### Inputs -| Parameter | Type | Description | -| --------- | --------------------------------------------------------------- | -------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`RequestExecuteCallMsg`](/sdk/go/api/accounts/types#requestexecutecallmsg) | Request execute call parameters. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -EstimateGasRequestExecute(ctx context.Context, msg RequestExecuteCallMsg) (uint64, error) +MainContract(ctx context.Context) (*zksync.IZkSync, error) +``` + +#### Example + +```go +mainContract, err := wallet.MainContract(context.Background()) +if err != nil { + log.Panic(err) +} +``` + +### `RequestExecute` + +Request execution of L2 transaction from L1. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------------------------------------------------------------- | --------------------------------------- | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `tx` | [`RequestExecuteTransaction`](/sdk/go/api/accounts/types#requestexecutetransaction) | Request execute transaction parameters. | + +```go +RequestExecute(auth *TransactOpts, tx RequestExecuteTransaction) (*types.Transaction, error) ``` #### Example ```go contractAddress := common.HexToAddress("") -gas, err := wallet.EstimateGasRequestExecute(context.Background(), accounts.RequestExecuteCallMsg{ - ContractAddress: contractAddress, - L2Value: big.NewInt(7_000_000_000), - L2GasLimit: big.NewInt(90_000), - GasPerPubdataByte: utils.RequiredL1ToL2GasPerPubdataLimit, - RefundRecipient: to, +requestExecuteTx, err := wallet.RequestExecute(nil, accounts.RequestExecuteTransaction{ + ContractAddress: contractAddress, + L2Value: big.NewInt(7_000_000_000), + L2GasLimit: big.NewInt(90_000), + GasPerPubdataByte: utils.RequiredL1ToL2GasPerPubdataLimit, + RefundRecipient: to, }) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Gas: ", gas) +fmt.Println("Request execute tx: ", requestExecuteTx.Hash()) ``` ### `RequestExecuteAllowanceParams` @@ -887,116 +984,19 @@ allowanceParams, err := wallet.RequestExecuteAllowanceParams(nil, msg) if err != nil { log.Panic(err) } - + bridgeContracts, err := client.BridgeContracts(context.Background()) if err != nil { log.Panic(err) } - + approveTx, err := wallet.ApproveERC20(nil, allowanceParams.Token, allowanceParams.Allowance, bridgeContracts.L1SharedBridge) if err != nil { log.Panic(err) } - + _, err = bind.WaitMined(context.Background(), ethClient, approveTx) if err != nil { log.Panic(err) } ``` - -### `EstimateCustomBridgeDepositL2Gas` - -Used by [`EstimateDefaultBridgeDepositL2Gas`](#estimatedefaultbridgedepositl2gas) to estimate L2 gas -required for token bridging via a custom ERC20 bridge. - -::callout{icon="i-heroicons-information-circle" color="blue"} -See the [default bridges documentation](https://docs.zksync.io/build/developer-reference/bridging-assets#default-bridges) -:: - -#### Inputs - -| Parameter | Type | Description | -| ------------------- | --------------------------- | -------------------------------- | -| `ctx` | `context.Context` | Context. | -| `l1BridgeAddress` | `common.Address` | L1 bridge address. | -| `l2BridgeAddress` | `common.Address` | L2 bridge address. | -| `token` | `common.Address` | Token address. | -| `amount` | `*big.Int` | Deposit amount. | -| `to` | `common.Address` | Recipient address. | -| `bridgeData` | `[]byte` | Bridge data. | -| `from` | `common.Address` (optional) | Sender address. | -| `gasPerPubdataByte` | `*big.Int` (optional) | Current gas per byte of pubdata. | - -```go -EstimateCustomBridgeDepositL2Gas(ctx context.Context, l1BridgeAddress, l2BridgeAddress, token common.Address, - amount *big.Int, to common.Address, bridgeData []byte, from common.Address, gasPerPubdataByte *big.Int) (uint64, error) -``` - -#### Example - -```go -L1BridgeAddress := common.HexToAddress("") -Token := common.HexToAddress("") -From := common.HexToAddress("") -To := common.HexToAddress("") - - -bridge, err := l1bridge.NewIL1Bridge(L1BridgeAddress, ethClient) -if err != nil { - log.Panic(err) -} -l2BridgeAddress, err := bridge.L2Bridge(nil) -if err != nil { - log.Panic(err) -} -customBridgeData, err := utils.Erc20DefaultBridgeData(Token, ethClient) -if err != nil { - log.Panic(err) -} - -gas, err := wallet1.EstimateCustomBridgeDepositL2Gas(context.Background(), L1BridgeAddress, l2BridgeAddress, Token, - big.NewInt(7), To, customBridgeData, From, utils.RequiredL1ToL2GasPerPubdataLimit) -if err != nil { - log.Panic(err) -} -fmt.Println("L2 gas: ", gas) -``` - -### `EstimateDefaultBridgeDepositL2Gas` - -Returns an estimation of L2 gas required for token bridging via the default ERC20 bridge. - -::callout{icon="i-heroicons-information-circle" color="blue"} -See the [default bridges documentation](https://docs.zksync.io/build/developer-reference/bridging-assets#default-bridges) -:: - -#### Inputs - -| Parameter | Type | Description | -| ------------------- | --------------------------- | -------------------------------- | -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | Token address. | -| `amount` | `*big.Int` | Deposit amount. | -| `to` | `common.Address` | Recipient address. | -| `from` | `common.Address` (optional) | Sender address. | -| `gasPerPubdataByte` | `*big.Int` (optional) | Current gas per byte of pubdata. | - -```go -EstimateDefaultBridgeDepositL2Gas(ctx context.Context, token common.Address, amount *big.Int, - to, from common.Address, gasPerPubdataByte *big.Int) (uint64, error) -``` - -#### Example - -```go -Token := common.HexToAddress("") -From := common.HexToAddress("") -To := common.HexToAddress("") -gas, err := wallet1.EstimateDefaultBridgeDepositL2Gas( - context.Background(), Token, big.NewInt(7), To, From, utils.RequiredL1ToL2GasPerPubdataLimit, -) -if err != nil { - log.Panic(err) -} -fmt.Println("L2 gas: ", gas) -``` diff --git a/content/sdk/20.go/02.api/01.accounts/05.walletl2.md b/content/sdk/20.go/02.api/01.accounts/05.walletl2.md index ff702eb2..720fcb72 100644 --- a/content/sdk/20.go/02.api/01.accounts/05.walletl2.md +++ b/content/sdk/20.go/02.api/01.accounts/05.walletl2.md @@ -7,42 +7,6 @@ tags: ["zksync", "walletL2", "account management", "go", "sdk"] The `WalletL2` class provides functionalities for managing and interacting with accounts on the Layer 2 (L2) network. It includes methods for creating wallets, querying balances, transferring tokens, and interacting with smart contracts on the ZKsync network. - -### `Init` - -Creates an instance of `WalletL2` associated with the account provided by the raw private key. - -```go -func NewWalletL2(rawPrivateKey []byte, client *clients.Client) (*WalletL2, error) -``` - -Creates an instance of `WalletL2`. The `client` can be optional; if it is not provided, only -`SignTransaction`, `Address`, `Signer` can be performed, as the rest of the functionalities -require communication to the network. - -```go -func NewWalletL2FromSigner(signer *Signer, client *clients.Client) (*WalletL2, error) -``` - -#### Example - -```go -PrivateKey := os.Getenv("PRIVATE_KEY") -ZkSyncEraProvider := "https://testnet.era.zksync.dev" - -client, err := clients.Dial(ZkSyncEraProvider) -if err != nil { - log.Panic(err) -} -defer client.Close() - -wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client) -if err != nil { - log.Panic(err) -} - -``` - ### `Address` Returns the address of the associated account. @@ -57,18 +21,28 @@ Address() common.Address fmt.Println("Address: ", wallet.Address()) ``` -### `Signer` +### `AllBalances` -Returns the signer of the associated account. +Returns all balances for confirmed tokens given by an associated account. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -Signer() Signer +AllBalances(ctx context.Context) (map[common.Address]*big.Int, error) ``` #### Example ```go -fmt.Printf("Signer %+v\n", wallet.Signer()) +balances, err := wallet.AllBalances(context.Background()) +if err != nil { + log.Panic(err) +} +fmt.Printf("Balances: %+v\n", balances) ``` ### `Balance` @@ -93,56 +67,58 @@ Balance(ctx context.Context, token common.Address, at *big.Int) (*big.Int, error ```go balance, err := wallet.Balance(context.Background(), utils.EthAddress, nil) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Balance: ", balance) ``` -### `AllBalances` +### `CallContract` -Returns all balances for confirmed tokens given by an associated account. +Executes a message call for EIP-712 transaction, which is directly executed in the VM of the node, but never mined +into the blockchain. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +| ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`CallMsg`](/sdk/go/api/accounts/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | +| `blockNumber` | `*big.Int` (optional) | Selects the block height at which the call runs. It can be `nil`, in which case the code is taken from the latest known block. Note that state from very old blocks might not be available. | ```go -AllBalances(ctx context.Context) (map[common.Address]*big.Int, error) +CallContract(ctx context.Context, msg CallMsg, blockNumber *big.Int) ([]byte, error) ``` #### Example ```go -balances, err := wallet.AllBalances(context.Background()) +// The Crown token on testnet +TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") + +tokenAbi, err := erc20.IERC20MetaData.GetAbi() if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Printf("Balances: %+v\n", balances) -``` - -### `L2BridgeContracts` - -Returns L2 bridge contracts. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | - -```go -L2BridgeContracts(ctx context.Context) (*zkTypes.L2BridgeContracts, error) -``` - -#### Example - -```go -contracts, err := wallet.L2BridgeContracts(context.Background()) +symbolCalldata, err := tokenAbi.Pack("symbol") +if err != nil { + log.Panic(err) +} + +result, err := wallet.CallContract(context.Background(), types.CallMsg{ + CallMsg: ethereum.CallMsg{ + To: &TokenAddress, + Data: symbolCalldata, + }, +}, nil) +if err != nil { + log.Panic(err) +} +unpack, err := tokenAbi.Unpack("symbol", result) if err != nil { - log.Panic(err) + log.Panic(err) } +symbol := *abi.ConvertType(unpack[0], new(string)).(*string) +fmt.Println("Symbol: ", symbol) ``` ### `DeploymentNonce` @@ -168,62 +144,33 @@ if err != nil { } ``` -### `IsBaseToken` - -Returns whether the token is the base token. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ----------------- |----------------| -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | Token address. | - -```go -IsBaseToken(ctx context.Context, token common.Address) (bool, error) -``` - -#### Example - -```go -isBaseToken, err := wallet.IsBaseToken( - context.Background(), - common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") -) -if err != nil { - log.Panic(err) -} -fmt.Println("Is base token: ", isBaseToken) -``` - -### `Withdraw` +### `EstimateGasTransfer` -Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network -to the target account on L1 network. +Estimates the amount of gas required for a transfer transaction. #### Inputs -| Parameter | Type | Description | -| --------- | --------------------------------------------------------------- | ---------------------------------- | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `tx` | [`WithdrawalTransaction`](/sdk/go/api/accounts/types#withdrawaltransaction) | Withdrawal transaction parameters. | +| Parameter | Type | Description | +| --------- | --------------------------------------------------- | ------------------------- | +| `ctx` | `context.Context` | Context. | +| `msg` | [`TransferCallMsg`](/sdk/go/api/accounts/types#transfercallmsg) | Transfer call parameters. | ```go -Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (*types.Transaction, error) +EstimateGasTransfer(ctx context.Context, msg TransferCallMsg) (uint64, error) ``` #### Example ```go -tx, err := wallet.Withdraw(nil, accounts.WithdrawalTransaction{ - To: wallet.Address(), - Amount: big.NewInt(1_000_000_000_000_000_000), - Token: utils.EthAddress, +gas, err := wallet.EstimateGasTransfer(context.Background(), accounts.TransferCallMsg{ + To: common.HexToAddress(""), + Amount: big.NewInt(7_000_000_000), + Token: utils.EthAddress, }) if err != nil { - panic(err) + log.Panic(err) } -fmt.Println("Withdraw transaction: ", tx.Hash()) +fmt.Println("Gas: ", gas) ``` ### `EstimateGasWithdraw` @@ -245,129 +192,106 @@ EstimateGasWithdraw(ctx context.Context, msg WithdrawalCallMsg) (uint64, error) ```go gas, err := wallet.EstimateGasWithdraw(context.Background(), accounts.WithdrawalCallMsg{ - To: wallet.Address(), - Amount: big.NewInt(7_000_000), - Token: utils.EthAddress, + To: wallet.Address(), + Amount: big.NewInt(7_000_000), + Token: utils.EthAddress, }) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Gas: ", gas) ``` -### `Transfer` +### `Init` -Moves the ETH or any ERC20 token from the associated account to the target account. +Creates an instance of `WalletL2` associated with the account provided by the raw private key. -#### Inputs +```go +func NewWalletL2(rawPrivateKey []byte, client *clients.Client) (*WalletL2, error) +``` -| Parameter | Type | Description | -| --------- | ----------------------------------------------------------- | -------------------------------- | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `tx` | [`TransferTransaction`](/sdk/go/api/accounts/types#transfertransaction) | Transfer transaction parameters. | +Creates an instance of `WalletL2`. The `client` can be optional; if it is not provided, only +`SignTransaction`, `Address`, `Signer` can be performed, as the rest of the functionalities +require communication to the network. ```go -Transfer(auth *TransactOpts, tx TransferTransaction) (*types.Transaction, error) +func NewWalletL2FromSigner(signer *Signer, client *clients.Client) (*WalletL2, error) ``` #### Example ```go -tx, err := wallet.Transfer(nil, accounts.TransferTransaction{ - To: common.HexToAddress(""), - Amount: big.NewInt(7_000_000_000), - Token: utils.EthAddress, -}) +PrivateKey := os.Getenv("PRIVATE_KEY") +ZkSyncEraProvider := "https://testnet.era.zksync.dev" + +client, err := clients.Dial(ZkSyncEraProvider) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Transaction: ", tx.Hash()) +defer client.Close() + +wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client) +if err != nil { + log.Panic(err) +} + ``` -### `EstimateGasTransfer` +### `IsBaseToken` -Estimates the amount of gas required for a transfer transaction. +Returns whether the token is the base token. #### Inputs -| Parameter | Type | Description | -| --------- | --------------------------------------------------- | ------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`TransferCallMsg`](/sdk/go/api/accounts/types#transfercallmsg) | Transfer call parameters. | +| Parameter | Type | Description | +| --------- | ----------------- |----------------| +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | Token address. | ```go -EstimateGasTransfer(ctx context.Context, msg TransferCallMsg) (uint64, error) +IsBaseToken(ctx context.Context, token common.Address) (bool, error) ``` #### Example ```go -gas, err := wallet.EstimateGasTransfer(context.Background(), accounts.TransferCallMsg{ - To: common.HexToAddress(""), - Amount: big.NewInt(7_000_000_000), - Token: utils.EthAddress, -}) +isBaseToken, err := wallet.IsBaseToken( + context.Background(), + common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B") +) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Gas: ", gas) +fmt.Println("Is base token: ", isBaseToken) ``` -### `CallContract` +### `L2BridgeContracts` -Executes a message call for EIP-712 transaction, which is directly executed in the VM of the node, but never mined -into the blockchain. +Returns L2 bridge contracts. #### Inputs -| Parameter | Type | Description | -| ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ctx` | `context.Context` | Context. | -| `msg` | [`CallMsg`](/sdk/go/api/accounts/types#callmsg) | Contains parameters for contract call using EIP-712 transaction. | -| `blockNumber` | `*big.Int` (optional) | Selects the block height at which the call runs. It can be `nil`, in which case the code is taken from the latest known block. Note that state from very old blocks might not be available. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go -CallContract(ctx context.Context, msg CallMsg, blockNumber *big.Int) ([]byte, error) +L2BridgeContracts(ctx context.Context) (*zkTypes.L2BridgeContracts, error) ``` #### Example ```go -// The Crown token on testnet -TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F") - -tokenAbi, err := erc20.IERC20MetaData.GetAbi() -if err != nil { - log.Panic(err) -} -symbolCalldata, err := tokenAbi.Pack("symbol") -if err != nil { - log.Panic(err) -} - -result, err := wallet.CallContract(context.Background(), types.CallMsg{ - CallMsg: ethereum.CallMsg{ - To: &TokenAddress, - Data: symbolCalldata, - }, -}, nil) -if err != nil { - log.Panic(err) -} -unpack, err := tokenAbi.Unpack("symbol", result) +contracts, err := wallet.L2BridgeContracts(context.Background()) if err != nil { - log.Panic(err) + log.Panic(err) } -symbol := *abi.ConvertType(unpack[0], new(string)).(*string) -fmt.Println("Symbol: ", symbol) ``` -### PopulateTransaction +### `SendTransaction` -Designed for users who prefer a simplified approach by providing only the necessary data to create a valid -[EIP-712 transaction](/sdk/go/api/types#transaction712). 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. +Injects a transaction into the pending pool for execution. Any unset transaction fields are prepared using the +`PopulateTransaction` method. #### Inputs @@ -377,7 +301,7 @@ Any other fields that are not set will be prepared by this method. | `tx` | [`Transaction`](/sdk/go/api/accounts/types#transaction) | Transaction parameters. | ```go -PopulateTransaction(ctx context.Context, tx Transaction) (*zkTypes.Transaction712, error) +SendTransaction(ctx context.Context, tx *Transaction) (common.Hash, error) ``` #### Example @@ -388,23 +312,61 @@ TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F" // Paymaster for Crown token on testnet PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") - + abi, err := erc20.IERC20MetaData.GetAbi() if err != nil { - log.Panic(err) + log.Panic(err) } - + // Encode transfer function from token contract calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7)) if err != nil { - log.Panic(err) + log.Panic(err) } - -preparedTx, err := wallet.PopulateTransaction(context.Background(), &accounts.Transaction{ - To: &TokenAddress, - Data: calldata, + +// Create paymaster parameters with encoded paymaster input +paymasterParams, err := utils.GetPaymasterParams( + PaymasterAddress, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: TokenAddress, + MinimalAllowance: big.NewInt(1), + InnerInput: []byte{}, + }) +if err != nil { + log.Panic(err) +} + +hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{ + To: &TokenAddress, + Data: calldata, + Meta: &types.Eip712Meta{ + PaymasterParams: paymasterParams, + }, }) -fmt.Printf("Prepared tx: %+v\n", preparedTx) +if err != nil { + log.Panic(err) +} + +_, err = client.WaitMined(context.Background(), hash) +if err != nil { + log.Panic(err) +} + +fmt.Println("Tx: ", hash) +``` + +### `Signer` + +Returns the signer of the associated account. + +```go +Signer() Signer +``` + +#### Example + +```go +fmt.Printf("Signer %+v\n", wallet.Signer()) ``` ### `SignTransaction` @@ -431,34 +393,95 @@ TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F" // Paymaster for Crown token on testnet PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") - + abi, err := erc20.IERC20MetaData.GetAbi() if err != nil { - log.Panic(err) + log.Panic(err) } - + // Encode transfer function from token contract calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7)) if err != nil { - log.Panic(err) + log.Panic(err) } - + preparedTx, err := wallet.PopulateTransaction(context.Background(), &accounts.Transaction{ - To: &TokenAddress, - Data: calldata, + To: &TokenAddress, + Data: calldata, }) - + signedTx, err := wallet.SignTransaction(preparedTx) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Printf("Signed tx: %+v\n", signedTx) ``` -### `SendTransaction` +### `Transfer` -Injects a transaction into the pending pool for execution. Any unset transaction fields are prepared using the -`PopulateTransaction` method. +Moves the ETH or any ERC20 token from the associated account to the target account. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------------------------------------------------- | -------------------------------- | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `tx` | [`TransferTransaction`](/sdk/go/api/accounts/types#transfertransaction) | Transfer transaction parameters. | + +```go +Transfer(auth *TransactOpts, tx TransferTransaction) (*types.Transaction, error) +``` + +#### Example + +```go +tx, err := wallet.Transfer(nil, accounts.TransferTransaction{ + To: common.HexToAddress(""), + Amount: big.NewInt(7_000_000_000), + Token: utils.EthAddress, +}) +if err != nil { + log.Panic(err) +} +fmt.Println("Transaction: ", tx.Hash()) +``` + +### `Withdraw` + +Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network +to the target account on L1 network. + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------------------------------------------------------------- | ---------------------------------- | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `tx` | [`WithdrawalTransaction`](/sdk/go/api/accounts/types#withdrawaltransaction) | Withdrawal transaction parameters. | + +```go +Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (*types.Transaction, error) +``` + +#### Example + +```go +tx, err := wallet.Withdraw(nil, accounts.WithdrawalTransaction{ + To: wallet.Address(), + Amount: big.NewInt(1_000_000_000_000_000_000), + Token: utils.EthAddress, +}) +if err != nil { + panic(err) +} +fmt.Println("Withdraw transaction: ", tx.Hash()) +``` + +### PopulateTransaction + +Designed for users who prefer a simplified approach by providing only the necessary data to create a valid +[EIP-712 transaction](/sdk/go/api/types#transaction712). 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. #### Inputs @@ -468,7 +491,7 @@ Injects a transaction into the pending pool for execution. Any unset transaction | `tx` | [`Transaction`](/sdk/go/api/accounts/types#transaction) | Transaction parameters. | ```go -SendTransaction(ctx context.Context, tx *Transaction) (common.Hash, error) +PopulateTransaction(ctx context.Context, tx Transaction) (*zkTypes.Transaction712, error) ``` #### Example @@ -479,45 +502,21 @@ TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F" // Paymaster for Crown token on testnet PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46") ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") - + abi, err := erc20.IERC20MetaData.GetAbi() if err != nil { - log.Panic(err) + log.Panic(err) } - + // Encode transfer function from token contract calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7)) if err != nil { - log.Panic(err) + log.Panic(err) } - -// Create paymaster parameters with encoded paymaster input -paymasterParams, err := utils.GetPaymasterParams( - PaymasterAddress, - &zkTypes.ApprovalBasedPaymasterInput{ - Token: TokenAddress, - MinimalAllowance: big.NewInt(1), - InnerInput: []byte{}, - }) -if err != nil { - log.Panic(err) -} - -hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{ - To: &TokenAddress, - Data: calldata, - Meta: &types.Eip712Meta{ - PaymasterParams: paymasterParams, - }, + +preparedTx, err := wallet.PopulateTransaction(context.Background(), &accounts.Transaction{ + To: &TokenAddress, + Data: calldata, }) -if err != nil { - log.Panic(err) -} - -_, err = client.WaitMined(context.Background(), hash) -if err != nil { - log.Panic(err) -} - -fmt.Println("Tx: ", hash) +fmt.Printf("Prepared tx: %+v\n", preparedTx) ``` diff --git a/content/sdk/20.go/02.api/01.accounts/06.smartaccount.md b/content/sdk/20.go/02.api/01.accounts/06.smartaccount.md index 19da7ee3..075f5f8f 100644 --- a/content/sdk/20.go/02.api/01.accounts/06.smartaccount.md +++ b/content/sdk/20.go/02.api/01.accounts/06.smartaccount.md @@ -8,53 +8,69 @@ A `SmartAccount` is a signer which can be configured to sign various payloads us The secret can be in any form, allowing for flexibility when working with different account implementations. The `SmartAccount` is bound to a specific address and provides the ability to define custom method for populating transactions and custom signing method used for signing messages, typed data, and transactions. +### `Address` -### `Init` +Returns the address of the associated account. -Creates a new `SmartAccount` instance. By default, it uses [`SignPayloadWithECDSA`](/sdk/go/api/accounts/smart-account-utils#signpayloadwithecdsa) -as a signer and [`PopulateTransactionECDSA`](/sdk/go/api/accounts/smart-account-utils#populatetransactionecdsa) as -a builder and -requires private key in hex format to be provided. +```go +Address() common.Address +``` + +#### Example + +```go +fmt.Println("Address: ", account.Address()) +``` + +### `AllBalances` + +Returns all balances for confirmed tokens given by an associated account. #### Inputs -| Parameter | Type | Description | -|-----------|--------------------------------------------------------------------|---------------------------------------------------------| -| `address` | `common.Address` | Account address. | -| `secret` | `interface{}` | Secret used for signing. | -| `signer` | [`*PayloadSigner`](/sdk/go/api/accounts/types#payloadsigner) | Function used for signing payload. | -| `builder` | [`*TransactionBuilder`](/sdk/go/api/accounts/types#transactionbuilder) | Function used for populating transaction. | -| `client` | [`*clients.BaseClient`](/sdk/go/api/clients/baseclient) | The client to connect to. Can be `nil` for offline usage. | +| Parameter | Type | Description | +| --------- | ----------------- | ----------- | +| `ctx` | `context.Context` | Context. | ```go +AllBalances(ctx context.Context) (map[common.Address]*big.Int, error) +``` -func NewSmartAccount( - address common.Address, - secret interface{}, - signer *PayloadSigner, - builder *TransactionBuilder, - client *clients.BaseClient) *SmartAccount +#### Example + +```go +balances, err := account.AllBalances(context.Background()) +if err != nil { + log.Panic(err) +} +fmt.Printf("Balances: %+v\n", balances) ``` -#### Examples +### `Balance` + +Returns the balance of the specified token that can be either ETH or any ERC20 token. The block number can be `nil`, +in which case the balance is taken from the latest known block. + +#### Inputs + +| Parameter | Type | Description | +| --------- | ----------------- | ----------------- | +| `ctx` | `context.Context` | Context. | +| `token` | `common.Address` | L2 token address. | +| `at` | `*big.Int` | Block number. | ```go -privateKey := os.Getenv("PRIVATE_KEY") -address := common.HexToAddress("") -ZkSyncEraProvider := "https://sepolia.era.zksync.dev" +Balance(ctx context.Context, token common.Address, at *big.Int) (*big.Int, error) +``` -client, err := clients.DialBase(ZkSyncEraProvider) +#### Example + +```go +balance, err := account.Balance(context.Background(), utils.EthAddress, nil) if err != nil { - log.Panic(err) + log.Panic(err) } -defer client.Close() - -account := accounts.NewSmartAccount( - address, - privateKey, - &accounts.SignPayloadWithECDSA, - &accounts.PopulateTransactionECDSA, -nil) +fmt.Println("Balance: ", balance) ``` ### `Connect` @@ -77,80 +93,86 @@ Connect(client *clients.BaseClient) *SmartAccount ```go privateKey := os.Getenv("PRIVATE_KEY") ZkSyncEraProvider := "https://testnet.era.zksync.dev" - + client, err := clients.Dial(ZkSyncEraProvider) if err != nil { - log.Panic(err) + log.Panic(err) } defer client.Close() - + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, nil) account = account.Connect(client) ``` -### `Address` - -Returns the address of the associated account. - -```go -Address() common.Address -``` - -#### Example - -```go -fmt.Println("Address: ", account.Address()) -``` - -### `Balance` +### `DeploymentNonce` -Returns the balance of the specified token that can be either ETH or any ERC20 token. The block number can be `nil`, -in which case the balance is taken from the latest known block. +Returns the deployment nonce of the account. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------------- | -| `ctx` | `context.Context` | Context. | -| `token` | `common.Address` | L2 token address. | -| `at` | `*big.Int` | Block number. | +| Parameter | Type | Description | +| --------- | ------------------------------------------------ | ------------- | +| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | ```go -Balance(ctx context.Context, token common.Address, at *big.Int) (*big.Int, error) +DeploymentNonce(opts *CallOpts) (*big.Int, error) ``` #### Example ```go -balance, err := account.Balance(context.Background(), utils.EthAddress, nil) +deploymentNonce, err := account.DeploymentNonce(nil) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Println("Balance: ", balance) ``` -### `AllBalances` +### `Init` -Returns all balances for confirmed tokens given by an associated account. +Creates a new `SmartAccount` instance. By default, it uses [`SignPayloadWithECDSA`](/sdk/go/api/accounts/smart-account-utils#signpayloadwithecdsa) +as a signer and [`PopulateTransactionECDSA`](/sdk/go/api/accounts/smart-account-utils#populatetransactionecdsa) as +a builder and +requires private key in hex format to be provided. #### Inputs -| Parameter | Type | Description | -| --------- | ----------------- | ----------- | -| `ctx` | `context.Context` | Context. | +| Parameter | Type | Description | +|-----------|--------------------------------------------------------------------|---------------------------------------------------------| +| `address` | `common.Address` | Account address. | +| `secret` | `interface{}` | Secret used for signing. | +| `signer` | [`*PayloadSigner`](/sdk/go/api/accounts/types#payloadsigner) | Function used for signing payload. | +| `builder` | [`*TransactionBuilder`](/sdk/go/api/accounts/types#transactionbuilder) | Function used for populating transaction. | +| `client` | [`*clients.BaseClient`](/sdk/go/api/clients/baseclient) | The client to connect to. Can be `nil` for offline usage. | ```go -AllBalances(ctx context.Context) (map[common.Address]*big.Int, error) + +func NewSmartAccount( + address common.Address, + secret interface{}, + signer *PayloadSigner, + builder *TransactionBuilder, + client *clients.BaseClient) *SmartAccount ``` -#### Example +#### Examples ```go -balances, err := account.AllBalances(context.Background()) +privateKey := os.Getenv("PRIVATE_KEY") +address := common.HexToAddress("") +ZkSyncEraProvider := "https://sepolia.era.zksync.dev" + +client, err := clients.DialBase(ZkSyncEraProvider) if err != nil { - log.Panic(err) + log.Panic(err) } -fmt.Printf("Balances: %+v\n", balances) +defer client.Close() + +account := accounts.NewSmartAccount( + address, + privateKey, + &accounts.SignPayloadWithECDSA, + &accounts.PopulateTransactionECDSA, +nil) ``` ### `Nonce` @@ -174,34 +196,11 @@ Nonce(ctx context.Context, blockNumber *big.Int) (uint64, error) ```go nonce, err := account.Nonce(context.Background(), big.NewInt(9000)) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Nonce: ", nonce) ``` -### `DeploymentNonce` - -Returns the deployment nonce of the account. - -#### Inputs - -| Parameter | Type | Description | -| --------- | ------------------------------------------------ | ------------- | -| `opts` | [`CallOpts`](/sdk/go/api/accounts/types#callopts) (optional) | Call options. | - -```go -DeploymentNonce(opts *CallOpts) (*big.Int, error) -``` - -#### Example - -```go -deploymentNonce, err := account.DeploymentNonce(nil) -if err != nil { - log.Panic(err) -} -``` - ### `PopulateTransaction` Populates the transaction `tx` using the provided [`TransactionBuilder`](/sdk/go/api/accounts/types#transactionbuilder) function. @@ -227,18 +226,17 @@ tx := &zkTypes.Transaction712{ To: &address, Value: big.NewInt(7_000_000_000), } - + err = account.PopulateTransaction(context.Background(), tx) if err != nil { log.Panic(err) } ``` -### `SignTransaction` +### `SendTransaction` -Returns a signed transaction that is ready to be broadcast to -the network. The `PopulateTransaction` method is called first to ensure that all -necessary properties for the transaction to be valid have been populated. +Injects a transaction into the pending pool for execution. +The `SignTransaction` is called first to ensure transaction is properly signed. #### Inputs @@ -248,15 +246,14 @@ necessary properties for the transaction to be valid have been populated. | `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be signed. | ```go - -SignTransaction(ctx context.Context, tx *zkTypes.Transaction712) ([]byte, error) +SendTransaction(ctx context.Context, tx *zkTypes.Transaction712) (common.Hash, error) ``` #### Example ```go address := common.HexToAddress("") -signedTx, err := account.SignTransaction(context.Background(), &zkTypes.Transaction712{ +txHash, err := account.SendTransaction(context.Background(), &zkTypes.Transaction712{ To: &address, Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH }) @@ -265,54 +262,56 @@ if err != nil { } ``` -### `SendTransaction` +### `SignMessage` -Injects a transaction into the pending pool for execution. -The `SignTransaction` is called first to ensure transaction is properly signed. +Signs a message using the provided [`PayloadSigner`](/sdk/go/api/accounts/types#payloadsigner) function. #### Inputs -| Parameter | Type | Description | -|-----------|---------------------------------------------------------|------------------------------------------| -| `ctx` | `context.Context` | Context. | -| `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be signed. | +| Parameter | Type | Description | +|-----------|-------------------|--------------------------------------| +| `ctx` | `context.Context` | Context. | +| `message` | `[]byte` | The message that needs to be signed. | ```go -SendTransaction(ctx context.Context, tx *zkTypes.Transaction712) (common.Hash, error) +SignMessage(ctx context.Context, message []byte) ([]byte, error) ``` #### Example ```go -address := common.HexToAddress("") -txHash, err := account.SendTransaction(context.Background(), &zkTypes.Transaction712{ - To: &address, - Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH -}) +signature, err := account.SignMessage(context.Background(), []byte("Hello World!")) if err != nil { log.Panic(err) } ``` -### `SignMessage` +### `SignTransaction` -Signs a message using the provided [`PayloadSigner`](/sdk/go/api/accounts/types#payloadsigner) function. +Returns a signed transaction that is ready to be broadcast to +the network. The `PopulateTransaction` method is called first to ensure that all +necessary properties for the transaction to be valid have been populated. #### Inputs -| Parameter | Type | Description | -|-----------|-------------------|--------------------------------------| -| `ctx` | `context.Context` | Context. | -| `message` | `[]byte` | The message that needs to be signed. | +| Parameter | Type | Description | +|-----------|---------------------------------------------------------|------------------------------------------| +| `ctx` | `context.Context` | Context. | +| `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be signed. | ```go -SignMessage(ctx context.Context, message []byte) ([]byte, error) + +SignTransaction(ctx context.Context, tx *zkTypes.Transaction712) ([]byte, error) ``` #### Example ```go -signature, err := account.SignMessage(context.Background(), []byte("Hello World!")) +address := common.HexToAddress("") +signedTx, err := account.SignTransaction(context.Background(), &zkTypes.Transaction712{ + To: &address, + Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH +}) if err != nil { log.Panic(err) } @@ -364,63 +363,6 @@ if err != nil { } ``` -### `Withdraw` - -Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network -to the target account on L1 network. - -#### Inputs - -| Parameter | Type | Description | -| --------- | --------------------------------------------------------------- | ---------------------------------- | -| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | -| `tx` | [`WithdrawalTransaction`](/sdk/go/api/accounts/types#withdrawaltransaction) | Withdrawal transaction parameters. | - -```go -Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (common.Hash, error) -``` - -#### Examples - -Withdraw ETH. - -```go -txHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ - To: account.Address(), - Amount: big.NewInt(1_000_000_000_000_000_000), - Token: utils.LegacyEthAddress, -}) -if err != nil { - log.Panic(err) -} -fmt.Println("Withdraw transaction: ", txHash) -``` - -Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. - -```go -token := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F"); // Crown token which can be minted for free -paymaster := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46"); // Paymaster for Crown token - -paymasterParams, err := utils.GetPaymasterParams( - paymaster, - &zkTypes.ApprovalBasedPaymasterInput{ - Token: token, - MinimalAllowance: big.NewInt(1), - InnerInput: []byte{}, -}) -if err != nil { - log.Panic(err) -} - -txHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ - To: account.Address(), - Amount: big.NewInt(1_000_000_000_000_000_000), - Token: utils.LegacyEthAddress, - PaymasterParams: paymasterParams, - }) -``` - ### `Transfer` Moves the ETH or any ERC20 token from the associated account to the target account. @@ -447,7 +389,7 @@ txHash, err := account.Transfer(nil, accounts.TransferTransaction{ Token: utils.LegacyEthAddress, }) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Transaction: ", txHash) ``` @@ -457,7 +399,7 @@ Transfer ETH using paymaster to facilitate fee payment with an ERC20 token. ```go token := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F"); // Crown token which can be minted for free paymaster := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46"); // Paymaster for Crown token - + paymasterParams, err := utils.GetPaymasterParams( paymaster, &zkTypes.ApprovalBasedPaymasterInput{ @@ -468,7 +410,7 @@ paymasterParams, err := utils.GetPaymasterParams( if err != nil { log.Panic(err) } - + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ To: Address2, Amount: amount, @@ -476,7 +418,64 @@ txHash, err := account.Transfer(nil, accounts.TransferTransaction{ PaymasterParams: paymasterParams, }) if err != nil { - log.Panic(err) + log.Panic(err) } fmt.Println("Transaction: ", txHash) ``` + +### `Withdraw` + +Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network +to the target account on L1 network. + +#### Inputs + +| Parameter | Type | Description | +| --------- | --------------------------------------------------------------- | ---------------------------------- | +| `auth` | [`*TransactOpts`](/sdk/go/api/accounts/types#transactopts) (optional) | Transaction options. | +| `tx` | [`WithdrawalTransaction`](/sdk/go/api/accounts/types#withdrawaltransaction) | Withdrawal transaction parameters. | + +```go +Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (common.Hash, error) +``` + +#### Examples + +Withdraw ETH. + +```go +txHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: account.Address(), + Amount: big.NewInt(1_000_000_000_000_000_000), + Token: utils.LegacyEthAddress, +}) +if err != nil { + log.Panic(err) +} +fmt.Println("Withdraw transaction: ", txHash) +``` + +Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token. + +```go +token := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F"); // Crown token which can be minted for free +paymaster := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46"); // Paymaster for Crown token + +paymasterParams, err := utils.GetPaymasterParams( + paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: token, + MinimalAllowance: big.NewInt(1), + InnerInput: []byte{}, +}) +if err != nil { + log.Panic(err) +} + +txHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: account.Address(), + Amount: big.NewInt(1_000_000_000_000_000_000), + Token: utils.LegacyEthAddress, + PaymasterParams: paymasterParams, + }) +``` diff --git a/content/sdk/20.go/02.api/01.accounts/08.smart-account-utils.md b/content/sdk/20.go/02.api/01.accounts/08.smart-account-utils.md index 4b51a01c..b062d8d2 100644 --- a/content/sdk/20.go/02.api/01.accounts/08.smart-account-utils.md +++ b/content/sdk/20.go/02.api/01.accounts/08.smart-account-utils.md @@ -10,6 +10,100 @@ the ZKsync Era. ## Functions +### `PopulateTransactionECDSA` + +Populates missing properties meant for signing using an ECDSA private key: + +- Populates tx.From using the address derived from the ECDSA private key. +- Populates tx.Nonce via client.NonceAt(). +- Populates tx.Gas via client.EstimateGasL2(). If tx.From is not EOA, the estimation is done with address +derived from the ECDSA private key. +- Populates tx.GasFeeCap via client.SuggestGasPrice(). +- Populates tx.GasTipCap with 0 if is not set. +- Populates tx.ChainID via client.ChainID(). +- Populates tx.Data with "0x". +- Populates tx.Meta.GasPerPubdata with utils.DefaultGasPerPubdataLimit. + +Expects the secret to be ECDSA private in hex format. + +#### Inputs + +| Parameter | Type | Description | +|-----------|-----------------------------------------------------------------|------------------------------------| +| `ctx` | `context.Context` | Context. | +| `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be populated. | +| `secret` | `string` | The ECDSA private key. | +| `client` | [`*clients.BaseClient`](/sdk/go/api/clients/baseclient) | The client which fetches data from the network. | + +```go +var PopulateTransactionECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error +``` + +#### Examples + +```go +privateKey := os.Getenv("PRIVATE_KEY") +client, err := clients.DialBase(ZkSyncEraProvider) +if err != nil { + log.Panic(err) +} +defer client.Close() + +tx := zkTypes.Transaction712{ + To: &Address2, + Value: big.NewInt(7_000_000_000), + From: &Address1, +} + +err = accounts.PopulateTransactionECDSA(context.Background(), &tx, privateKey, client) +if err != nil { + log.Panic(err) +} +``` + +### `PopulateTransactionMultipleECDSA` + +Populates missing properties meant for signing using multiple ECDSA private keys. +It uses [`PopulateTransactionECDSA`](#populatetransactionecdsa), where the address of the first +ECDSA key is set as the secret argument. +Expects the secret to be a slice of ECDSA private in hex format. + +#### Inputs + +| Parameter | Type | Description | +|-----------|-----------------------------------------------------------------|-------------------------------------------------| +| `ctx` | `context.Context` | Context. | +| `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be populated. | +| `secret` | `[]string` | The list of the ECDSA private keys. | +| `client` | [`*clients.BaseClient`](/sdk/go/api/clients/baseclient) | The client which fetches data from the network. | + +```go +var PopulateTransactionMultipleECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error +``` + +#### Examples + +```go +privateKey1 := os.Getenv("PRIVATE_KEY1") +privateKey2 := os.Getenv("PRIVATE_KEY2") +client, err := clients.DialBase(ZkSyncEraProvider) +if err != nil { + log.Panic(err) +} +defer client.Close() + +tx := zkTypes.Transaction712{ + To: &Address2, + Value: big.NewInt(7_000_000_000), + From: &Address1, +} + +err = accounts.PopulateTransactionECDSA(context.Background(), &tx, privateKey, client) +if err != nil { + log.Panic(err) +} +``` + ### `SignPayloadWithECDSA` Implementation of [`PayloadSigner`](/sdk/go/api/accounts/types#payloadsigner) which signs the payload using @@ -283,97 +377,3 @@ if err != nil { log.Panic(err) } ``` - -### `PopulateTransactionECDSA` - -Populates missing properties meant for signing using an ECDSA private key: - -- Populates tx.From using the address derived from the ECDSA private key. -- Populates tx.Nonce via client.NonceAt(). -- Populates tx.Gas via client.EstimateGasL2(). If tx.From is not EOA, the estimation is done with address -derived from the ECDSA private key. -- Populates tx.GasFeeCap via client.SuggestGasPrice(). -- Populates tx.GasTipCap with 0 if is not set. -- Populates tx.ChainID via client.ChainID(). -- Populates tx.Data with "0x". -- Populates tx.Meta.GasPerPubdata with utils.DefaultGasPerPubdataLimit. - -Expects the secret to be ECDSA private in hex format. - -#### Inputs - -| Parameter | Type | Description | -|-----------|-----------------------------------------------------------------|------------------------------------| -| `ctx` | `context.Context` | Context. | -| `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be populated. | -| `secret` | `string` | The ECDSA private key. | -| `client` | [`*clients.BaseClient`](/sdk/go/api/clients/baseclient) | The client which fetches data from the network. | - -```go -var PopulateTransactionECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error -``` - -#### Examples - -```go -privateKey := os.Getenv("PRIVATE_KEY") -client, err := clients.DialBase(ZkSyncEraProvider) -if err != nil { - log.Panic(err) -} -defer client.Close() - -tx := zkTypes.Transaction712{ - To: &Address2, - Value: big.NewInt(7_000_000_000), - From: &Address1, -} - -err = accounts.PopulateTransactionECDSA(context.Background(), &tx, privateKey, client) -if err != nil { - log.Panic(err) -} -``` - -### `PopulateTransactionMultipleECDSA` - -Populates missing properties meant for signing using multiple ECDSA private keys. -It uses [`PopulateTransactionECDSA`](#populatetransactionecdsa), where the address of the first -ECDSA key is set as the secret argument. -Expects the secret to be a slice of ECDSA private in hex format. - -#### Inputs - -| Parameter | Type | Description | -|-----------|-----------------------------------------------------------------|-------------------------------------------------| -| `ctx` | `context.Context` | Context. | -| `tx` | [`*zkTypes.Transaction712`](/sdk/go/api/types#transaction712) | The transaction that needs to be populated. | -| `secret` | `[]string` | The list of the ECDSA private keys. | -| `client` | [`*clients.BaseClient`](/sdk/go/api/clients/baseclient) | The client which fetches data from the network. | - -```go -var PopulateTransactionMultipleECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error -``` - -#### Examples - -```go -privateKey1 := os.Getenv("PRIVATE_KEY1") -privateKey2 := os.Getenv("PRIVATE_KEY2") -client, err := clients.DialBase(ZkSyncEraProvider) -if err != nil { - log.Panic(err) -} -defer client.Close() - -tx := zkTypes.Transaction712{ - To: &Address2, - Value: big.NewInt(7_000_000_000), - From: &Address1, -} - -err = accounts.PopulateTransactionECDSA(context.Background(), &tx, privateKey, client) -if err != nil { - log.Panic(err) -} -``` diff --git a/content/sdk/20.go/02.api/01.accounts/09.types.md b/content/sdk/20.go/02.api/01.accounts/09.types.md index 9ea58ed8..125a1ac8 100644 --- a/content/sdk/20.go/02.api/01.accounts/09.types.md +++ b/content/sdk/20.go/02.api/01.accounts/09.types.md @@ -6,7 +6,6 @@ tags: ["zksync", "types", "go", "sdk", "accounts"] This section describes various types used in the ZKsync Era. These types are essential for interacting with the blockchain, performing transactions, and managing accounts. - ### `AllowanceParams` Contains the parameters required for approval of an ERC20 token. @@ -18,100 +17,86 @@ type AllowanceParams struct { } ``` -### `CallOpts` +### `CallMsg` -Is the collection of options to fine tune a contract call request from an account associated with -`AdapterL1`, `AdapterL2`, `Deployer` or `Adapter`. Its primary purpose is to be transformed into -`bind.CallOpts`, wherein the `From` field represents the associated account. +Contains parameters for contract call from an account associated with `AdapterL1`, `AdapterL2`, `Deployer` +or`Adapter`. Its primary purpose is to be transformed into [`types.CallMsg`](#callmsg), wherein the `From` +field represents the associated account. ```go -type CallOpts struct { - Pending bool // Whether to operate on the pending state or the last known one - BlockNumber *big.Int // Optional the block number on which the call should be performed - Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) +type CallMsg struct { + To *common.Address // The address of the recipient. + Gas uint64 // If 0, the call executes with near-infinite gas. + GasPrice *big.Int // Wei <-> gas exchange ratio. + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + GasTipCap *big.Int // EIP-1559 tip per gas. + Value *big.Int // Amount of wei sent along with the call. + Data []byte // Input data, usually an ABI-encoded contract method invocation + AccessList types.AccessList // EIP-2930 access list. + Meta *zkTypes.Eip712Meta // EIP-712 metadata. } + +func (m *CallMsg) ToCallMsg(from common.Address) zkTypes.CallMsg ``` -### `FullDepositFee` +### `CallOpts` -Represents the total ETH fee required for performing the deposit on both L1 and L2 networks. +Is the collection of options to fine tune a contract call request from an account associated with +`AdapterL1`, `AdapterL2`, `Deployer` or `Adapter`. Its primary purpose is to be transformed into +`bind.CallOpts`, wherein the `From` field represents the associated account. ```go -type FullDepositFee struct { - MaxFeePerGas, // MaxFeePerGas of the L1 transaction if 1559 transaction is used. - MaxPriorityFeePerGas, // MaxPriorityFeePerGas of the L1 transaction if 1559 transaction is used. - GasPrice, // Gas price of the L1 transaction if legacy transaction is used. - BaseCost, // Base cost of the L2 transaction. - L1GasLimit, // Gas limit of the L1 transaction. - L2GasLimit *big.Int // Gas limit of the L2 transaction. +type CallOpts struct { + Pending bool // Whether to operate on the pending state or the last known one + BlockNumber *big.Int // Optional the block number on which the call should be performed + Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) } ``` -### `CallMsg` +### `Create2Transaction` -Contains parameters for contract call from an account associated with `AdapterL1`, `AdapterL2`, `Deployer` -or`Adapter`. Its primary purpose is to be transformed into [`types.CallMsg`](#callmsg), wherein the `From` -field represents the associated account. +Represents the parameters for deploying a contract or account using the CREATE2 opcode. +This transaction is initiated by the account associated with `Deployer`. ```go -type CallMsg struct { - To *common.Address // The address of the recipient. - Gas uint64 // If 0, the call executes with near-infinite gas. - GasPrice *big.Int // Wei <-> gas exchange ratio. - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. - Value *big.Int // Amount of wei sent along with the call. - Data []byte // Input data, usually an ABI-encoded contract method invocation - AccessList types.AccessList // EIP-2930 access list. - Meta *zkTypes.Eip712Meta // EIP-712 metadata. +type Create2Transaction struct { + Bytecode []byte // The bytecode of smart contract or smart account. + Calldata []byte // The constructor calldata. + Salt []byte // The create2 salt. + Dependencies [][]byte // The bytecode of dependent smart contracts or smart accounts. + Auth *TransactOpts // Authorization data. } - -func (m *CallMsg) ToCallMsg(from common.Address) zkTypes.CallMsg + +func (t *Create2Transaction) ToTransaction(deploymentType DeploymentType) (*Transaction, error) ``` -### `WithdrawalCallMsg` +### `CreateTransaction` -Contains the common data required to execute a withdrawal call on L1 from L2. -This execution is initiated by the account associated with `AdapterL2` +Represents the parameters for deploying a contract or account using the CREATE opcode. +This transaction is initiated by the account associated with `Deployer`. ```go -type WithdrawalCallMsg struct { - To common.Address // The address of the recipient on L1. - Amount *big.Int // The amount of the token to transfer. - Token common.Address // The address of the token. ETH by default. - BridgeAddress *common.Address // The address of the bridge contract to be used. - - Gas uint64 // If 0, the call executes with near-infinite gas. - GasPrice *big.Int // Wei <-> gas exchange ratio. - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. - - AccessList types.AccessList // EIP-2930 access list. +type CreateTransaction struct { + Bytecode []byte // The bytecode of smart contract or smart account. + Calldata []byte // The constructor calldata. + Dependencies [][]byte // The bytecode of dependent smart contracts or smart accounts. + Auth *TransactOpts // Authorization data. } - -func (m *WithdrawalCallMsg) ToWithdrawalCallMsg(from common.Address) clients.WithdrawalCallMsg + +func (t *CreateTransaction) ToTransaction(deploymentType DeploymentType) (*Transaction, error) ``` -### `TransferCallMsg` +### `DeploymentType` -Contains the common data required to execute a transfer call on L2. -This execution is initiated by the account associated with `AdapterL2`. +Represents an enumeration of deployment types. ```go -type TransferCallMsg struct { - To common.Address // The address of the recipient. - Amount *big.Int // The amount of the token to transfer. - Token common.Address // The address of the token. ETH by default. - - Gas uint64 // If 0, the call executes with near-infinite gas. - GasPrice *big.Int // Wei <-> gas exchange ratio. - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. - - AccessList types.AccessList // EIP-2930 access list. -} - -func (m *TransferCallMsg) ToTransferCallMsg(from common.Address) clients.TransferCallMsg +type DeploymentType string + +const ( + DeployContract DeploymentType = "CONTRACT" + DeployAccount DeploymentType = "ACCOUNT" +) ``` ### `DepositCallMsg` @@ -121,43 +106,115 @@ This execution is initiated by the account associated with `AdapterL2`. ```go type DepositCallMsg struct { - To common.Address // The address that will receive the deposited tokens on L2. - Token common.Address // The address of the token to deposit. - Amount *big.Int // The amount of the token to be deposited. + To common.Address // The address that will receive the deposited tokens on L2. + Token common.Address // The address of the token to deposit. + Amount *big.Int // The amount of the token to be deposited. + + // If the ETH value passed with the transaction is not explicitly stated Value, + // this field will be equal to the tip the operator will receive on top of the base cost + // of the transaction. + OperatorTip *big.Int + + // The address of the bridge contract to be used. Defaults to the default ZKsync bridge + // (either L1EthBridge or L1Erc20Bridge). + BridgeAddress *common.Address + + L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. + + // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. + GasPerPubdataByte *big.Int + + // The address on L2 that will receive the refund for the transaction. + // If the transaction fails, it will also be the address to receive L2Value. + RefundRecipient common.Address + + CustomBridgeData []byte // Additional data that can be sent to a bridge. + + Value *big.Int // The amount of wei sent along with the call. + Gas uint64 // If 0, the call executes with near-infinite gas. + GasPrice *big.Int // Wei <-> gas exchange ratio. + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + GasTipCap *big.Int // EIP-1559 tip per gas. + + AccessList types.AccessList // EIP-2930 access list. +} + +func (m *DepositCallMsg) ToDepositTransaction() DepositTransaction +func (m *DepositCallMsg) ToRequestExecuteCallMsg() RequestExecuteCallMsg +func (m *DepositCallMsg) ToCallMsg(from, l1Bridge common.Address) (ethereum.CallMsg, error) +func (m *DepositCallMsg) ToTransactOpts() *TransactOpts +``` - // If the ETH value passed with the transaction is not explicitly stated Value, - // this field will be equal to the tip the operator will receive on top of the base cost - // of the transaction. - OperatorTip *big.Int +### `DepositTransaction` - // The address of the bridge contract to be used. Defaults to the default ZKsync bridge - // (either L1EthBridge or L1Erc20Bridge). - BridgeAddress *common.Address +Represents a deposit transaction on L2 from L1 initiated by the account associated with `AdapterL1`. - L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. +```go +type DepositTransaction struct { + To common.Address // The address of the token to deposit. + Token common.Address // The address of the token to deposit. + Amount *big.Int // The amount of the token to be deposited. + + // If the ETH value passed with the transaction is not explicitly stated Auth.Value, + // this field will be equal to the tip the operator will receive on top of the base cost + // of the transaction. + OperatorTip *big.Int + + // The address of the bridge contract to be used. Defaults to the default ZKsync bridge + // (either L1EthBridge or L1Erc20Bridge). + BridgeAddress *common.Address + + // Whether should the token approval be performed under the hood. Set this flag to true if you + // bridge an ERC20 token and didn't call the approveERC20 function beforehand. + ApproveERC20 bool + + // Whether should the base token approval be performed under the hood. Set this flag to true if you + // bridge an ERC20 token and didn't call the approveERC20 function beforehand. + ApproveBaseERC20 bool + + L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. + + // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. + GasPerPubdataByte *big.Int + + // The address on L2 that will receive the refund for the transaction. + // If the transaction fails, it will also be the address to receive L2Value. + RefundRecipient common.Address + + CustomBridgeData []byte // Additional data that can be sent to the bridge. + + ApproveAuth *TransactOpts // Authorization data for the token approval transaction. + ApproveBaseAuth *TransactOpts // Authorization data for the base token approval transaction. +} + +func (t *DepositTransaction) ToRequestExecuteTransaction() *RequestExecuteTransaction +func (t *DepositTransaction) ToDepositCallMsg(opts *TransactOpts) DepositCallMsg +func (t *DepositTransaction) PopulateEmptyFields(from common.Address) +``` - // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. - GasPerPubdataByte *big.Int +### `FullDepositFee` - // The address on L2 that will receive the refund for the transaction. - // If the transaction fails, it will also be the address to receive L2Value. - RefundRecipient common.Address +Represents the total ETH fee required for performing the deposit on both L1 and L2 networks. - CustomBridgeData []byte // Additional data that can be sent to a bridge. +```go +type FullDepositFee struct { + MaxFeePerGas, // MaxFeePerGas of the L1 transaction if 1559 transaction is used. + MaxPriorityFeePerGas, // MaxPriorityFeePerGas of the L1 transaction if 1559 transaction is used. + GasPrice, // Gas price of the L1 transaction if legacy transaction is used. + BaseCost, // Base cost of the L2 transaction. + L1GasLimit, // Gas limit of the L1 transaction. + L2GasLimit *big.Int // Gas limit of the L2 transaction. +} +``` - Value *big.Int // The amount of wei sent along with the call. - Gas uint64 // If 0, the call executes with near-infinite gas. - GasPrice *big.Int // Wei <-> gas exchange ratio. - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. +### `PayloadSigner` - AccessList types.AccessList // EIP-2930 access list. -} +Signs various types of payloads, optionally using a some kind of secret. +Returns the serialized signature. +The client is used to fetch data from the network if it is required for signing. -func (m *DepositCallMsg) ToDepositTransaction() DepositTransaction -func (m *DepositCallMsg) ToRequestExecuteCallMsg() RequestExecuteCallMsg -func (m *DepositCallMsg) ToCallMsg(from, l1Bridge common.Address) (ethereum.CallMsg, error) -func (m *DepositCallMsg) ToTransactOpts() *TransactOpts +```go +type PayloadSigner func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error) ``` ### `RequestExecuteCallMsg` @@ -167,34 +224,34 @@ This execution is initiated by the account associated with `AdapterL1`. ```go type RequestExecuteCallMsg struct { - ContractAddress common.Address // The L2 receiver address. - Calldata []byte // The input of the L2 transaction. - L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. + ContractAddress common.Address // The L2 receiver address. + Calldata []byte // The input of the L2 transaction. + L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. MintValue *big.Int // The amount of base token that needs to be minted on non-ETH-based L2. L2Value *big.Int // `msg.value` of L2 transaction. - FactoryDeps [][]byte // An array of L2 bytecodes that will be marked as known on L2. - - // If the ETH value passed with the transaction is not explicitly stated Value, - // this field will be equal to the tip the operator will receive on top of the base cost - // of the transaction. - OperatorTip *big.Int - - // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. - GasPerPubdataByte *big.Int - - // The address on L2 that will receive the refund for the transaction. - // If the transaction fails, it will also be the address to receive L2Value. - RefundRecipient common.Address - - Value *big.Int // The amount of wei sent along with the call. - Gas uint64 // If 0, the call executes with near-infinite gas. - GasPrice *big.Int // Wei <-> gas exchange ratio. - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. - - AccessList types.AccessList // EIP-2930 access list. + FactoryDeps [][]byte // An array of L2 bytecodes that will be marked as known on L2. + + // If the ETH value passed with the transaction is not explicitly stated Value, + // this field will be equal to the tip the operator will receive on top of the base cost + // of the transaction. + OperatorTip *big.Int + + // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. + GasPerPubdataByte *big.Int + + // The address on L2 that will receive the refund for the transaction. + // If the transaction fails, it will also be the address to receive L2Value. + RefundRecipient common.Address + + Value *big.Int // The amount of wei sent along with the call. + Gas uint64 // If 0, the call executes with near-infinite gas. + GasPrice *big.Int // Wei <-> gas exchange ratio. + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + GasTipCap *big.Int // EIP-1559 tip per gas. + + AccessList types.AccessList // EIP-2930 access list. } - + func (m *RequestExecuteCallMsg) ToRequestExecuteTransaction() RequestExecuteTransaction // Deprecated in favor of ToCallMsgWithChainID func (m *RequestExecuteCallMsg) ToCallMsg(from common.Address) (ethereum.CallMsg, error) @@ -202,25 +259,34 @@ func (m *RequestExecuteCallMsg) ToCallMsgWithChainID(from common.Address, chainI func (m *RequestExecuteCallMsg) ToTransactOpts() TransactOpts ``` -### `TransactOpts` +### `RequestExecuteTransaction` -Contains common data required to create a valid transaction on both L1 and L2 using the account -associated with `AdapterL1`, `AdapterL2` or `Deployer`. Its primary purpose is to be transformed into -[`bind.TransactOpts`](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.12.0/accounts/abi/bind#TransactOpts), -wherein the `From` and `Signer` fields are linked to the associated account. +Represents a request execution of L2 transaction from L1 initiated by the account associated with `AdapterL1`. ```go -type TransactOpts struct { - Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state). - Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds). - GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle). - GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle). - GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle). - GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate). - Context context.Context // Network context to support cancellation and timeouts (nil = no timeout). +type RequestExecuteTransaction struct { + ContractAddress common.Address // The L2 receiver address. + Calldata []byte // The input of the L2 transaction. + L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. + MintValue *big.Int // The amount of base token that needs to be minted on non-ETH-based L2. + L2Value *big.Int // `msg.value` of L2 transaction. + FactoryDeps [][]byte // An array of L2 bytecodes that will be marked as known on L2. + + // If the ETH value passed with the transaction is not explicitly stated Auth.Value, + // this field will be equal to the tip the operator will receive on top of the base cost + // of the transaction. + OperatorTip *big.Int + + // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. + GasPerPubdataByte *big.Int + + // The address on L2 that will receive the refund for the transaction. + // If the transaction fails, it will also be the address to receive L2Value. + RefundRecipient common.Address } - -func (t *TransactOpts) ToTransactOpts(from common.Address, signer bind.SignerFn) *bind.TransactOpts + +func (t *RequestExecuteTransaction) ToRequestExecuteCallMsg(opts *TransactOpts) RequestExecuteCallMsg +func (t *RequestExecuteTransaction) ToCallMsg(from common.Address, opts *TransactOpts) zkTypes.CallMsg ``` ### `Transaction` @@ -231,195 +297,128 @@ The From field is bound to the specific account, and thus, it is not included in ```go type Transaction struct { - To *common.Address // The address of the recipient. - Data hexutil.Bytes // Input data, usually an ABI-encoded contract method invocation. - Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds). - Nonce *big.Int // Nonce to use for the transaction execution. - GasTipCap *big.Int // EIP-1559 tip per gas. - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - Gas uint64 // Gas limit to set for the transaction execution. - - AccessList types.AccessList // EIP-2930 access list. - - ChainID *big.Int // Chain ID of the network. - Meta *zkTypes.Eip712Meta // EIP-712 metadata. + To *common.Address // The address of the recipient. + Data hexutil.Bytes // Input data, usually an ABI-encoded contract method invocation. + Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds). + Nonce *big.Int // Nonce to use for the transaction execution. + GasTipCap *big.Int // EIP-1559 tip per gas. + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + Gas uint64 // Gas limit to set for the transaction execution. + + AccessList types.AccessList // EIP-2930 access list. + + ChainID *big.Int // Chain ID of the network. + Meta *zkTypes.Eip712Meta // EIP-712 metadata. } - + func (t *Transaction) ToTransaction712(from common.Address) *zkTypes.Transaction712 func (t *Transaction) ToCallMsg(from common.Address) zkTypes.CallMsg ``` -### `TransferTransaction` +### `TransactionBuilder` -Represents a transfer transaction on L2 initiated by the account associated with `AdapterL2`. +Populates missing fields in a tx with default values. +The client is used to fetch data from the network if it is required. ```go -type TransferTransaction struct { - To common.Address // The address of the recipient. - Amount *big.Int // The amount of the token to transfer. - Token common.Address // The address of the token. ETH by default. -} - -func (t *TransferTransaction) ToTransaction(opts *TransactOpts) *Transaction -func (t *TransferTransaction) ToTransferCallMsg(from common.Address, opts *TransactOpts) clients.TransferCallMsg +type TransactionBuilder func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error ``` -### `WithdrawalTransaction` +### `TransactOpts` -Represents a withdrawal transaction on L1 from L2 initiated by the account associated with `AdapterL2`. +Contains common data required to create a valid transaction on both L1 and L2 using the account +associated with `AdapterL1`, `AdapterL2` or `Deployer`. Its primary purpose is to be transformed into +[`bind.TransactOpts`](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.12.0/accounts/abi/bind#TransactOpts), +wherein the `From` and `Signer` fields are linked to the associated account. ```go -type WithdrawalTransaction struct { - To common.Address // The address that will receive the withdrawn tokens on L1. - Token common.Address // The address of the token to withdraw. - Amount *big.Int // The amount of the token to withdraw. - - // The address of the bridge contract to be used. Defaults to the default ZKsync bridge - // (either L2EthBridge or L2Erc20Bridge). - BridgeAddress *common.Address +type TransactOpts struct { + Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state). + Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds). + GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle). + GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle). + GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle). + GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate). + Context context.Context // Network context to support cancellation and timeouts (nil = no timeout). } - -func (t *WithdrawalTransaction) ToWithdrawalCallMsg(from common.Address, opts *TransactOpts) *clients.WithdrawalCallMsg + +func (t *TransactOpts) ToTransactOpts(from common.Address, signer bind.SignerFn) *bind.TransactOpts ``` -### `RequestExecuteTransaction` +### `TransferCallMsg` -Represents a request execution of L2 transaction from L1 initiated by the account associated with `AdapterL1`. +Contains the common data required to execute a transfer call on L2. +This execution is initiated by the account associated with `AdapterL2`. ```go -type RequestExecuteTransaction struct { - ContractAddress common.Address // The L2 receiver address. - Calldata []byte // The input of the L2 transaction. - L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. - MintValue *big.Int // The amount of base token that needs to be minted on non-ETH-based L2. - L2Value *big.Int // `msg.value` of L2 transaction. - FactoryDeps [][]byte // An array of L2 bytecodes that will be marked as known on L2. - - // If the ETH value passed with the transaction is not explicitly stated Auth.Value, - // this field will be equal to the tip the operator will receive on top of the base cost - // of the transaction. - OperatorTip *big.Int - - // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. - GasPerPubdataByte *big.Int - - // The address on L2 that will receive the refund for the transaction. - // If the transaction fails, it will also be the address to receive L2Value. - RefundRecipient common.Address +type TransferCallMsg struct { + To common.Address // The address of the recipient. + Amount *big.Int // The amount of the token to transfer. + Token common.Address // The address of the token. ETH by default. + + Gas uint64 // If 0, the call executes with near-infinite gas. + GasPrice *big.Int // Wei <-> gas exchange ratio. + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + GasTipCap *big.Int // EIP-1559 tip per gas. + + AccessList types.AccessList // EIP-2930 access list. } - -func (t *RequestExecuteTransaction) ToRequestExecuteCallMsg(opts *TransactOpts) RequestExecuteCallMsg -func (t *RequestExecuteTransaction) ToCallMsg(from common.Address, opts *TransactOpts) zkTypes.CallMsg + +func (m *TransferCallMsg) ToTransferCallMsg(from common.Address) clients.TransferCallMsg ``` -### `DepositTransaction` +### `TransferTransaction` -Represents a deposit transaction on L2 from L1 initiated by the account associated with `AdapterL1`. +Represents a transfer transaction on L2 initiated by the account associated with `AdapterL2`. ```go -type DepositTransaction struct { - To common.Address // The address of the token to deposit. - Token common.Address // The address of the token to deposit. - Amount *big.Int // The amount of the token to be deposited. - - // If the ETH value passed with the transaction is not explicitly stated Auth.Value, - // this field will be equal to the tip the operator will receive on top of the base cost - // of the transaction. - OperatorTip *big.Int - - // The address of the bridge contract to be used. Defaults to the default ZKsync bridge - // (either L1EthBridge or L1Erc20Bridge). - BridgeAddress *common.Address - - // Whether should the token approval be performed under the hood. Set this flag to true if you - // bridge an ERC20 token and didn't call the approveERC20 function beforehand. - ApproveERC20 bool - - // Whether should the base token approval be performed under the hood. Set this flag to true if you - // bridge an ERC20 token and didn't call the approveERC20 function beforehand. - ApproveBaseERC20 bool - - L2GasLimit *big.Int // Maximum amount of L2 gas that transaction can consume during execution on L2. - - // The maximum amount L2 gas that the operator may charge the user for single byte of pubdata. - GasPerPubdataByte *big.Int - - // The address on L2 that will receive the refund for the transaction. - // If the transaction fails, it will also be the address to receive L2Value. - RefundRecipient common.Address - - CustomBridgeData []byte // Additional data that can be sent to the bridge. - - ApproveAuth *TransactOpts // Authorization data for the token approval transaction. - ApproveBaseAuth *TransactOpts // Authorization data for the base token approval transaction. +type TransferTransaction struct { + To common.Address // The address of the recipient. + Amount *big.Int // The amount of the token to transfer. + Token common.Address // The address of the token. ETH by default. } - -func (t *DepositTransaction) ToRequestExecuteTransaction() *RequestExecuteTransaction -func (t *DepositTransaction) ToDepositCallMsg(opts *TransactOpts) DepositCallMsg -func (t *DepositTransaction) PopulateEmptyFields(from common.Address) -``` - -### `DeploymentType` - -Represents an enumeration of deployment types. - -```go -type DeploymentType string - -const ( - DeployContract DeploymentType = "CONTRACT" - DeployAccount DeploymentType = "ACCOUNT" -) + +func (t *TransferTransaction) ToTransaction(opts *TransactOpts) *Transaction +func (t *TransferTransaction) ToTransferCallMsg(from common.Address, opts *TransactOpts) clients.TransferCallMsg ``` -### `CreateTransaction` +### `WithdrawalCallMsg` -Represents the parameters for deploying a contract or account using the CREATE opcode. -This transaction is initiated by the account associated with `Deployer`. +Contains the common data required to execute a withdrawal call on L1 from L2. +This execution is initiated by the account associated with `AdapterL2` ```go -type CreateTransaction struct { - Bytecode []byte // The bytecode of smart contract or smart account. - Calldata []byte // The constructor calldata. - Dependencies [][]byte // The bytecode of dependent smart contracts or smart accounts. - Auth *TransactOpts // Authorization data. +type WithdrawalCallMsg struct { + To common.Address // The address of the recipient on L1. + Amount *big.Int // The amount of the token to transfer. + Token common.Address // The address of the token. ETH by default. + BridgeAddress *common.Address // The address of the bridge contract to be used. + + Gas uint64 // If 0, the call executes with near-infinite gas. + GasPrice *big.Int // Wei <-> gas exchange ratio. + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + GasTipCap *big.Int // EIP-1559 tip per gas. + + AccessList types.AccessList // EIP-2930 access list. } - -func (t *CreateTransaction) ToTransaction(deploymentType DeploymentType) (*Transaction, error) + +func (m *WithdrawalCallMsg) ToWithdrawalCallMsg(from common.Address) clients.WithdrawalCallMsg ``` -### `Create2Transaction` +### `WithdrawalTransaction` -Represents the parameters for deploying a contract or account using the CREATE2 opcode. -This transaction is initiated by the account associated with `Deployer`. +Represents a withdrawal transaction on L1 from L2 initiated by the account associated with `AdapterL2`. ```go -type Create2Transaction struct { - Bytecode []byte // The bytecode of smart contract or smart account. - Calldata []byte // The constructor calldata. - Salt []byte // The create2 salt. - Dependencies [][]byte // The bytecode of dependent smart contracts or smart accounts. - Auth *TransactOpts // Authorization data. +type WithdrawalTransaction struct { + To common.Address // The address that will receive the withdrawn tokens on L1. + Token common.Address // The address of the token to withdraw. + Amount *big.Int // The amount of the token to withdraw. + + // The address of the bridge contract to be used. Defaults to the default ZKsync bridge + // (either L2EthBridge or L2Erc20Bridge). + BridgeAddress *common.Address } - -func (t *Create2Transaction) ToTransaction(deploymentType DeploymentType) (*Transaction, error) -``` - -### `PayloadSigner` - -Signs various types of payloads, optionally using a some kind of secret. -Returns the serialized signature. -The client is used to fetch data from the network if it is required for signing. - -```go -type PayloadSigner func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error) -``` - -### `TransactionBuilder` - -Populates missing fields in a tx with default values. -The client is used to fetch data from the network if it is required. - -```go -type TransactionBuilder func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error + +func (t *WithdrawalTransaction) ToWithdrawalCallMsg(from common.Address, opts *TransactOpts) *clients.WithdrawalCallMsg ``` diff --git a/content/sdk/30.python/02.api/00.providers/01.provider.md b/content/sdk/30.python/02.api/00.providers/01.provider.md index 26fb4ca2..c6f88a5d 100644 --- a/content/sdk/30.python/02.api/00.providers/01.provider.md +++ b/content/sdk/30.python/02.api/00.providers/01.provider.md @@ -194,7 +194,7 @@ Returns the L1 base token address. Calls the `zks_getBaseTokenL1Address` JSON-RPC method. -### Example +#### Example ```python from zksync2.module.module_builder import ZkSyncBuilder @@ -233,7 +233,7 @@ Returns the Bridgehub smart contract address. Calls the `zks_getBridgehubContract` JSON-RPC method. -### Example +#### Example ```python from zksync2.module.module_builder import ZkSyncBuilder @@ -259,7 +259,7 @@ Returns the transaction confirmation data that is part of `L2->L1` message. | `tx_hash` | `HexStr` | Hash of the L2 transaction where the withdrawal was initiated. | | `index` | `int` | In case there were multiple transactions in one message, you may pass an index of the transaction which confirmation data should be fetched. Defaults to 0 (optional). | -### Example +#### Example ```python from zksync2.module.module_builder import ZkSyncBuilder