Utils 工具方法
在 ethers.js
v6 版本中,提供了许多实用工具方法(utility functions),用于处理以太坊相关的数据,例如单位转换、地址验证、数据编码等。类似于 parseEther
的工具方法主要集中在单位转换、格式化、编码和验证等方面,这些方法通常位于 ethers.utils
模块(在 v6 中,utils
模块被直接整合到 ethers
命名空间下)。以下是对 ethers.js
v6 中类似 parseEther
的工具方法的详细讲解,包括分类、功能描述和代码示例。
格式化
parseUnits
将以太币(ETH)的字符串表示转换为小单位。
parseUnits(value: string, unit?: string | Numeric): bigint
value
: 要转换的字符串表示的以太币数量。unit
: 要转换的单位,可以是字符串(如"wei"
、"gwei"
等)或数字(表示单位位数)。
常见单位:
wei
:以太坊的最小单位。- 换算:1 Ether = 10^18 wei(即 1,000,000,000,000,000,000 wei)。
kwei
:Kwei 是以太坊的次小单位,等于 1,000 wei。- 换算:1 Ether = 10^15 Kwei。
mwei
:Mwei 是更大的单位,等于 1,000,000 wei(10^6 wei)。- 换算:1 Ether = 10^12 Mwei。
gwei
:Gwei 是以太坊中非常常用的单位,主要用于 Gas 费用,等于 10^9 wei(1,000,000,000 wei)。- 换算:1 Ether = 10^9 Gwei。
szabo
:Szabo 等于 10^12 wei(1,000,000,000,000 wei)。- 换算:1 Ether = 10^6 Szabo。
finney
:Finney 等于 10^15 wei(1,000,000,000,000,000 wei)。- 换算:1 Ether = 10^3 Finney。
ether
:Ether 是以太坊的主要货币单位,等于 10^18 wei。- 换算:1 Ether = 10^18 wei = 10^9 Gwei = 10^6 Szabo = 10^3 Finney。
// 将 1.5 ETH 转换为 gwei 单位
const value = ethers.parseUnits("1.5", "gwei");
// 1500000000n
const value = ethers.parseUnits("1.5", 9);
// 1500000000n
parseEther
将 ETH
单位转换为 wei
单位。
功能
:将以太币(ETH)的字符串表示转换为以 wei 为单位的 Bigint。参数
:value
(字符串,表示 ETH 数量,例如 "1.5")。返回值
:Bigint
,表示 wei 单位的数量(1 ETH = 10^18 wei)。
该方法是语法糖,实际上调用 parseUnits(value, 18)
。
const value = ethers.parseEther("1.5");
// 1500000000000000000n
formatUnits
parseUnits
的相反操作,将以最小单位为单位的 bigint
转换为指定小数位数的字符串
。
formatUnits(value: BigNumberish, unit?: string | Numeric): string
value
: 要转换的bigint
表示的以太币数量。unit
: 默认18
,要转换的单位,可以是字符串(如 "wei"、"gwei" 等)或数字(表示单位位数)。
const value = ethers.formatUnits(1500000000000000000n);
const value = ethers.formatUnits(1500000000000000000n, 18);
// 1.5
formatEther
将 wei
单位转换为 ETH
单位。
是一个语法糖,实际上调用 formatUnits(value, 18)
const value = ethers.formatEther(1500000000000000000n);
// 1.5
判断
isAddress
检查字符串是否为有效的以太坊地址。
ethers.isAddress("0x2cFC43B94126595E8B636fed9fB585fF220Bc97d"); // true
ethers.isAddress("0x"); // false
isError
isError
的主要用途是帮助开发者在处理以太坊交易或智能合约交互时,准确识别和处理 ethers.js
抛出的特定错误。
function isError(error, code): boolean
错误码有以下:
- 通用错误
UNKNOWN_ERROR
:当以太坊无法知道潜在问题是什么情况时抛出。NOT_IMPLEMENTED
:此错误主要用作未来功能的存根,但目前尚未实现。UNSUPPORTED_OPERATION
:此错误表示不支持尝试的操作,可能包括从不支持功能的特定 JSON-RPC 端点到禁止操作的对象的特定配置。NETWORK_ERROR
:此错误表示连接到网络时出现问题。SERVER_ERROR
:此错误表示从服务器获取资源时出现问题。TIMEOUT
:此错误表示超时时间已过,操作已被隐式取消。BAD_DATA
:此错误表示无法正确解释提供的数据集。CANCELLED
:此错误表示操作被程序调用取消,例如“cancel()”
。
- 操作错误
BUFFER_OVERRUN
:此错误表示有人试图读取受保护数据的边界之外的数据。NUMERIC_FAULT
:此错误表示发生了可能导致错误算术输出的操作。
- 参数错误
INVALID_ARGUMENT
:此错误表示传递给函数或方法的类型或值不正确。MISSING_ARGUMENT
:此错误表示提供的参数太少。UNEXPECTED_ARGUMENT
:此错误表示提供的参数太多。
- 块链错误
CALL_EXCEPTION
:此错误表示交易已恢复。INSUFFICIENT_FUNDS
:发送账户的资金不足以支付全部交易成本。NONCE_EXPIRED
:发送帐户已在已包含的交易中使用了此随机数。REPLACEMENT_UNDERPRICED
:试图替换一个事务,但额外费用不足以从内存池中删除旧事务。TRANSACTION_REPLACED
:一笔待处理的交易被另一笔交易所取代。UNCONFIGURED_NAME
:此错误表示使用了 ENS 名称,但尚未配置该名称。OFFCHAIN_FAULT
:CCIP 读取异常,无法从中恢复或进一步处理。
- 用户接口错误
ACTION_REJECTED
:此错误表示用户拒绝了请求。
try {
const provider = new ethers.JsonRpcProvider("");
await provider.getBalance("0x");
} catch (error: any) {
// 返回 true, ethers.js 抛出的错误
if (ethers.isError(error, "UNSUPPORTED_OPERATION")) {
// code...
}
}
try {
await fetch('https://api.example.com/data')
} catch (error: any) {
// 同样抛出错误,但不是 ethers.js 抛出的错误
}
isHexString
function isHexString(value: any, length?: number): boolean;
函数用于判断一个值是否为有效的十六进制字符串。
- 类型检查:输入值必须是一个字符串。
- 前缀检查:字符串必须以 "0x" 开头。
- 字符检查:紧跟 "0x" 之后的所有字符必须是有效的十六进制字符(即
0-9
和a-f
,不区分大小写)。 - 长度检查 (可 选):可以额外指定一个期望的字节长度。如果指定了长度,
isHexString
还会检查字符串(去掉"0x"
前缀后)的长度是否是期望字节长度的两倍。这是因为一个字节由两个十六进制字符表示。
// 有效的十六进制地址
console.log(isHexString("0x742d35Cc6634C0532925a3b844Bc454e4438f44e")); // true
// 有效的十六进制地址, 并指定正确的字节长度 (地址是20字节)
console.log(isHexString("0x742d35Cc6634C0532925a3b844Bc454e4438f44e", 20)); // true
// 有效的十六进制字符串 (短)
console.log(isHexString("0x123aF")); // true
// 有效的十六进制字符串,并指定正确的字节长度
console.log(isHexString("0x123aFf", 3)); // true (3字节 = 6个十六进制字符)
// 无 "0x" 前缀
console.log(isHexString("742d35Cc6634C0532925a3b844Bc454e4438f44e")); // false
// 包含无效字符
console.log(isHexString("0x123GHI")); // false (G, H, I 不是有效的十六进制字符)
// 长度不匹配 (期望20字节,实际不是)
console.log(isHexString("0x123456", 20)); // false
// 奇数长度的十六进制字 符 (不指定长度时是允许的,只要字符有效)
console.log(isHexString("0x123")); // true (因为 '1', '2', '3' 都是有效十六进制字符)
// 奇数长度的十六进制字符,但指定了字节长度,则会因长度不匹配而失败
console.log(isHexString("0x123", 2)); // false (期望2字节即4个字符,实际3个字符)
// 非字符串输入
console.log(isHexString(123)); // false
console.log(isHexString(null)); // false
console.log(isHexString(undefined)); // false
在以太坊开发中,十六进制字符串被广泛用于表示各种数据,例如:
地址 (Address)
:例如0x2cFC43B94126595E8B636fed9fB585fF220Bc97d
交易哈希 (Transaction Hash)
:例如0x86e02b444996402090920b38bbccfcdea27f6bc9921a3d4b841c25bfe64581ce
私钥 (Private Key)
:虽然不常直接在前端操作,但其原始形式也是十六进制。字节码 (Bytecode)
:合约编译后的代码。数据 (Data)
:例如在调用合约方法时传递的参数。
哈希与加密
keccak256
keccak256
是一个非常核心的加密函数,用于计算 Keccak-256
哈希值(与以太坊中常说的 SHA3
相同,但略有区别)。这个函数在以太坊的智能合约开发、签名、地址生成等场景中都非常常见。
function keccak256(data: string | Uint8Array): string
- 字符串:如果你传的是字符串,务必要用
toUtf8Bytes()
来转换成字节流。 - Uint8Array:如果你传的是字节流,那么就直接传。
import { keccak256, toUtf8Bytes } from "ethers";
const value = keccak256(toUtf8Bytes("Hello World"));
console.log(value); // 0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba
const value2 = keccak256(new Uint8Array([0x13, 0x37]));
console.log(value2); // 0x2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc