Skip to content

Ethers.js JavaScript代码库

Intro diagram

概览

ethers.js代码库提供用户使用JavaScript与以太坊节点交互的多样工具,类似于web3.js。Moonbeam拥有与以太坊相似的API供用户使用,其与以太坊风格的JSON RPC调用完全兼容。因此,开发者可以利用此兼容特性并使用ether.js库与Moonbeam节点交互,与在以太坊操作相同。您可以在此博客文章了解更多关于ether.js的信息。

在本教程中,您将学习如何使用ethers.js库在Moonbase Alpha上发送交易和部署合约。本教程也同样适用于MoonbeamMoonriver,或是Moonbeam development node

查看先决条件

在开始本教程示例之前,您将需要提前准备以下内容:

  • 具有拥有一定数量资金的账户。 您可以每24小时一次从Moonbase Alpha水龙头上获取DEV代币以在Moonbase Alpha上进行测试
  • 要在Moonbeam或Moonriver网络上测试本指南中的示例,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。

注意事项

本教程示例基于Ubuntu 18.04和MacOS的环境,用户需根据其所使用的Windows版本进行微调。

创建一个JavaScript项目

首先,您需要创建一个目录,以存储您在本教程中将要创建的所有文件:

mkdir ethers-examples && cd ethers-examples

在本教程中,您将需要安装ether.js代码库和Solidity编译器。您可以通过运行以下命令来安装两者的NPM安装包:

npm install ethers solc@0.8.0

设置Ehters提供商

在本教程中,您将会创建提供不同功能的脚本,如发送交易、部署合约以及与一个已部署合约交互。在大部分的脚本中,您需要创建一个Ethers提供者与网络交互。

要为Moonbeam或Moonriver网络配置您的项目,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。

为创建一个提供者,您可以遵循以下步骤:

  1. 导入ethers代码库

  2. 定义providerRPC标的,包括您希望在其上发送交易的网络配置。您将会需要包含网络的namerpcchainId

  3. 使用ethers.providers.StaticJsonRpcProvider函数创建provider 。除此之外,您也可以使用ethers.providers.JsonRpcProvide(providerRPC)函数,其仅需要提供者RPC端点的地址。此操作可能因为个别项目规格而存在兼容性问题

// 1. Import ethers
const ethers = require('ethers');

// 2. Define network configurations
const providerRPC = {
  moonbeam: {
    name: 'moonbeam',
    rpc: 'RPC-API-ENDPOINT-HERE', // Insert your RPC URL here
    chainId: 1284, // 0x504 in hex,
  },
};
// 3. Create ethers provider
const provider = new ethers.providers.StaticJsonRpcProvider(
  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: 'RPC-API-ENDPOINT-HERE', // Insert your RPC URL here
    chainId: 1285, // 0x505 in hex,
  },
};
// 3. Create ethers provider
const provider = new ethers.providers.StaticJsonRpcProvider(
  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.providers.StaticJsonRpcProvider(
  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:9933',
    chainId: 1281, // 0x501 in hex,
  },
};
// 3. Create ethers provider
const provider = new ethers.providers.StaticJsonRpcProvider(
  providerRPC.dev.rpc, 
  {
    chainId: providerRPC.dev.chainId,
    name: providerRPC.dev.name,
  }
);

发送交易

在这一部分,您将需要创建一些脚本。第一个脚本将用于发送交易前检查账户余额。第二个脚本将执行交易。

您也可以在交易发送后,使用余额脚本查看账户余额。

查看余额脚本

您仅需要一个文件查看交易发送前后两个地址的余额。首先,您可以运行以下命令创建一个balances.js文件:

touch balances.js

接下来,您将为此文件创建脚本并完成以下步骤:

  1. 设置Ethers提供者

  2. 定义addressFromaddressTo变量

  3. 创建打包了provider.getBalance函数的异步balances函数

  4. 使用provider.getBalance函数获取addressFromaddressTo地址的余额。您也可以使用eths.utils.formatEther函数将余额转换成以ETH为单位的数字便于阅读

  5. 最后,运行balances函数

// 1. Add the Ethers provider logic here:
// {...}

// 2. Create address variables
const addressFrom = 'ADDRESS-FROM-HERE';
const addressTo = 'ADDRESS-TO-HERE';

// 3. Create balances function
const balances = async () => {
  // 4. Fetch balances
  const balanceFrom = ethers.utils.formatEther(await provider.getBalance(addressFrom));
  const balanceTo = ethers.utils.formatEther(await provider.getBalance(addressTo));

  console.log(`The balance of ${addressFrom} is: ${balanceFrom} ETH`);
  console.log(`The balance of ${addressTo} is: ${balanceTo} ETH`);
};

// 5. Call the balances function
balances();

您可以查看GitHub上的完整脚本

您可以运行以下命令以运行脚本并获取账户余额:

node balances.js

如果成功,发送地址和接收地址的余额将以ETH为单位显示在终端。

发送交易脚本

在本示例中,您将从拥有私钥的发送地址转移1个DEV Token至另一个地址。首先,您可以运行以下命令创建一个transaction.js文件:

touch transaction.js

接下来,您将为此文件创建脚本并完成以下步骤:

  1. 设置Ethers提供者

  2. 定义privateKeyaddressTo变量。此处需要私钥以创建一个钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中

  3. 使用先前步骤中的privateKeyprovider创建一个钱包。此钱包实例将会被用于签署交易

  4. 创建打包了交易标的以及wallet.sendTransaction函数的异步send函数

  5. 创建仅需要接受者地址以及发送数量的交易标的。注意,您可以使用ethers.utils.parseEther,其能够处理Ether至Wei的必要单位换算,如同使用ethers.utils.parseUnits(value, 'ether')

  6. 使用wallet.sendTransaction函数发送交易,然后使用await等待交易处理完毕并返回交易回执

  7. 最后,运行send函数

// 1. Add the Ethers provider logic here:
// {...}

// 2. Create account variables
const account_from = {
  privateKey: 'YOUR-PRIVATE-KEY-HERE',
};
const addressTo = 'ADDRESS-TO-HERE';

// 3. Create wallet
let wallet = new ethers.Wallet(account_from.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.utils.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();

您可以查看GitHub上的完整脚本

您可以在终端运行以下命令以运行脚本:

node transaction.js

如果交易成功,您将在终端看到显示的交易哈希。

您也可以使用balances.js脚本为发送地址和接收地址查看余额是否变化。整体操作流程如下所示:

Send Tx Etherjs

部署合约

在下几个部分中您将要编译和部署的合约是一个简单的增量合约,命名为_Incrementer.sol_。您可以先为合约创建一个文件:

touch Incrementer.sol

接下来,您可以添加Solidity代码至文件:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Incrementer {
    uint256 public number;

    constructor(uint256 _initialNumber) {
        number = _initialNumber;
    }

    function increment(uint256 _value) public {
        number = number + _value;
    }

    function reset() public {
        number = 0;
    }
}

constructor函数将在合约部署时运行,设置存储在链上的数字变量的初始值(默认值为0)。increment函数将提供的_value添加至当前数字,但是需要发送一个交易以修改存储的数据。最后,reset函数将存储的数值重置为零。

注意事项

此合约为简单示例,仅供演示使用,其数值无实际意义。

编译合约脚本

在这一部分,您将创建一个脚本,该脚本使用Solidity编译器为Incrementer.sol合约输出字节码和接口(ABI)。首先,您可以通过运行以下命令创建一个compile.js文件:

touch compile.js

接下来,您将为此文件创建脚本,并执行以下步骤:

  1. 导入fssolc安装包

  2. 使用fs.readFileSync函数,您将读取Incrementer.sol的文件内容并保存至source

  3. 通过指定要使用的languagesourcessettings为Solidity编译器构建input对象

  4. 通过input对象,您可以使用solc.compile编译合约

  5. 提取已编译的合约文件并导出以在部署脚本中使用

// 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

接下来,您将为此文件创建脚本并完成以下步骤:

  1. compile.js导入合约文件

  2. 设置Ethers提供者

  3. 为初始账户定义privateKey ,此私钥将用于创建一个钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中

  4. 为已编译合约储存bytecodeabi

  5. 使用先前步骤的privateKeyprovider创建钱包。此钱包实例将会被用于签署交易

  6. 使用ethers.ContractFactory函数创建具有签名者的合约实例,提供abibytecode以及wallet参数

  7. 创建用于部署合约的异步deploy函数

  8. deploy函数中,使用incrementer合约实例以连接deploy并输入初始数值。在本示例中,您可以将初始值设置为5。这将会为交易部署传送交易,您可以使用合约部署交易的deployed以等待交易记录

  9. 最后,运行deploy函数

// 1. Import the contract file
const contractFile = require('./compile');

// 2. Add the Ethers provider logic here:
// {...}

// 3. Create account variables
const account_from = {
  privateKey: 'YOUR-PRIVATE-KEY-HERE',
};

// 4. Save the bytecode and ABI
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;

// 5. Create wallet
let wallet = new ethers.Wallet(account_from.privateKey, provider);

// 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]);
  await contract.deployed();

  console.log(`Contract deployed at address: ${contract.address}`);
};

// 9. Call the deploy function
deploy();

您可以查看GitHub上的完整脚本

您可以在终端运行以下命令以运行脚本:

node deploy.js

如果成功,合约地址将显示在终端。

Deploy Contract Etherjs

读取合约数据(调用函数)

调用函数是无需修改合约存储(更改变量)的交互类型,这意味着无需发送交易,只需读取已部署合约的各种存储变量。

首先,您需要创建一个文件并命名为get.js

touch get.js

接下来,您可以遵循以下步骤创建脚本:

  1. compile.js文件导入abi

  2. 设置Ethers提供者

  3. 使用已部署合约的地址创建contractAddress变量

  4. 使用ethers.Contract函数并传入contractAddressabiprovider以创建合约实例

  5. 创建异步get函数

  6. 使用合约实例以调用其中一个合约函数并输入任何需要的信息。在本示例中,您将调用number函数(此函数无需任何输入)。您可以使用await,这将在请求解决后返回请求的数值

  7. 最后,运行get函数

// 1. Import the ABI
const { abi } = require('./compile');

// 2. Add the Ethers provider logic here:
// {...}

// 3. Contract address variable
const contractAddress = 'CONTRACT-ADDRESS-HERE';

// 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();

您可以查看GitHub上的完整脚本

您可以在终端运行以下命令以运行脚本:

node get.js

如果成功,数值将显示在终端。

交互合约(发送函数){: #interact-with-contract }

发送函数是修改合约存储(更改变量)的交互类型,这意味着需要签署和发送交易。在这一部分,您将创建两个脚本:一个是增量,另一个是重置增量器。首先,您可以为每个脚本创建一个文件,并分别命名为increment.jsreset.js

touch increment.js reset.js

接下来,打开increment.js文件并执行以下步骤以创建脚本:

  1. compile.js文件导入abi

  2. 设置Ethers提供者

  3. 为初始账户定义privateKey、已部署合约的contractAddress以及要增量的_value。此处的私钥将用于创建钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中

  4. 使用先前步骤中的privateKeyprovider创建钱包,钱包实例将用于传送交易

  5. 使用ethers.Contract函数并输入contractAddressabiprovider以创建合约实例

  6. 使用异步increment函数

  7. 使用合约实例以调用其中一个合约函数并输入任何需要的信息。在本示例中,您将调用increment函数(此函数无需任何输入)。您可以使用await,这将在请求解决后返回请求的数值

  8. 最后,运行increment函数

// 1. Import the contract ABI
const { abi } = require('./compile');

// 2. Add the Ethers provider logic here:
// {...}

// 3. Create variables
const account_from = {
  privateKey: 'YOUR-PRIVATE-KEY-HERE',
};
const contractAddress = 'CONTRACT-ADDRESS-HERE';
const _value = 3;

// 4. Create wallet
let wallet = new ethers.Wallet(account_from.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();

您可以查看GitHub上的完整脚本

您可以在终端运行以下命令以运行脚本:

node increment.js

如果成功,交易哈希将显示在终端。您可以在increment.js脚本旁边使用get.js脚本以确保数值如预期变化:

Increment Contract Ethers

接下来,您可以打开reset.js文件并执行以下步骤以创建脚本:

  1. compile.js文件导入abi

  2. 设置Ethers提供者

  3. 为初始地址和已部署合约的contractAddress定义privateKey ,此处私钥用于创建一个钱包实例。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在JavaScript文件中

  4. 使用先前步骤的privateKeyprovider创建一个钱包,此钱包实例将用于签署交易

  5. 使用ethers.Contract 函数并输入contractAddressabiprovider以创建合约实例

  6. 创建异步reset函数

  7. 使用合约实例以调用其中一个合约函数并输入任何需要的信息。在本示例中,您将调用reset函数(此函数无需任何输入)。您可以使用await,这将在请求解决后返回请求的数值

  8. 最后,运行reset函数

// 1. Import the contract ABI
const { abi } = require('./compile');

// 2. Add the Ethers provider logic here:
// {...}

// 3. Create variables
const account_from = {
  privateKey: 'YOUR-PRIVATE-KEY-HERE',
};
const contractAddress = 'CONTRACT-ADDRESS-HERE';

// 4. Create wallet
let wallet = new ethers.Wallet(account_from.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();

您可以查看在GitHub上的完整脚本

您可以在终端运行以下命令以运行脚本:

node reset.js

如果成功,交易哈希将显示在终端。您可以在reset.js脚本配合使用get.js脚本以确保数值如预期变化:

Reset Contract Ethers

本网站的所有信息由第三方提供,仅供参考之用。Moonbeam Foundation不保证网站信息的准确性、完整性或真实性。如使用或依赖本网站信息,需自行承担相关风险,Moonbeam Foundation不承担任何责任和义务。这些材料的所有陈述和/或意见由提供方个人或实体负责,与Moonbeam Foundation立场无关,概不构成任何投资建议。对于任何特定事项或情况,应寻求专业权威人士的建议。此处的信息可能会包含或链接至第三方提供的信息与/或第三方服务(包括任何第三方网站等)。这类链接网站不受Moonbeam Foundation控制。Moonbeam Foundation对此类链接网站的内容(包括此类链接网站上包含的任何信息或资料)概不负责也不认可。这些链接内容仅为方便访客而提供,Moonbeam Foundation对因您使用此信息或任何第三方网站或服务提供的信息而产生的所有责任概不负责。