Send your first transaction
This page guides you through the process of sending a transaction to the zkEVM network with ethers.js and Passport zkEVM provider.
Pre-requisites
- Have the Passport module installed and initalised
- Install (ethers.js)
npm install ethers
(Here we use ethers v5)
Scenario
In this scenario, we will be sending a transaction to the zkEVM network that will transfer an ERC-721 token.
Ethers provides an helper class called Contract
that allows us to interact with smart contracts
by abstracting away data-encoding using the contract ABI (definition of the contract's interface).
Read more about ABI Formats, here we use the human readable format.
- Create a new contract instance
The first step is to create a new instance of the contract that we want to interact with. In this example, we will be using the ERC-721 interface
import { ethers } from 'ethers';
const provider = passport.connectEvm();
const signer = provider.getSigner();
const userAddress = await signer.getAddress();
const toAddress = '<address to transfer the token to>';
const erc721ContractAddress = '<address of the ERC-721 contract>';
const tokenId = 1234;
// Construct the contract interface using the ABI
const contract = new ethers.Contract(
erc721ContractAddress,
[
'function safeTransferFrom(address from, address to, uint256 tokenId)',
],
signer,
);
- Then call the contract method
const tx = await contract.safeTransferFrom(
userAddress,
toAddress,
tokenId,
);
// Wait for the transaction to complete
await tx.wait();
Under the hood, ethers will build a eth_sendTransaction
RPC call to the Passport provider.
{
"data": "0x42842e0e...the rest of encoded the data",
"to": "<address of the ERC-721 contract>",
"from": "<your wallet address>"
}
Working with Typescript
Constructing the contract interface using the ABI is not type-safe. To make it type-safe, we can use Typechain to generate typescript interfaces from the contract ABI.
The contract ABI could be stored or exported to a file and then used to generate the typescript interfaces.
typechain --target=ethers-v5 -out-dir=app/contracts abis/ERC721.json
The generated code includes a contract factory that can be used to create a contract instance.
import { ethers } from 'ethers';
import { ERC721_factory, ERC721 } from './contracts';
const provider = passport.connectEvm();
const signer = provider.getSigner();
const userAddress = await signer.getAddress();
const toAddress = '<address to transfer the token to>';
const erc721ContractAddress = '<address of the ERC-721 contract>';
// Create a new instance of the contract
const contract: ERC721 = ERC721_factory.connect(
erc721ContractAddress,
signer,
);
// Call the contract method, the arguments are now type-safe
const tx = await contract.safeTransferFrom(
userAddress,
toAddress,
tokenId,
);