news 2026/9/9 20:12:54

fuels-ts 钱包余额查询全指南:getBalance 与 getBalances 的用法与原理解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fuels-ts 钱包余额查询全指南:getBalance 与 getBalances 的用法与原理解析

fuels-ts 钱包余额查询全指南:getBalance 与 getBalances 的用法与原理解析

【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts

本指南以 Fuel Network TypeScript SDK(fuels-ts)官方文档 checking-balances.md 为主体,讲解在 fuels-ts 中如何查询单个资产余额与账户全部资产余额。文章将结合 Account 与 Provider 的真实源码,说明getBalance/getBalances的底层调用链、返回类型与分页行为,帮助你既会写查询代码,也理解其工作原理。

一、概述:两类余额查询场景

在 fuels-ts 中,钱包/账户对象(Account)封装了对链上资产状态的查询能力。查看余额通常分两种诉求:

场景方法返回值
查询某个特定资产的余额getBalanceBN(BigNumber 大数对象)
查询账户下所有资产的余额getBalances{ balances: CoinQuantity[], pageInfo? }

两个方法都定义在 Account 上,因此钱包(Wallet)、只读账户等一切继承 Account 的实体都能直接调用。官方文档对二者的定位分别是:

  • getBalance:聚合钱包中给定资产所有未花费 Coin(UTXO)的金额总和;
  • getBalances:返回一组CoinQuantity,用于完整掌握账户的全部持仓

二、查询单个资产余额:getBalance

2.1 官方示例

官方文档示例(checking-balances.ts)展示了最小可用写法:

import type { BN } from 'fuels'; import { Provider, Wallet } from 'fuels'; import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../../env'; const provider = new Provider(LOCAL_NETWORK_URL); const myWallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); // The returned amount is a BigNumber const balance: BN = await myWallet.getBalance(await provider.getBaseAssetId());

代码要点:

  1. 创建 Providernew Provider(LOCAL_NETWORK_URL)建立与 Fuel 节点的连接。LOCAL_NETWORK_URL指向本地测试网络节点(通常是http://127.0.0.1:4000之类的地址,在文档示例工程 apps/docs/src/env.ts 中以环境注入变量形式提供)。
  2. 从私钥实例化钱包Wallet.fromPrivateKey(WALLET_PVT_KEY, provider),其中WALLET_PVT_KEY对应一个预先注资的测试账户私钥。
  3. 传入基准资产 IDprovider.getBaseAssetId()返回当前网络的基准资产(Fuel 主资产)ID。在标准 Fuel 网络中它通常是0x0000...0000(零地址),但为了与自定义网络的配置解耦,官方示例统一通过 Provider 查询获取。
  4. 返回值是 BNgetBalance返回BN大数类型,而非普通number。余额以最小原子单位(base asset 的最小精度单位)计,直接做数值运算或展示前应先转换(如balance.toString()),避免 JSnumber精度丢失。

2.2 参数省略的默认行为

从源码看,Account.getBalance 的assetId参数是可选的:

async getBalance(assetId?: BytesLike): Promise<BN> { const assetIdToFetch = assetId ?? (await this.provider.getBaseAssetId()); const amount = await this.provider.getBalance(this.address, assetIdToFetch); return amount; }

也就是说,当你不传任何参数直接调用wallet.getBalance()时,它会自动取provider.getBaseAssetId()作为默认资产。显式传入与省略参数效果等价,但建议显式传入以增强代码可读性。

三、查询全部资产余额:getBalances

官方文档示例(checking-balances-two.ts):

import { Provider, Wallet } from 'fuels'; import { WALLET_PVT_KEY_2, LOCAL_NETWORK_URL } from '../../../env'; const provider = new Provider(LOCAL_NETWORK_URL); const myOtherWallet = Wallet.fromPrivateKey(WALLET_PVT_KEY_2, provider); const { balances } = await myOtherWallet.getBalances(); console.log('balances:', balances);

返回的balancesCoinQuantity数组,其类型定义位于 coin-quantity.ts:

export type CoinQuantity = { amount: BN; assetId: string; max?: BN };

每个元素包含:

字段类型含义
assetIdstring资产 ID(燃料链上的资产唯一标识)
amountBN该资产的可花费余额(大数,单位为原子单位)
maxBN(可选)可用的最大数量(预留估算费用等场景下与 amount 可能不同)

getBalances是观察一个地址持仓全貌的最直接途径:遍历该地址下所有资产,逐个给出资产 ID 与对应金额,适合做资产看板、余额列表展示等场景。

四、底层原理:方法调用链

文档只展示了 Account 层的用法,理解底层能帮你把握分页、节点兼容等行为。

4.1 getBalance 的调用链

Account.getBalance只是薄封装,真正干活的是 Provider.getBalance:

async getBalance( owner: AddressInput, assetId: BytesLike ): Promise<BN> { const { balance } = await this.operations.getBalanceV2({ owner: new Address(owner).toB256(), assetId: hexlify(assetId), }); return bn(balance.amountU128, 10); }

调用链为:Wallet.getBalance(assetId)Account.getBalance(补齐默认 baseAssetId)→Provider.getBalance(address, assetId)→ GraphQL 操作getBalanceV2→ 返回BN。关键实现事实:

  • 地址会被规范化为 b256 格式(Address(owner).toB256()),资产 ID 会被hexlify统一处理,确保链上查询参数格式正确;
  • 余额金额来自节点响应中的amountU128字段,属于u128 大整数,因此 SDK 用BN承载;
  • 文档描述"聚合所有未花费 Coin 的金额总和"正对应 Fuel 账户模型的 UTXO 特性——getBalanceV2在节点侧对同一资产的全部 UTXO 求和返回。

4.2 getBalances 的调用链与分页

Provider.getBalances 的实现揭示了文档未明说的节点兼容与分页逻辑

async getBalances( owner: string | Address, paginationArgs?: CursorPaginationArgs ): Promise<GetBalancesResponse> { // The largest possible size allowed by the node. let args: CursorPaginationArgs = { first: NON_PAGINATED_BALANCES_SIZE }; const { balancesPagination: supportsPagination } = await this.getNodeFeatures(); if (supportsPagination) { // If the node supports pagination, we use the provided pagination arguments. args = validatePaginationArgs({ inputArgs: paginationArgs, paginationLimit: BALANCES_PAGE_SIZE_LIMIT, }); } const { balances: { edges, pageInfo }, } = await this.operations.getBalancesV2({ ...args, filter: { owner: new Address(owner).toB256() }, supportsPagination, }); const balances = edges.map(({ node }) => ({ assetId: node.assetId, amount: bn(node.amountU128), })); return { balances, ...(supportsPagination ? { pageInfo } : {}), }; }

值得注意的实现事实:

  1. 自动探测节点分页能力:SDK 通过getNodeFeatures()读取节点的balancesPagination特性开关;
  2. 不支持分页的旧节点:一次请求尽量取满NON_PAGINATED_BALANCES_SIZE = 10000条(常量定义见 provider.ts 顶部);
  3. 支持分页的新节点:使用validatePaginationArgs校验用户传入的分页参数,上限受BALANCES_PAGE_SIZE_LIMIT = 100约束(分页单页大小限制为 100);
  4. 返回结构差异:当节点支持分页时,返回值额外附带pageInfo(含游标信息),便于后续翻页;
  5. 字段映射:每条余额同样取自amountU128并转为BN,组装成{ assetId, amount }形状的CoinQuantity

因此在处理大量资产余额时,若账户持仓种类很多,你可能需要通过paginationArgsafter游标 +first数量)遍历所有页;而对常规账户,默认一次调用即可取回全部持仓。

五、实操要点小结

  1. 始终以原子单位处理余额BN表示的金额未做精度缩放,UI 展示时应按资产精度换算,切勿当作十进制小数额直接拼接字符串。
  2. 不要丢失 UTXO 语境getBalance汇总的是未花费 Coin,余额为"可花费金额",与账户"锁定金额"(如进行中的交易占用)不同。
  3. 复用 ProviderProvider是重量级连接对象,官方示例刻意将同一个provider注入多个钱包,实际项目中也应复用而非每次新建。
  4. 资产 ID 的统一来源:多资产场景下,用provider.getBaseAssetId()获取主资产 ID,而非硬编码零地址,以兼容不同网络配置。
  5. 相关阅读:余额查询是钱包基础操作之一,可与本目录下的 私钥钱包、助记词钱包、资产转账 文档组合成完整的钱包开发工作流。

六、结语

fuels-ts 的余额查询 API 设计得非常克制:getBalance解决"某一资产有多少",getBalances解决"我持有哪些资产",两者都收敛到Provider层的 GraphQL 查询。理解getBalance默认回退基准资产、getBalances随节点能力自动切换分页策略这两处实现细节,能让你在编写余额展示、资产清单、自动化校验逻辑时少踩坑。配套的官方示例代码位于 wallets/snippets 目录,可直接作为脚手架参考。

【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 20:12:35

开源本地PDF处理方案:隐私安全与实践详解

我在做合同、标书这类PDF处理时&#xff0c;最烦的还不是操作繁琐&#xff0c;而是每次用在线工具都要上传一遍文件。有一回急着给客户转一份带签章页的合同&#xff0c;手头电脑没装办公软件&#xff0c;找了个在线PDF转换器&#xff0c;传上去转完还提示"文件过大请升级…

作者头像 李华
网站建设 2026/9/9 20:10:53

Vue 3 实战笔记:组合式API、响应式原理与工程化部署全解

Vue 3 正式版发布已经有一阵子了&#xff0c;但直到今天&#xff0c;还是有很多人在问“Vue 3 到底比 Vue 2 强在哪”“项目里要不要上组合式 API”。打开招聘网站搜前端岗&#xff0c;十个里面至少七个写着“熟悉 Vue 3 / 组合式 API”&#xff1b;打开同事的 git log&#xf…

作者头像 李华
网站建设 2026/9/9 20:10:42

Java基本类型与包装类型:从自动装箱到NPE实战全解析

Java面试里有一道题&#xff0c;明明背得滚瓜烂熟&#xff0c;但每次被问都能感觉到面试官在等你说出某个隐藏的坑。这道题就是&#xff1a;包装类型和基本类型的区别是什么&#xff1f;包装类型与基本类型&#xff0c;一个是对象&#xff0c;一个是普通值&#xff0c;这两个概…

作者头像 李华
网站建设 2026/9/9 20:09:24

Function Calling 本质:LLM 工具调用的运行时契约解析

Function Calling 这个词&#xff0c;最近半年在大模型应用开发圈里几乎天天刷屏——不是在调试 tool call&#xff0c;就是在重试 codex runtime 报错的路上。我从去年底开始做 Agent 类项目&#xff0c;从最原始的手写 JSON Schema 工具描述&#xff0c;到接入 LangChain 的 …

作者头像 李华
网站建设 2026/9/9 20:07:06

TikTok商城卖家必看:跌落测试实战指南

1. 跌落测试&#xff1a;TikTok商城卖家必须补上的第一课 做TikTok商城&#xff0c;很多卖家把精力都花在了选品、拍摄和投流上&#xff0c;觉得只要产品好、视频爆&#xff0c;就能出单。但有一个环节&#xff0c;往往被忽视&#xff0c;却直接决定了你能否留住客户、赚到利润…

作者头像 李华