Ethers.js JavaScript代码库¶
概览¶
Ethers.js代码库提供用户使用JavaScript与以太坊节点交互的多样工具,类似于Web3.js。Moonbeam拥有与以太坊相似的API供用户使用,其与以太坊风格的JSON-RPC调用完全兼容。因此,开发者可以利用此兼容特性并使用Ethers.js库与Moonbeam节点交互,与在以太坊操作相同。您可以在其官方文档获取更多关于如何使用Ethers.js的信息。
在本教程中,您将学习如何使用Ethers.js库在Moonbase Alpha上发送交易和部署合约。本教程也同样适用于Moonbeam,Moonriver,或是Moonbeam development node。
查看先决条件¶
在开始本教程示例之前,您将需要提前准备以下内容:
- 具有拥有一定数量资金的账户。 您可以每24小时一次从Moonbase Alpha水龙头上获取DEV代币以在Moonbase Alpha上进行测试
- 要在Moonbeam或Moonriver网络上测试本指南中的示例,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥
注意事项
本教程示例基于Ubuntu 22.04和MacOS的环境,用户需根据其所使用的Windows版本进行微调。
安装Ethers.js¶
首先,您需要开始一个基本的JavaScript项目。第一步,创建一个目录来存储您在本教程中将要生成的所有文件,并使用以下命令来初始化该文件夹:
mkdir ethers-examples && cd ethers-examples && npm init --y
在本教程中,您将需要安装Ethers.js代码库和Solidity编译器。您可以通过运行以下命令来安装两者的NPM安装包:
npm install ethers solc@0.8.0
yarn add ethers solc@0.8.0
设置Ethers提供商¶
在本教程中,您将会创建提供不同功能的脚本,如发送交易、部署合约以及与一个已部署合约交互。在大部分的脚本中,您需要创建一个Ethers提供者与网络交互。
要为Moonbeam或Moonriver网络配置您的项目,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。
为创建一个提供者,您可以遵循以下步骤:
- 导入
ethers
代码库 - 定义
providerRPC
标的,包括您希望在其上发送交易的网络配置。您将会需要包含网络的name
、rpc
和chainId
- 使用
ethers.JsonRpcProvider
函数创建provider
// 1. Import ethers
const ethers = require('ethers');
// 2. Define network configurations
const providerRPC = {
moonbeam: {
name: 'moonbeam',
rpc: 'INSERT_RPC_API_ENDPOINT', // Insert your RPC URL here
chainId: 1284, // 0x504 in hex,
},
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbeam.rpc, {
chainId: providerRPC.moonbeam.chainId,
name: providerRPC.moonbeam.name,
});
// 1. Import ethers
const ethers = require('ethers');
// 2. Define network configurations
const providerRPC = {
moonriver: {
name: 'moonriver',
rpc: 'INSERT_RPC_API_ENDPOINT', // Insert your RPC URL here
chainId: 1285, // 0x505 in hex,
},
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonriver.rpc, {
chainId: providerRPC.moonriver.chainId,
name: providerRPC.moonriver.name,
});
// 1. Import ethers
const ethers = require('ethers');
// 2. Define network configurations
const providerRPC = {
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287, // 0x507 in hex,
},
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
});
// 1. Import ethers
const ethers = require('ethers');
// 2. Define network configurations
const providerRPC = {
dev: {
name: 'moonbeam-development',
rpc: 'http://127.0.0.1:9944',
chainId: 1281, // 0x501 in hex,
},
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.dev.rpc, {
chainId: providerRPC.dev.chainId,
name: providerRPC.dev.name,
});
将此代码片段保存起来,因为您将在以下部分使用的脚本中用到它。
发送交易¶
在这一部分,您将需要创建一些脚本。第一个脚本将用于发送交易前检查账户余额。第二个脚本将执行交易。
您也可以在交易发送后,使用余额脚本查看账户余额。
查看余额脚本¶
您仅需要一个文件查看交易发送前后两个地址的余额。首先,您可以运行以下命令创建一个balances.js
文件:
touch balances.js
接下来,您将为此文件创建脚本并完成以下步骤:
- 设置Ethers提供者
- 定义
addressFrom
和addressTo
变量 - 创建打包了
provider.getBalance
函数的异步balances
函数 - 使用
provider.getBalance
函数获取addressFrom
和addressTo
地址的余额。您也可以使用ethers.formatEther
函数将余额转换成以DEV为单位的数字便于阅读 - 最后,运行
balances
函数
// 1. Add the Ethers provider logic here:
// {...}
// 2. Create address variables
const addressFrom = 'INSERT_FROM_ADDRESS';
const addressTo = 'INSERT_TO_ADDRESS';
// 3. Create balances function
const balances = async () => {
// 4. Fetch balances
const balanceFrom = ethers.formatEther(await provider.getBalance(addressFrom));
const balanceTo = ethers.formatEther(await provider.getBalance(addressTo));
console.log(`The balance of ${addressFrom} is: ${balanceFrom} DEV`);
console.log(`The balance of ${addressTo} is: ${balanceTo} DEV`);
};
// 5. Call the balances function
balances();
查看完整脚本
// Import ethers
const ethers = require('ethers');
// Define network configurations
const providerRPC = {
development: {
name: 'moonbeam-development',
rpc: 'http://localhost:9944',
chainId: 1281,
},
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
}); // Change to correct network
// Define addresses
const addressFrom = 'INSERT_FROM_ADDRESS';
const addressTo = 'INSERT_TO_ADDRESS';
// Create balances function
const balances = async () => {
// Fetch balances
const balanceFrom = ethers.formatEther(
await provider.getBalance(addressFrom)
);
const balanceTo = ethers.formatEther(await provider.getBalance(addressTo));
console.log(`The balance of ${addressFrom} is: ${balanceFrom} DEV`);
console.log(`The balance of ${addressTo} is: ${balanceTo} DEV`);
};
// Call the balances function
balances();
您可以运行以下命令以运行脚本并获取账户余额:
node balances.js
如果成功,发送地址和接收地址的余额将以DEV为单位显示在终端。
发送交易脚本¶
在本示例中,您将从拥有私钥的发送地址转移1个DEV Token至另一个地址。首先,您可以运行以下命令创建一个transaction.js
文件:
touch transaction.js
接下来,您将为此文件创建脚本并完成以下步骤:
- 设置Ethers提供者
- 定义
privateKey
和addressTo
变量。此处需要私钥以创建一个钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中 - 使用先前步骤中的
privateKey
和provider
创建一个钱包。此钱包实例将会被用于签署交易 - 创建打包了交易标的以及
wallet.sendTransaction
函数的异步send
函数 - 创建仅需要接受者地址以及发送数量的交易标的。注意,您可以使用
ethers.parseEther
,其能够处理Ether至Wei的必要单位换算,如同使用ethers.parseUnits(value, 'ether')
- 使用
wallet.sendTransaction
函数发送交易,然后使用await
等待交易处理完毕并返回交易回执 - 最后,运行
send
函数
// 1. Add the Ethers provider logic here:
// {...}
// 2. Create account variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const addressTo = 'INSERT_TO_ADDRESS';
// 3. Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 4. Create send function
const send = async () => {
console.log(`Attempting to send transaction from ${wallet.address} to ${addressTo}`);
// 5. Create tx object
const tx = {
to: addressTo,
value: ethers.parseEther('1'),
};
// 6. Sign and send tx - wait for receipt
const createReceipt = await wallet.sendTransaction(tx);
await createReceipt.wait();
console.log(`Transaction successful with hash: ${createReceipt.hash}`);
};
// 7. Call the send function
send();
查看完整脚本
// Import ethers
const ethers = require('ethers');
// Define network configurations
const providerRPC = {
development: {
name: 'moonbeam-development',
rpc: 'http://localhost:9944',
chainId: 1281,
},
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
}); // Change to correct network
// Define accounts and wallet
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const addressTo = 'INSERT_TO_ADDRESS';
const wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Create send function
const send = async () => {
console.log(
`Attempting to send transaction from ${wallet.address} to ${addressTo}`
);
// Create transaction
const tx = {
to: addressTo,
value: ethers.parseEther('1'),
};
// Send transaction and get hash
const createReceipt = await wallet.sendTransaction(tx);
await createReceipt.wait();
console.log(`Transaction successful with hash: ${createReceipt.hash}`);
};
// Call the send function
send();
您可以在终端运行以下命令以运行脚本:
node transaction.js
如果交易成功,您将在终端看到显示的交易哈希。
您也可以使用balances.js
脚本为发送地址和接收地址查看余额是否变化。整体操作流程如下所示:
部署合约¶
编译合约脚本¶
// 1. Import packages
const fs = require('fs');
const solc = require('solc');
// 2. Get path and load contract
const source = fs.readFileSync('Incrementer.sol', 'utf8');
// 3. Create input object
const input = {
language: 'Solidity',
sources: {
'Incrementer.sol': {
content: source,
},
},
settings: {
outputSelection: {
'*': {
'*': ['*'],
},
},
},
};
// 4. Compile the contract
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
const contractFile = tempFile.contracts['Incrementer.sol']['Incrementer'];
// 5. Export contract data
module.exports = contractFile;
部署合约脚本¶
有了用于编译Incrementer.sol
合约的脚本,您就可以使用这些结果发送部署的签名交易。首先,您可以为部署的脚本创建一个名为deploy.js
的文件:
touch deploy.js
接下来,您将为此文件创建脚本并完成以下步骤:
- 从
compile.js
导入合约文件 - 设置Ethers提供者
- 为初始账户定义
privateKey
,此私钥将用于创建一个钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中 - 使用先前步骤的
privateKey
和provider
创建钱包。此钱包实例将会被用于签署交易 - 加载已编译合约的合约
bytecode
和abi
- 使用
ethers.ContractFactory
函数创建具有签名者的合约实例,提供abi
、bytecode
以及wallet
参数 - 创建用于部署合约的异步
deploy
函数 - 在
deploy
函数中,使用incrementer
合约实例以连接deploy
并输入初始数值。在本示例中,您可以将初始值设置为5
。这将会为交易部署传送交易,您可以使用合约部署交易的deployed
以等待交易记录 - 最后,运行
deploy
函数
// 1. Import the contract file
const contractFile = require('./compile');
// 2. Add the Ethers provider logic here:
// {...}
// 3. Create account variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
// 4. Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 5. Load contract information
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;
// 6. Create contract instance with signer
const incrementer = new ethers.ContractFactory(abi, bytecode, wallet);
// 7. Create deploy function
const deploy = async () => {
console.log(`Attempting to deploy from account: ${wallet.address}`);
// 8. Send tx (initial value set to 5) and wait for receipt
const contract = await incrementer.deploy(5);
const txReceipt = await contract.deploymentTransaction().wait();
console.log(`Contract deployed at address: ${txReceipt.contractAddress}`);
};
// 9. Call the deploy function
deploy();
查看完整脚本
// Import ethers and compile
const ethers = require('ethers');
const contractFile = require('./compile');
// Define network configurations
const providerRPC = {
development: {
name: 'moonbeam-development',
rpc: 'http://localhost:9944',
chainId: 1281,
},
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
}); // Change to correct network
// Define accounts and wallet
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Load contract info
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;
// Create contract instance with signer
const incrementer = new ethers.ContractFactory(abi, bytecode, wallet);
// Create deploy function
const deploy = async () => {
console.log(`Attempting to deploy from account: ${wallet.address}`);
// Send tx (initial value set to 5) and wait for receipt
const contract = await incrementer.deploy(5);
const txReceipt = await contract.deploymentTransaction().wait();
console.log(`Contract deployed at address: ${txReceipt.contractAddress}`);
};
// Call the deploy function
deploy();
您可以在终端运行以下命令以运行脚本:
node deploy.js
如果成功,合约地址将显示在终端。
读取合约数据(调用函数)¶
调用函数是无需修改合约存储(更改变量)的交互类型,这意味着无需发送交易,只需读取已部署合约的各种存储变量。
首先,您需要创建一个文件并命名为get.js
:
touch get.js
接下来,您可以遵循以下步骤创建脚本:
- 从
compile.js
文件导入abi
- 设置Ethers提供者
- 使用已部署合约的地址创建
contractAddress
变量 - 使用
ethers.Contract
函数并传入contractAddress
、abi
和provider
以创建合约实例 - 创建异步
get
函数 - 使用合约实例以调用其中一个合约函数并输入任何需要的信息。在本示例中,您将调用
number
函数(此函数无需任何输入)。您可以使用await
,这将在请求解决后返回请求的数值 - 最后,运行
get
函数
// 1. Import the ABI
const { abi } = require('./compile');
// 2. Add the Ethers provider logic here:
// {...}
// 3. Contract address variable
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// 4. Create contract instance
const incrementer = new ethers.Contract(contractAddress, abi, provider);
// 5. Create get function
const get = async () => {
console.log(`Making a call to contract at address: ${contractAddress}`);
// 6. Call contract
const data = await incrementer.number();
console.log(`The current number stored is: ${data}`);
};
// 7. Call get function
get();
查看完整脚本
// Import ethers and compile
const ethers = require('ethers');
const { abi } = require('./compile');
// Define network configurations
const providerRPC = {
development: {
name: 'moonbeam-development',
rpc: 'http://localhost:9944',
chainId: 1281,
},
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287,
},
};
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
}); // Change to correct network
// Contract address variable
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// Create contract instance
const incrementer = new ethers.Contract(contractAddress, abi, provider);
// Create get function
const get = async () => {
console.log(`Making a call to contract at address: ${contractAddress}`);
// Call contract
const data = await incrementer.number();
console.log(`The current number stored is: ${data}`);
};
// Call get function
get();
您可以在终端运行以下命令以运行脚本:
node get.js
如果成功,数值将显示在终端。
交互合约(发送函数)¶
发送函数是修改合约存储(更改变量)的交互类型,这意味着需要签署和发送交易。在这一部分,您将创建两个脚本:一个是增量,另一个是重置增量器。首先,您可以为每个脚本创建一个文件,并分别命名为increment.js
和reset.js
:
touch increment.js reset.js
接下来,打开increment.js
文件并执行以下步骤以创建脚本:
- 从
compile.js
文件导入abi
- 设置Ethers提供者
- 为初始账户定义
privateKey
、已部署合约的contractAddress
以及要增量的_value
。此处的私钥将用于创建钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中 - 使用先前步骤中的
privateKey
和provider
创建钱包,钱包实例将用于传送交易 - 使用
ethers.Contract
函数并输入contractAddress
、abi
和provider
以创建合约实例 - 使用异步
increment
函数 - 使用合约实例以调用其中一个合约函数并输入任何需要的信息。在本示例中,您将调用
increment
函数(此函数无需任何输入)。您可以使用await
,这将在请求解决后返回请求的数值 - 最后,运行
increment
函数
// 1. Import the contract ABI
const { abi } = require('./compile');
// 2. Add the Ethers provider logic here:
// {...}
// 3. Create variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const _value = 3;
// 4. Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 5. Create contract instance with signer
const incrementer = new ethers.Contract(contractAddress, abi, wallet);
// 6. Create increment function
const increment = async () => {
console.log(
`Calling the increment by ${_value} function in contract at address: ${contractAddress}`
);
// 7. Sign and send tx and wait for receipt
const createReceipt = await incrementer.increment(_value);
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// 8. Call the increment function
increment();
查看完整脚本
// Import ethers and compile
const ethers = require('ethers');
const { abi } = require('./compile');
// Define network configurations
const providerRPC = {
development: {
name: 'moonbeam-development',
rpc: 'http://localhost:9944',
chainId: 1281,
},
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
}); // Change to correct network
// Create variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const _value = 3;
// Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Create contract instance with signer
const incrementer = new ethers.Contract(contractAddress, abi, wallet);
// Create reset function
const increment = async () => {
console.log(
`Calling the increment by ${_value} function in contract at address: ${contractAddress}`
);
// Sign and send tx and wait for receipt
const createReceipt = await incrementer.increment(_value);
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// Call the reset function
increment();
您可以在终端运行以下命令以运行脚本:
node increment.js
如果成功,交易哈希将显示在终端。您可以在increment.js
脚本旁边使用get.js
脚本以确保数值如预期变化:
接下来,您可以打开reset.js
文件并执行以下步骤以创建脚本:
- 从
compile.js
文件导入abi
- 设置Ethers提供者
- 为初始地址和已部署合约的
contractAddress
定义privateKey
,此处私钥用于创建一个钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中 - 使用先前步骤的
privateKey
和provider
创建一个钱包,此钱包实例将用于签署交易 - 使用
ethers.Contract
函数并输入contractAddress
、abi
和provider
以创建合约实例 - 创建异步
reset
函数 - 使用合约实例以调用其中一个合约函数并输入任何需要的信息。在本示例中,您将调用
reset
函数(此函数无需任何输入)。您可以使用await
,这将在请求解决后返回请求的数值 - 最后,运行
reset
函数
// 1. Import the contract ABI
const { abi } = require('./compile');
// 2. Add the Ethers provider logic here:
// {...}
// 3. Create variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// 4. Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 5. Create contract instance with signer
const incrementer = new ethers.Contract(contractAddress, abi, wallet);
// 6. Create reset function
const reset = async () => {
console.log(
`Calling the reset function in contract at address: ${contractAddress}`
);
// 7. sign and send tx and wait for receipt
const createReceipt = await incrementer.reset();
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// 8. Call the reset function
reset();
查看完整脚本
// Import ethers and compile
const ethers = require('ethers');
const { abi } = require('./compile');
// Define network configurations
const providerRPC = {
development: {
name: 'moonbeam-development',
rpc: 'http://localhost:9944',
chainId: 1281,
},
moonbase: {
name: 'moonbase-alpha',
rpc: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
}); // Change to correct network
// Create variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Create contract instance with signer
const incrementer = new ethers.Contract(contractAddress, abi, wallet);
// Create reset function
const reset = async () => {
console.log(
`Calling the reset function in contract at address: ${contractAddress}`
);
// Sign and send tx and wait for receipt
const createReceipt = await incrementer.reset();
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// Call the reset function
reset();
您可以在终端运行以下命令以运行脚本:
node reset.js
如果成功,交易哈希将显示在终端。您可以在reset.js
脚本配合使用get.js
脚本以确保数值如预期变化: