Interacting with the blockchain with ethers.js
ethers.js is a JavaScript library that allows developers to interact with EVM-compatible blockchain networks.
You can use ethers.js to interact with smart contracts deployed on the Lisk network.
Install
To install ethers.js run the following command:
npm install --save ethers
Setup
Before you can start using ethers.js, you need to import it into your project.
Add the following line of code to the top of your file to import ethers.js:
const ethers = require('ethers');
Connecting to Lisk
You can connect to Lisk by instantiating a new ethers.js JsonRpcProvider
object with an RPC URL of the Lisk network:
- Lisk
- Lisk Sepolia
const ethers = require('ethers');
const url = 'https://rpc.api.lisk.com';
const provider = new ethers.JsonRpcProvider(url);
const ethers = require('ethers');
const url = 'https://rpc.sepolia-api.lisk.com';
const provider = new ethers.JsonRpcProvider(url);
A Provider (in ethers.js) is a class that provides an abstraction for a connection to the Ethereum Network. It provides read-only access to the Blockchain and its status.
Reading data from the blockchain
Once you have created a provider, you can use it to read data from the Lisk network.
For example, you can use the getBlockNumber
method to get the latest block:
async function getLatestBlock() {
const latestBlock = await provider.getBlockNumber();
console.log("The latest block's number is:", latestBlock);
}
getLatestBlock();
Complete code example
const ethers = require('ethers');
// For Lisk Sepolia network
const url = 'https://rpc.sepolia-api.lisk.com';
// For Lisk network
// const url = 'https://rpc.api.lisk.com';
const provider = new ethers.JsonRpcProvider(url);
async function getLatestBlock() {
const latestBlock = await provider.getBlockNumber();
console.log("The latest block's number is:", latestBlock);
}
getLatestBlock();
Writing data to the blockchain
In order to write data to the Lisk network, you need to create a Signer
.
A Signer is a class that (usually) in some way directly or indirectly has access to a private key, which can sign messages and transactions to authorize the network to charge your account ether to perform operations.
You can create a Signer
by instantiating a new ethers.js Wallet
object, providing it with a private key and Provider
.
const privateKey = 'PRIVATE_KEY';
const signer = new ethers.Wallet(privateKey, provider);
const receiver = '0x5e1A92F84cA1CE280B3Cb29d79C3368f45b41EBB';
// Send 0.01 ether to a given address.
async function sendTx(to) {
const tx = await signer.sendTransaction({
to: to,
value: ethers.parseEther("0.01")
});
console.log(tx);
}
//sendTx(receiver);
PRIVATE_KEY
is the private key of the account that is to be used when creating the signer
object.
The receiving account's balance will increment by 0.01
ETH once the transaction execution is successful.
Complete code example
const ethers = require('ethers');
// For Lisk Sepolia network
const url = 'https://rpc.sepolia-api.lisk.com';
// For Lisk network
// const url = 'https://rpc.api.lisk.com';
const provider = new ethers.JsonRpcProvider(url);
// Replace PRIVATE_KEY with the private key of your account.
const privateKey = 'PRIVATE_KEY';
const signer = new ethers.Wallet(privateKey, provider);
const receiver = '0x5e1A92F84cA1CE280B3Cb29d79C3368f45b41EBB';
// Send 0.01 ether to a given address.
async function sendTx(to) {
const tx = await signer.sendTransaction({
to: to,
value: ethers.parseEther("0.01")
});
console.log(tx);
}
sendTx(receiver);
Interacting with smart contracts
You can use ethers.js to interact with a smart contract on Lisk by instantiating a Contract
object using the ABI and address of a deployed contract:
The ABI of a contract can be found on the respective contract page in BlockScout.
For example, you can use the ABI for the Hello contract. Just scroll down to Contract ABI
and copy the deployed contract's ABI.
// Replace the contractAddress' value with the desired contract.
const contractAddress = "CONTRACT_ADDRESS"
// read-only
const contract = new ethers.Contract(contractAddress, abi, provider);
const abi = [
… // ABI of deployed contract
];
async function getHello() {
const value = await contract.message("0x3C46A11471f285E36EE8d089473ce98269D1b081");
console.log(value.toString());
}
getHello();
CONTRACT_ADDRESS
is the address of the deployed contract.
A Contract (in ethers.js) is an abstraction that represents a connection to a specific contract on the Lisk Network, so that applications can use it like a normal JavaScript object.
For reading and writing contracts, provide a Signer
object instead of a Provider
object:
// read & write
const contract = new ethers.Contract(contractAddress, abi, signer);
Once you have created a Contract
object, you can use it to call desired methods on the smart contract:
async function createHello(message) {
const tx = await contract.createHello(message);
return tx.hash;
}
//createHello("Hello Lisk!");
For an overview of existing public functions for the contract, please check the Read Contract and Write Contract tabs for the specific contract.
Complete code example
const ethers = require('ethers');
// For Lisk Sepolia network
const url = 'https://rpc.sepolia-api.lisk.com';
// For Lisk network
// const url = 'https://rpc.api.lisk.com';
const provider = new ethers.JsonRpcProvider(url);
const privateKey = 'PRIVATE_KEY';
const signer = new ethers.Wallet(privateKey, provider);
const contractAddress = "0xb18eb752813c2fbedfdf2be6e5e842a85a3b8539"
// Read & Write
const contract = new ethers.Contract(contractAddress, abi, signer);
// Read-only
//const contract = new ethers.Contract(contractAddress, abi, provider);
const abi = [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"indexed": false,
"internalType": "string",
"name": "message",
"type": "string"
}
],
"name": "NewHello",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "blacklist",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "counter",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_message",
"type": "string"
}
],
"name": "createHello",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "maxLength",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "message",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "minLength",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string[]",
"name": "_newBlackList",
"type": "string[]"
}
],
"name": "setBlacklist",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_newMin",
"type": "uint32"
},
{
"internalType": "uint32",
"name": "_newMax",
"type": "uint32"
}
],
"name": "setMinMaxMessageLength",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
async function createHello(message) {
const tx = await contract.createHello(message);
return tx.hash;
}
//createHello("Hello Lisk!");
async function getHello() {
const value = await contract.message("0x3C46A11471f285E36EE8d089473ce98269D1b081");
console.log(value.toString());
}
getHello();