Skip to main content

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

📋Prerequisites

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.

💡Crafting burn and transfer assets
The Immutable SDK provides contract interfaces for Crafting, burning and transfer of assets that you could use directly. This guide is intended to show you how to interact with any general contract via ethers.js.
  1. 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,
);
  1. 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,
);