资讯动态

fuels-ts 类型生成实战:fuels typegen 为 Sway 合约、脚本与谓词生成强类型 API

发布时间:2026/9/6 18:22:07 来源:尧图企业网站定制
fuels-ts 类型生成实战fuels typegen 为 Sway 合约、脚本与谓词生成强类型 API【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts本文以 demo-typegen 示例 为核心讲解 fuels-ts 仓库中fuels typegen类型生成Typegen的完整工作流如何从 Sway 合约、脚本script与谓词predicate编译产物中提取 ABI生成 TypeScript 强类型客户端并基于生成的类型完成部署、调用与转账等端到端操作。读完本篇你可以独立在自己的项目里配置forc build与fuels typegen流水线理解--script、--predicate等参数的作用并掌握生成类型的实际调用方式。一、demo-typegen 示例的结构apps/demo-typegen 是 fuels-ts 仓库中一个独立的最小示例包其 README 描述了它的基本组成一个 Sway 程序加一个 TypeScript 项目。结合仓库实际目录当前示例已扩展为三种 Sway 程序类型各一个外加 TypeScript 侧的测试与消费代码apps/demo-typegen/ ├── demo-contract/ │ ├── Forc.toml # Sway 项目清单 │ └── src/main.sw # Sway 合约 ├── demo-script/ │ ├── Forc.toml │ └── src/main.sw # Sway 脚本 ├── demo-predicate/ │ ├── Forc.toml │ └── src/main.sw # Sway 谓词 ├── src/ │ └── demo.test.ts # 消费生成类型的测试即 TypeScript 侧项目 ├── package.json # 构建与类型生成脚本 ├── turbo.json # Turborepo 缓存配置 └── README.md三个 Sway 程序都极其精简正好覆盖 typegen 需要处理的三种程序形态合约demo-contract/src/main.sw——暴露一个回显函数contract; abi DemoContract { fn return_input(input: u64) - u64; } impl DemoContract for Contract { fn return_input(input: u64) - u64 { input } }脚本demo-script/src/main.sw——main直接返回常量script; fn main() - u8 { 10 }谓词demo-predicate/src/main.sw——恒为真的签名校验逻辑predicate; fn main() - bool { true }每个 Sway 项目都有配套的 Forc.toml声明项目名如name demo-contract、入口文件entry main.sw与许可证fuels typegen后续正是依据这些名字去定位编译产物中的 ABI 文件。二、构建流程编译 Sway 并生成类型README 给出的核心命令是pnpm build并注明“详见package.json中的 scripts”。下面完整列出 package.json 中的脚本及其执行顺序这是理解 typegen 流水线的关键。scripts: { pretest: run-s build:forc build:types, build:forc: run-p forc:*, forc:contract: pnpm fuels-forc build -p demo-contract --release, forc:script: pnpm fuels-forc build -p demo-script --release, forc:predicate: pnpm fuels-forc build -p demo-predicate --release, build:types: run-p types:*, types:contract: pnpm fuels typegen -i demo-contract/out/release/demo-contract-abi.json -o src/contract-types, types:script: pnpm fuels typegen -i demo-script/out/release/demo-script-abi.json -o src/script-types --script, types:predicate: pnpm fuels typegen -i demo-predicate/out/release/demo-predicate-abi.json -o src/predicate-types --predicate }流程分两个阶段串行执行run-s串行、run-p并行2.1 阶段一build:forc编译 Sway 程序build:forc通过run-p forc:*并行触发三个 forc 编译任务每个任务形如pnpm fuels-forc build -p demo-contract --release参数说明-p demo-contract指定要编译的 Sway 包对应 Forc.toml 中的name--release以 release 模式编译产物落在包目录/out/release/下包含字节码.bin、ABI包名-abi.json、存储槽位storage_slots.json等。fuels-forc来自 devDependencies 中的internal/forcworkspace 内部包internal/forc作用是安装/调用与当前 fuels-ts 版本匹配的 Forc 编译器保证工具链版本一致。2.2 阶段二build:types生成 TypeScript 类型编译完成后build:types并行运行三个 typegen 任务每个任务对应一种程序类型pnpm fuels typegen -i demo-contract/out/release/demo-contract-abi.json -o src/contract-types pnpm fuels typegen -i demo-script/out/release/demo-script-abi.json -o src/script-types --script pnpm fuels typegen -i demo-predicate/out/release/demo-predicate-abi.json -o src/predicate-types --predicate参数含义参数含义-i path输入 ABI 文件路径即 forc 编译产物中的包名-abi.json-o dir生成类型的输出目录--script声明输入为脚本程序生成脚本调用客户端--predicate声明输入为谓词程序生成谓词客户端无标志默认为合约类型生成合约与合约工厂客户端需要说明的是README 中“类型生成在src/generated-types内”的描述对应早期单合约形态从当前 package.json 的脚本看实际输出已按程序类型分为三个目录src/contract-types、src/script-types、src/predicate-types与测试代码中的导入路径一致。fuels typegen命令的实现位于 packages/fuels/src/cli/commands/build/generateTypes.ts。从源码结构看CLI 将-i指定的 ABI 路径交给fuel-ts/abi-typegen包的runTypegen执行按程序类型分发到不同的模板生成逻辑若未显式指定路径则通过getABIPaths从 Forc 项目目录中自动发现*-abi.json。对于 script 与 predicate它还会额外把out目录下所有*-abi.jsonloader ABI一并纳入生成范围见 generateTypes.ts因为脚本与谓词除业务代码外还有独立的 loader 部分。类型模板与生成引擎主体在 packages/abi-typegen 包中。更完整的参数说明可参考官方文档 generating-types.md 与 using-generated-types.md。三、使用生成的类型从部署到调用demo.test.ts 完整演示了三种生成类型的消费方式。它从fuels导入运行时能力从生成目录导入强类型客户端import { toHex, Address, Wallet, FuelError, ErrorCode } from fuels; import { expectToThrowFuelError, launchTestNode } from fuels/test-utils; import storageSlots from ../demo-contract/out/release/demo-contract-storage_slots.json; import { DemoContract, DemoContractFactory } from ./contract-types; import { DemoPredicate } from ./predicate-types; import type { DemoPredicateInputs } from ./predicate-types/DemoPredicate; import { DemoScript } from ./script-types;注意storageSlots直接来自 forc 编译产物demo-contract/out/release/demo-contract-storage_slots.json这解释了为什么类型生成与 forc 编译必须按pretest脚本中的顺序执行。3.1 合约工厂部署与实例调用生成的合约类型包含两个关键导出DemoContractFactory负责部署与DemoContract已部署合约实例。测试中展示了三种等价的部署/调用路径方式一带存储槽位部署demo.test.tsconst { waitForResult } await DemoContractFactory.deploy(wallet, { storageSlots, }); const { contract } await waitForResult(); expect(contract.id).toBeTruthy();方式二实例化工厂后部署再调用函数const factory new DemoContractFactory(wallet); const deploy await factory.deploy(); const { contract } await deploy.waitForResult(); const contractId contract.id; const { waitForResult } await contract.functions.return_input(1337).call(); const { value } await waitForResult(); expect(value.toHex()).toEqual(toHex(1337));方式三跳过部署用已知合约 ID 直接连接实例demo.test.tsconst contractInstance new DemoContract(contractId, wallet); const call2 await contractInstance.functions.return_input(1337).call(); const { value: v2 } await call2.waitForResult();可以看到return_input(u64) - u64的 Sway 签名被 typegen 映射为强类型的contract.functions.return_input(1337)调用链functions下按函数名组织、.call()发起交易、waitForResult()等待回执并解包返回值。类型层面的函数名、参数个数与返回类型都由 ABI 推导调用侧无需手写 JSON 编码。测试还验证了生成类型的错误边界用无资金的钱包simulate()会抛出INSUFFICIENT_FUNDS_OR_MAX_COINS的FuelError而dryRun()不消耗资金、不会抛错demo.test.ts说明生成的合约客户端与 fuels 的 Provider/资金检查体系是打通的。3.2 脚本以类钱包方式执行 main脚本类型的用法与合约显著不同——没有部署概念直接用钱包构造实例并调用maindemo.test.tsconst script new DemoScript(wallet); const { waitForResult } await script.functions.main().call(); const { value } await waitForResult(); expect(value).toStrictEqual(10);返回值10与 Sway 侧fn main() - u8 { 10 }严格对应。3.3 谓词构造、注资与转出谓词类型的使用分三步demo.test.tsconst receiver Wallet.fromAddress(Address.fromRandom(), provider); // 1. 按 ABI 定义构造谓词输入数据 const predicateData: DemoPredicateInputs []; const predicate new DemoPredicate({ provider, data: predicateData }); // 2. 向谓词地址转入资金 const tx await wallet.transfer(predicate.address, 200_000, await provider.getBaseAssetId()); const { isStatusSuccess } await tx.wait(); // 3. 由谓词转出资金给接收方验证签名成功 const tx2 await predicate.transfer(receiver.address, 50_000, await provider.getBaseAssetId()); await tx2.wait(); expect((await receiver.getBalance()).toNumber()).toEqual(50_000);这里DemoPredicateInputs是 typegen 依据fn main() - bool签名推导出的输入数据类型谓词客户端构造时需要provider与data两个字段之后即可像普通账户一样发起transfer。本示例谓词恒返回true因此转出必然成功真实场景中data会承载签名、白名单地址等校验参数。四、缓存与工程化要点turbo.json 声明了pretest任务的inputsSway 源码与outputsout/release/**编译产物Turborepo 可据此对编译与生成结果做增量缓存依赖上该包仅依赖 workspace 内的fuels运行时与internal/forc编译器工具链见 package.json说明整条 typegen 流水线都可用 fuels-ts 自带的 CLI 完成运行测试即触发完整流程pnpm pretest先build:forc再build:types随后 vitest 执行 demo.test.ts 中的用例。五、小结以 apps/demo-typegen 为骨架fuels-ts 的类型生成工作流可以概括为三步fuels-forc build -p 包名 --release编译 Sway 程序产出*-abi.json等文件fuels typegen -i abi.json -o 输出目录生成类型按程序类型追加--script或--predicate标志在 TypeScript 侧导入生成的工厂/实例类以functions.方法名(...).call()链完成部署、调用与转账。这套机制把 Sway ABI 的编码细节封装在生成代码里开发者获得的是带完整类型提示的调用 API这也是 fuels-ts “先编译、后 typegen、再编码”标准开发流程的最小可运行范例。【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价