苏泽
大家好 这里是苏泽 一个钟爱区块链技术的后端开发者
本篇专栏++←++持续记录本人自学智能合约学习笔记和经验总结 如果喜欢拜托三连支持~
目录
Ethers极简入门教程:HelloVitalik(非小白可跳)
简介
在以太坊生态系统中,ERC20 代币是最常见的一种代币标准。ERC20 代币基于智能合约构建,可以在以太坊网络上进行转账和查询余额。
在本文中,我们将使用 ethers.js 库实现与 ERC20 合约进行交互的功能,包括转账代币和查询余额等操作。
前景科普-ERC20
ERC20代币是符合以太坊请求评论20(Ethereum Request for Comments 20,简称ERC20)标准的代币。ERC20是一种协议标准,定义了代币在以太坊区块链上必须实现的一系列规则和功能,以确保不同代币之间的兼容性和互操作性
Ethers极简入门教程:HelloVitalik(非小白可跳)
教程概览
- 工具与环境 :我们将使用
VScode
作为开发工具,并通过npm
安装ethers
库。 - 在线编辑器 :介绍使用
playcode
在线编译JavaScript代码。 - 程序示例 :编写
HelloVitalik
程序,查询Vitalik的ETH余额。
开发工具
VScode(推荐)
使用本地VScode
进行开发,安装Node.js后,通过npm安装ethers
库:
javascript
npm install ethers --save
HelloVitalik程序
导入ethers
库
javascript
import { ethers } from "ethers";
连接以太坊网络
使用Provider
类连接以太坊网络:
javascript
const provider = ethers.getDefaultProvider();
编写异步函数
使用async/await
语法编写异步函数,与区块链进行交互:
javascript
const main = async () => {
// ...
};
main();
获取Vitalik的ETH余额
利用Provider
类的getBalance()
函数查询Vitalik的ETH余额:
javascript
const balance = await provider.getBalance("vitalik.eth");
输出结果
将获取到的余额从wei转换为ETH,并在控制台输出:
javascript
console.log(`ETH Balance of vitalik: ${ethers.formatEther(balance)} ETH`);
不难发现 我们的代码中用到Async和Await,这是为什么呢?
Async/Await
除了Promises和回调函数,ethers.js还支持使用async/await关键字来处理异步性。
async/await是ES7引入的语法糖,它可以让我们像编写同步代码一样编写异步代码。使用async关键字修饰一个函数,就可以在函数体内使用await关键字来等待一个异步操作完成。await关键字可以在Promise对象或返回Promise对象的函数前使用,它会暂停函数的执行,直到Promise对象状态变为resolved并返回结果。
为什么以太坊交互需要异步编程?
以太坊是一个分布式网络,涉及到网络通信和共识机制等复杂因素。在与以太坊进行交互时,我们需要等待交易被确认、智能合约的执行结果等。这些操作都需要耗费时间,并且可能会受到网络延迟等因素的影响。如果使用同步编程模型,主线程会被阻塞,无法处理其他任务,从而造成用户体验的下降。
异步编程模型通过将长时间运行的任务委托给后台处理,让主线程能够继续执行其他任务,提高了程序的响应能力和效率。ethers.js利用了Promises和回调函数等机制来处理以太坊交互的异步性。
以太坊开发实践:使用Ethers.js与ERC20代币交互
环境准备
首先,确保你已经安装了Node.js环境,并准备好了以下依赖:
ethers
:以太坊JavaScript库,用于与以太坊网络交互。dotenv
:用于加载环境变量的库。chalk
:用于在控制台输出中添加颜色。
安装依赖:
npm install ethers dotenv chalk
设置环境变量
在与以太坊网络进行交互时,我们需要使用一些环境变量来连接到以太坊节点。为了安全起见,我们将这些敏感信息保存在 .env
文件中,并通过 dotenv
库加载到环境变量中。
在项目目录中创建一个新的文件 .env
,并填入以下内容:
INFURA_API_KEY=<YOUR_INFURA_API_KEY>
PRIVATE_KEY=<YOUR_PRIVATE_KEY>
TOKEN_ADDRESS=<TOKEN_ADDRESS>
步骤1:引入依赖并配置环境变量
javascript
const { ethers } = require("ethers");
const dotenv = require("dotenv");
const chalk = require("chalk");
dotenv.config();
这里我们引入了所需的模块,并使用dotenv
库加载了存储在.env
文件中的环境变量。
步骤2:设置以太坊提供者和钱包
javascript
const main = async () => {
const provider = new ethers.providers.InfuraProvider(
"mainnet",
process.env.INFURA_API_KEY
);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
console.log(chalk.bold("Connected to Ethereum network!!!"));
我们使用Infura作为我们的以太坊节点提供者,并使用环境变量中的私钥创建了一个钱包实例。
步骤3:加载ERC20合约
javascript
const tokenAddress = process.env.TOKEN_ADDRESS;
const tokenAbi = []; // 这里应该是ERC20代币的ABI数组
const tokenContract = new ethers.Contract(tokenAddress, tokenAbi, wallet);
console.log(chalk.bold(`Loaded ERC20 contract at address ${tokenContract.address}`));
创建一个合约实例,用于与特定的ERC20代币合约交互。
步骤4:查询代币余额
javascript
const getAddressBalance = async (address) => {
const balance = await tokenContract.balanceOf(address);
const decimals = await tokenContract.decimals();
return balance.div(ethers.BigNumber.from(10).pow(decimals)).toString();
};
const address = "<ADDRESS_TO_QUERY>"; // 要查询余额的以太坊地址
const balance = await getAddressBalance(address);
console.log(chalk.green.bold(`Current token balance: ${balance}`));
定义一个异步函数getAddressBalance
来查询指定地址的代币余额,并将其转换为人类可读的格式。
步骤5:转账代币
javascript
const transferToken = async (toAddress, amount) => {
const tx = await tokenContract.transfer(toAddress, amount);
console.log(
chalk.green.bold(
`Transfer of ${amount} tokens to ${toAddress} successful! Transaction hash: ${tx.hash}`
)
);
};
const toAddress = "<ADDRESS_TO_TRANSFER>"; // 要转账代币的以太坊地址
const amount = ethers.utils.parseUnits("<AMOUNT>", "<DECIMALS>"); // 要转账的代币数量
await transferToken(toAddress, amount);
定义一个异步函数transferToken
来执行代币转账,并输出交易成功的信息。
步骤6:执行主函数并处理错误
javascript
main().catch((error) => console.error(chalk.foregroundColorNames.bold("Error: "), error));
执行main
函数,并捕获任何可能发生的错误。
一些方法的详细解释:
-
Provider:Provider是ethers.js中的一个核心概念,它负责与以太坊节点通信。Provider可以是WebSocket连接、HTTP连接,或者是任何实现了所需API的自定义实现。
-
getSigner() :这个方法从Provider对象中获取一个
Signer
实例。Signer
实例代表了一个拥有私钥的以太坊账户,它能够签署交易和消息,从而允许你代表该账户发送交易。 -
contractAddress:这是智能合约在以太坊网络上的地址。
-
abi:ABI代表应用二进制接口(Application Binary Interface),它是智能合约的接口描述,定义了合约的方法和事件。
-
new ethers.Contract() :这是创建一个表示智能合约的实例的方法。你需要提供合约地址、ABI和
Signer
对象,这样你就可以调用合约的方法并与之交互。