- 区块链
- Web3
【免费下载链接】fuels-ts
Fuel Network Typescript SDK
导读
本文围绕 fuels-ts(Fuel Network TypeScript SDK)中“如何运行本地 Fuel 节点”这一核心开发环节展开,系统讲解两条官方支持路径:直接使用fuel-core二进制程序,以及通过 TS SDK 提供的fuels nodeCLI 命令启动。在此基础上,进一步深入fuels dev热重载开发模式与launchTestNode测试节点工具,并结合仓库源码说明其底层实现原理。读完本文,你将能独立完成本地节点的启动、配置、接入与测试集成,覆盖从开发到单元测试的完整本地工作流。
本文对应官方文档:running-a-local-fuel-node.md。文档中的命令、配置与行为均以当前仓库实际实现为准。
一、前置条件:先安装 Fuel Toolchain
在启动任何本地 Fuel 节点之前,需要先安装 Fuel Toolchain 中明确指出:使用本库之前必须安装 Fuel Toolchain。
随后在你的项目中添加fuels依赖(当前仓库各 demo 应用均使用fuels包,例如 demo-fuels/package.json):
npm install fuels --save # 或 pnpm add fuels # 或 bun add fuels二、两条启动路径:fuel-core二进制 vsfuels nodeCLI
官方文档给出的速览表如下:
| 启动方式 | 命令 | 用途 |
|---|---|---|
| Fuel 二进制 | fuel-core | 直接运行一个本地 Fuel 节点 |
| TS SDK | fuels node | 通过fuelsCLI 启动本地节点 |
两条路径各有适用场景:
fuel-core二进制:适合需要对节点启动参数有完全掌控的场景,例如手动指定端口、快照目录、链配置等;fuels node:基于项目内已有的fuels.config.ts配置启动节点,与项目构建链路天然集成,无需手动拼装启动参数。
原始文档中曾被考虑过的forc node命令(对应 Forc 工具链的节点子命令)目前仍处于注释状态,说明官方当前推荐的本地节点方案就是上述两种。
三、方式一:使用fuels node启动节点
3.1 前提:先生成fuels.config.ts
fuels node命令要求项目根目录存在fuels.config.ts配置文件。官方推荐用fuels init命令生成,见 commands.md 的fuels init小节。
对于使用 Forc workspace 的项目,一条命令即可生成最小配置:
npx fuels init --workspace ./sway-programs --output ./src/sway-programs-api生成的fuels.config.ts最小配置如下(完整示例见 demo-fuels/fuels.config.minimal.ts):
import { createConfig } from 'fuels'; export default createConfig({ workspace: './sway-programs', // forc workspace output: './src/sway-programs-api', });fuels init的常用选项包括:
| 选项 | 说明 |
|---|---|
--path <path> | 项目根目录(默认当前目录) |
-w, --workspace <path> | Forc workspace 相对路径 |
-c, --contracts [paths...] | 合约相对路径列表 |
-s, --scripts [paths...] | 脚本相对路径列表 |
-p, --predicates [paths...] | 谓词相对路径列表 |
-o, --output <path> | TypeScript 生成输出目录 |
--forc-path <path> | forc二进制路径 |
--fuel-core-path <path> | fuel-core二进制路径 |
--auto-start-fuel-core | dev命令期间自动启动fuel-core节点 |
--fuel-core-port <port> | 本地fuel-core节点使用的端口 |
-h, --help | 显示帮助 |
init之后的项目布局:
. ├── sway-programs # forc workspace ├── src │ └── sway-programs-api # 类型生成输出目录 ├── fuels.config.ts └── package.json3.2 运行fuels node
npx fuels node该命令会启动一个短生命周期的fuel-core节点(short-lived),这意味着它主要用于本地开发与调试,不会常驻后台。
3.3 源码剖析:fuels node到底做了什么
从源码看,fuels node命令的实现位于 packages/fuels/src/cli/commands/node/index.ts:
- 通过
loadConfig(config.basePath)加载fuels.config.ts; - 调用
autoStartFuelCore(config)启动fuel-core子进程(#L43-L44); - 使用
chokidar监听fuels.config.ts与snapshotDir的变化,一旦文件变更就关闭旧节点、重新加载配置并重启新节点(#L28-L41),因此修改配置无需手动重启; - 每次成功重启后调用配置中的
onNode回调(#L37)。
节点本身由autoStartFuelCore完成(见 packages/fuels/src/cli/commands/dev/autoStartFuelCore.ts),其关键行为:
- 默认绑定
0.0.0.0,对外地址127.0.0.1; - 端口取
config.fuelCorePort,未配置时用portfinder从 4000 开始寻找第一个空闲端口(#L26); - 以
--db-type in-memory方式启动,即内存数据库,进程退出数据即消失; - 启动成功后,会覆盖
config.providerUrl为本地节点 URL,并将config.privateKey覆盖为defaultConsensusKey(#L52-L54)。
3.4 与节点相关的常用配置项
fuels node的行为由 config-file.md 中定义的一系列配置项控制,完整示例见 demo-fuels/fuels.config.full.ts:
import { createConfig } from 'fuels'; export default createConfig({ workspace: './sway-programs', // 自动启动本地 fuel-core 节点 autoStartFuelCore: true, // 端口:默认从 4000 起取第一个空闲端口 fuelCorePort: 4000, // 自定义 fuel-core 快照目录(包含 chainConfig.json / metadata.json / stateConfig.json) snapshotDir: './my/snapshot/dir', // 节点启动成功并刷新后触发 onNode: (config) => { console.log('fuels:onNode', { config }); }, // 默认使用系统 binaries;可指定路径 forcPath: '~/.fuelup/bin/forc', fuelCorePath: '~/.fuelup/bin/fuel-core', });要点说明:
autoStartFuelCore:置为true时自动启动节点并覆盖providerUrl;置为false时你必须自行启动fuel-core,并通过providerUrl手动指定节点地址;providerUrl:默认http://127.0.0.1:4000/v1/graphql;snapshotDir:仅fuels dev/fuels node使用,且只在autoStartFuelCore为true时生效;目录内可放置chainConfig.json、metadata.json、stateConfig.json来定制链的创世状态。
四、方式二:直接运行fuel-core二进制
如果你希望完全绕开 CLI 封装,可以手动安装并运行fuel-core二进制程序:
fuel-core run --ip 127.0.0.1 --port 4000 --db-type in-memory运行本地节点后,在 TS SDK 中通过Provider接入(示例见 connecting-to-the-network.md 及 snippets/connecting-to-the-network.ts):
import { Provider } from 'fuels'; const NETWORK_URL = 'http://127.0.0.1:4000/v1/graphql'; const provider = new Provider(NETWORK_URL); const baseAssetId = await provider.getBaseAssetId(); const chainId = await provider.getChainId(); const gasConfig = await provider.getGasConfig();采用这种方式时,需要手动配置fuels.config.ts中的providerUrl,因为不会自动覆盖:
export default createConfig({ workspace: './sway-programs', output: './src/sway-programs-api', providerUrl: 'http://127.0.0.1:4000/v1/graphql', });五、开发模式:fuels dev与热重载
除了fuels node,fuels dev是本地开发体验的进阶选择。根据 commands.md 的fuels dev小节,它会做三件事:
- 自动启动一个短生命周期的
fuel-core节点(对应配置项autoStartFuelCore); - 启动时先执行一次
build与deploy; - 监听你的 Forc workspace,每次变更都重新构建、重新生成类型定义与工厂类、重新部署。
在
dev模式下,每次更新 workspace 中的合约,都会按照你配置的output目录重新生成类型定义与工厂类;如果它被其他构建系统(如next dev)纳入,还可以触发自动重编译 / 自动刷新。
得益于autoStartFuelCore在启动节点后自动覆盖providerUrl与privateKey,你无需关心本地节点地址,SDK 会直接与自动启动的节点通信。这正是fuels node/fuels dev相比手动运行fuel-core的便利之处。
六、在单元测试中启动节点:launchTestNode
除了命令行方式,你还可以在.ts单元测试内部直接拉起一个临时 Fuel 节点。官方文档 launching-a-test-node.md 提供了launchTestNode工具函数(源码位于 packages/contract/src/test-utils/launch-test-node.ts)。它可以在一次调用中完成:启动短生命周期的fuel-core节点、创建自定义Provider、生成钱包、部署合约等全部准备工作。
6.1 显式资源管理(using自动清理)
launchTestNode返回的对象实现了Symbol.dispose(源码#L177),因此支持 TypeScript 5.2 引入的显式资源管理(explicit resource management):
import { launchTestNode } from 'fuels/test-utils'; using launched = await launchTestNode(); // launched.cleanup() 会在 launched 离开块作用域时被自动调用使用using前需要调整tsconfig.json:
{ "compilerOptions": { "target": "es2022", "lib": ["es2022", "esnext.disposable"] } }要求:TypeScript ≥ 5.2、编译目标为es2022或以下、lib包含esnext或esnext.disposable。
6.2 标准 API:手动调用cleanup()
如果不使用(或无法使用)显式资源管理,按常规const声明即可,但必须手动调用.cleanup()来销毁节点:
const launchedTestNode = await launchTestNode(); // 运行你的测试…… launchedTestNode.cleanup();6.3 返回值:provider / wallets / contracts
launchTestNode返回{ provider, wallets, contracts, cleanup }。基本用法示例(来自 snippets/launching-a-test-node.ts):
import { CounterFactory } from './typegend/contracts/CounterFactory'; using launched = await launchTestNode({ contractsConfigs: [CounterFactory], }); const { contracts: [contract], provider, wallets } = launched; const { waitForResult } = await contract.functions.get_count().call(); const response = await waitForResult();6.4 配置钱包:walletsConfig
通过walletsConfig可以精细控制创世区块中的钱包与资产分布(配置类型定义见 packages/account/src/test-utils/wallet-config.ts):
| 字段 | 含义 |
|---|---|
count | 生成的钱包数量 |
assets | 数字表示每个钱包拥有的资产种类数(含基础资产);TestAssetId[]表示除基础资产外指定的资产 ID 列表 |
coinsPerAsset | 每种资产对应的 UTXO 币数量 |
amountPerCoin | 每个币的金额 |
messages | 预置到钱包的链上消息(recipient会被覆盖为钱包地址) |
示例(来自 snippets/launch-test-node-wallets.ts):
import { launchTestNode, TestAssetId } from 'fuels/test-utils'; using launched = await launchTestNode({ walletsConfig: { count: 3, assets: [TestAssetId.A, TestAssetId.B], coinsPerAsset: 5, amountPerCoin: 100_000, }, }); const { wallets: [wallet1, wallet2, wallet3] } = launched;从实现上看(wallet-config.ts),WalletsConfig会根据这些配置在stateConfig中生成对应的coins与messages,写入快照的创世状态。TestAssetId预置了A、B两个固定资产,也支持TestAssetId.random(n)生成随机资产(见 packages/account/src/test-utils/test-asset-id.ts)。
6.5 部署合约:contractsConfigs
contractsConfigs接受合约工厂类,或带细粒度控制的对象:
using launched = await launchTestNode({ walletsConfig: { count: 4, assets: TestAssetId.random(2), coinsPerAsset: 2, amountPerCoin: 1_000_000, messages: [new TestMessage({ amount: 1000 })], }, contractsConfigs: [ { factory: CounterFactory, walletIndex: 3, // 使用第 4 个钱包部署 options: { storageSlots: [] }, }, ], }); const { contracts: [counterContract], wallets: [wallet1, wallet2, wallet3, wallet4] } = launched;部署逻辑见 launch-test-node.ts:逐个调用工厂的deploy(wallet, options),walletIndex指定部署所用钱包(默认第 0 个),options透传给ContractFactory.deploy(如storageSlots)。
6.6 自定义节点行为
nodeOptions允许你传入自定义参数,包括args(透传给fuel-core的附加参数)与snapshotConfig(覆盖链配置 / 状态配置):
process.env.DEFAULT_FUEL_CORE_ARGS = `--tx-max-depth 20`; // 注意:nodeOptions.args 会覆盖上述环境变量中的值 const nodeWithCustomArgs = await launchTestNode(); process.env.DEFAULT_FUEL_CORE_ARGS = ''; nodeWithCustomArgs.cleanup();还支持通过DEFAULT_CHAIN_SNAPSHOT_DIR环境变量指向自定义快照目录(包含metadata.json、chainConfig、stateConfig),或者直接用nodeOptions.snapshotConfig覆盖链配置,例如修改基础资产 ID:
const [baseAssetId] = TestAssetId.random(); using launched = await launchTestNode({ nodeOptions: { snapshotConfig: { chainConfig: { consensus_parameters: { V2: { base_asset_id: baseAssetId.value }, }, }, }, }, });这些快照合并与参数解析逻辑分别位于 launch-test-node.ts 的getChainSnapshot与getFuelCoreArgs函数中。
6.7 节点启动的底层实现
无论 CLI 还是测试工具,最终都通过 packages/account/src/test-utils/launchNode.ts 的launchNode函数以子进程方式拉起fuel-core:
- 在临时目录中写入
metadata.json、chainConfig.json、stateConfig.json(#L187-L217); - 使用
spawn执行fuel-core run,携带--ip、--port、--db-type、--snapshot、--consensus-key等参数(#L219-L240); - 通过监听进程 stderr 中的
Binding GraphQL provider to日志判断节点就绪,并解析出真实 GraphQL 地址(#L295-L321); - 提供
cleanup(),负责杀掉子进程并清理临时目录,同时挂载了exit、SIGINT等进程信号处理以保证资源释放(#L262-L338)。
理解了这一层,你就明白为什么fuels node、fuels dev与launchTestNode都能“一键起节点”——它们共享同一套fuel-core子进程管理机制。
七、更多参考资源
- React 示例:react-example.md,演示在 React 应用中使用 fuels-ts 的完整流程;
- CDN 用法:cdn-usage.md,不经过打包器直接在浏览器中以 CDN 方式使用;
- CLI 全部命令:commands.md,涵盖
init、build、deploy、dev、node、typegen、versions; - 配置项详解:config-file.md;
- 接入本地节点的官方 RPC 地址:本地节点地址即
http://127.0.0.1:4000/v1/graphql(与 connecting-to-the-network.md 中列出的 Mainnet / Testnet 地址对应); - 真实项目参考:本仓库的 demo-fuels(含完整与最小配置示例)、create-fuels-counter-guide/fuels.config.ts(演示如何结合
dotenv从.env加载端口与 provider 配置)。
小结
本地节点是 fuels-ts 开发与测试的基石:日常调试可用fuels node/fuels dev借助fuels.config.ts一键启动并热重载,对节点有完全控制需求时可手动运行fuel-core二进制,单元测试则统一交给launchTestNode快速拉起隔离环境。理解它们共享的launchNode子进程机制与快照生成逻辑,能帮助你在遇到端口占用、节点启动失败或创世状态异常时快速定位问题。
- 区块链
- Web3
【免费下载链接】fuels-ts
Fuel Network Typescript SDK
相关推荐
Fuels SDK 测试指南:通过 Fuel-Core Options 定制 `launchTestNode` 的快照与节点参数
Fuels SDK 测试指南:通过 Fuel Core Options 定制 launchTestNode 的快照与节点参数 launchTestNode 是
区块链Web3fuels-rs 外部节点连接指南:用 Provider::connect 接入 Testnet 与本地 fuel-core 节点
fuels rs 外部节点连接指南:用 Provider::connect 接入 Testnet 与本地 fuel core 节点 本文围绕 fuels rs(
区块链后端使用 Fuel Rust SDK 连接 Fuel 节点:Provider、Testnet/本地 fuel-core 与测试用临时节点全指南
使用 Fuel Rust SDK 连接 Fuel 节点:Provider、Testnet/本地 fuel core 与测试用临时节点全指南 Fuel Rust
区块链后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考