从 1.x 到 4.x:web3.js 工具函数库(web3-utils)完整迁移指南
2026/9/20 10:03:34 网站建设 项目流程

从 1.x 到 4.x:web3.js 工具函数库(web3-utils)完整迁移指南

【免费下载链接】web3.jsCollection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.项目地址: https://gitcode.com/gh_mirrors/we/web3.js

导读:web3.js 4.x 对工具函数库web3-utils做了一系列破坏性变更:推荐按需命名导入、用原生BigInt取代BN、强制显式传入单位参数、调整toHex/isHex的边界行为、把校验函数迁移到web3-validator、把stripHexPrefix挪到web3-eth-accounts,并收紧了compareBlockNumbers的类型约束。本文以官方迁移指南为骨架,结合仓库源码与测试用例,逐项拆解这些差异,给出可直接复制的迁移示例,帮助你将基于 web3.js 1.x 的代码平滑升级到 4.x。

迁移总览:一次看清所有破坏性变更

变更项1.x 行为4.x 行为影响等级
导入方式import web3Utils from 'web3-utils'推荐import * as web3Utils from 'web3-utils'或按需命名导入编译期
BN大数类内置Web3.utils.BN(基于 bn.js)移除,改用原生BigInt运行时
toWei单位参数可省略,默认ether必须显式传入单位编译期/运行时
toHex('1')数字字符串被当作数字,返回0x1纯数字字符串按字符串处理,返回0x31运行时(易踩坑)
校验函数位于web3-utils迁移至web3-validator,旧位置标记 deprecated编译期告警
stripHexPrefix位于web3-utils迁移至web3-eth-accounts编译期
compareBlockNumbers允许 block tag 与数字混比只允许同类比较(或earliest特例),否则抛InvalidBlockError运行时

其中大部分为编译期即可发现的变化,真正需要逐行排查的是toHex的字符串语义变化与compareBlockNumbers的抛错行为——这两处属于"编译能过、运行结果不同/抛错"的隐蔽差异。

导入方式:按需命名导入

1.x 中web3-utils默认导出整个工具包;4.x 将每个工具函数改为具名导出(见 packages/web3-utils/src/index.ts 中从converters.jsvalidation.jshash.jsrandom.js等模块的export *转发),并鼓励只导入应用实际用到的函数,以利于 tree-shaking 减小打包体积:

// 1.x —— 默认导出整个包 import web3Utils from 'web3-utils'; // 4.x —— 全量导入(兼容 1.x 习惯) import * as web3Utils from 'web3-utils'; // 4.x —— 推荐:按需具名导入 import { toWei, fromWei, toHex } from 'web3-utils';

该改动不影响Web3.utilsweb3.utils命名空间的访问方式,例如web3.utils.toWei('0.1', 'ether')依然可用。按需导入配合 4.x 的 tree-shaking 支持,能显著减小最终 bundle 体积(可参考 13_advanced/tree_shaking 一节)。

告别 BN:全面切换原生 BigInt

1.x 中web3-utils内置BN属性(封装 bn.js)用于处理超出Number安全范围的大整数。4.x 移除了该属性,全面采用 JavaScript 原生BigInt类型:

// 1.x new Web3.utils.BN(1); // 4.x BigInt(4);

这一变更的底层证据在源码中随处可见:单位换算映射表ethUnitMap的全部值均为BigInt(见 packages/web3-utils/src/converters.ts 中wei: BigInt(1)ether: BigInt('1000000000000000000')等);compareBlockNumbers在数字比较路径上直接使用BigInt(blockA) < BigInt(blockB)进行比较(见 packages/web3-utils/src/validation.ts)。

迁移时注意:BigIntNumber不能直接混用算术运算符,跨类型计算需显式转换;另外BigInt不能与Math.*函数、JSON 序列化直接配合,需要时可用Number(...)toString()过渡。

单位换算:toWei/fromWei 必须显式传单位

1.x 中toWei的第二参(单位)可省略,默认ether。4.x 中该可选参数被移除,必须显式传入单位:

// 1.x —— 省略单位,默认 ether web3.utils.toWei('0.1'); // 4.x —— 必须显式传单位 web3.utils.toWei('0.1', 'ether');

从 packages/web3-utils/src/converters.ts 的toWei实现可以看到,单位参数unit: EtherUnits | number已被声明为必选,且支持两类取值:

  • 字符串单位:查表ethUnitMap,如weigweishannonether等,传入不存在的单位会抛InvalidUnitError
  • 数字(十进制幂):直接作为 10 的指数,例如传18等价于etherdenomination = bigintPower(BigInt(10), BigInt(18)))。

fromWei同样要求显式单位(见 packages/web3-utils/src/converters.ts)。此外,当以number类型传入较大数值或高精度小数时,库会输出PrecisionLossWarning警告,提示改用stringBigInt以避免精度丢失——这是所有换算函数(toWei/fromWei/toNumber等)共用的保护机制。

十六进制转换:toHex 对纯数字字符串的处理变了

toHex在两个版本中的绝大多数行为一致,唯一差异是仅包含数字的字符串

// 1.x new Web3().utils.toHex(0x1); // 0x1 new Web3().utils.toHex('0x1'); // 0x1 new Web3().utils.toHex(1); // 0x1 new Web3().utils.toHex('1'); // 0x1(数字字符串被当作数字) // 4.x new Web3().utils.toHex(0x1); // 0x1 new Web3().utils.toHex('0x1'); // 0x1 new Web3().utils.toHex(1); // 0x1 new Web3().utils.toHex('1'); // 0x31(按字符串处理,即字符 '1' 的 ASCII 十六进制)

原因在 packages/web3-utils/src/converters.ts 的toHex分支逻辑中清晰可见:4.x 对字符串先检查是否0x/-0x前缀(走numberToHex),再检查isHexStrict(原样返回),随后才根据isHex/isInt/isUInt的组合判断;纯数字字符串'1'会被当作普通字符串做 UTF-8 编码,因此'1'的十六进制是0x31。注意,toHex对字符串输入遵循"除非以0x为前缀,否则一律按字符串处理"的规则。

迁移排查清单:凡是对"可能为数字的字符串"调用toHex的代码,要么预先用Number()/BigInt()转换,要么确保输入带0x前缀。

校验函数迁移:从 web3-utils 到 web3-validator

4.x 将全部校验函数(isAddressisBloomisInBloomisTopiccheckAddressCheckSumisHexisHexStrict等)迁移到了新包web3-validator。为兼容 1.x 代码,web3-utils仍保留这些导出,但在源码中明确标注了 deprecated 并提示迁移(见 packages/web3-utils/src/validation.ts 中大量@deprecated Will be removed in next release. Please use 'web3-validator' package instead.注释,且每个函数实质上是web3-validator同名实现的再导出):

// 1.x / 4.x(可用但已弃用,会收到弃用告警) import { isAddress, isHex } from 'web3-utils'; // 4.x(推荐) import { isAddress, isHex, isHexStrict } from 'web3-validator';

web3-validator的校验实现集中在 packages/web3-validator/src/validation 目录下,isHex/isHexStrict的具体正则见 packages/web3-validator/src/validation/string.ts。

isHex:负数返回 true

isHex('-123'); // 1.x 返回 false;4.x 返回 true // true

新实现的正则^((-0x|0x|-)?[0-9a-f]+|(0x))$允许可选的-前缀,因此'-123'被视为合法十六进制表示(注意-0x单独不匹配)。

isHex:空字符串返回 false

isHex(''); // 1.x 返回 true;4.x 返回 false // false

空串不满足上述正则中"至少一个十六进制字符"的要求。

isHex / isHexStrict:'-0x' 返回 false

isHex('-0x'); // 1.x 返回 true;4.x 返回 false // false isHexStrict('-0x'); // 1.x 返回 true;4.x 返回 false // false

isHexStrict的正则^((-)?0x[0-9a-f]+|(0x))$要求0x之后至少跟一个十六进制字符(packages/web3-validator/src/validation/string.ts),所以'-0x''0x'均不通过严格校验。

stripHexPrefix:改从 web3-eth-accounts 导入

stripHexPrefix在 4.x 中从web3-utils移至web3-eth-accounts(实现位于 packages/web3-eth-accounts/src/common/utils.ts,对非字符串输入会抛类型错误):

// 4.x import { stripHexPrefix } from 'web3-eth-accounts'; console.log(stripHexPrefix('0x123')); // "123"

从源码看,该函数同时被web3-eth-accounts内部大量使用(如 nonce 补零、RLP 编码前的十六进制规范化等,见 packages/web3-eth-accounts/src/common/utils.ts 与 packages/web3-eth-accounts/src/common/utils.ts),这也是它被"下沉"到账户包的原因。若需在web3-utils中获取同等能力,可自行用str.replace(/^0x/i, '')替代。

compareBlockNumbers:只允许同类比较

compareBlockNumbers(blockA, blockB)用于比较两个区块位置(区块号或区块标签),返回-1(A < B)、0(相等)或1(A > B)。4.x 收紧了入参约束:要么两边都传区块标签,要么两边都传区块数字,唯一例外是earliest与数字0的等价比较。

compareBlockNumbers('earliest', 'safe'); // 合法,返回 -1 compareBlockNumbers(8692, 2); // 合法,返回 1 compareBlockNumbers('latest', 500); // 1.x 返回 1;4.x 抛 InvalidBlockError

源码逻辑(packages/web3-utils/src/validation.ts)按以下顺序执行:

  1. 相等短路blockA === blockB('earliest'|0)('earliest'|0)的组合返回0
  2. earliest 特判:任一方为earliest时直接返回-1/1(这是标签与数字混比的唯一豁免,且测试覆盖了['earliest', 2][2, 'earliest']等组合);
  3. 双标签比较:按earliest → finalized → safe → latest → pending的递增顺序(内部tagsOrder映射为 1~5)返回-1/1
  4. 标签与数字混比:直接抛InvalidBlockError('Cannot compare blocktag with provided non-blocktag input.')
  5. 双数字比较:用BigInt精确比较(支持 number、string、bigint 混用)。

测试用例完整验证了上述行为(packages/web3-utils/test/fixtures/validation.ts):合法数据包括['earliest', 0][0, 'earliest'][['safe', 'pending'], -1]等;非法数据则覆盖['latest', 110][[22, 'finalized'], errorObj]['pending', BigInt(1)]等所有标签与数字混比组合,均断言抛出InvalidBlockError

迁移注意:1.x 代码中若存在"数字区块号与'latest'/'pending'标签比较"的逻辑(例如判断某区块是否已确认),需改写为先获取对应标签的区块号再比较,或改用BlockTags之间的比较,避免运行时抛错。

迁移实战检查清单

完成上述逐项改造后,建议按以下清单回归验证:

  1. 搜索BN:仓库内所有Web3.utils.BN/new BN(...)用法替换为BigInt(...),并检查toString()、比较运算等跨类型操作;
  2. 搜索toWei/fromWei:确认所有调用都传入了单位参数(字符串或十进制指数);
  3. 搜索toHex('纯数字字符串'):确认输入带0x前缀或先转数字,防止'1' → 0x31这类静默语义变化;
  4. 搜索isHex/isHexStrict的边界输入:关注负数、空串、'-0x'三类返回值变化(web3-validator 校验实现);
  5. 搜索stripHexPrefix的导入来源:统一改为web3-eth-accounts
  6. 搜索compareBlockNumbers的混比调用:标签与数字混比需改写,必要时捕获InvalidBlockError(web3-errors 错误码定义);
  7. 检查弃用告警:对web3-utils中 deprecated 的校验函数统一改导web3-validator

需要说明的是,本文所有行为差异均以当前仓库(web3.js 4.x 系列)源码与测试为据,若你的项目锁定在特定 4.x 小版本,建议以该版本发布说明为准做最终核对。其他包的迁移可继续参考本升级指南目录下的 accounts_migration_guide、providers_migration_guide 等姊妹篇。

【免费下载链接】web3.jsCollection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.项目地址: https://gitcode.com/gh_mirrors/we/web3.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询