Skip to main content
本快速入门会构建一个最小化的 Flow,将 WETH 交换为 USDC,并将 USDC zap 进一个 Aave 借贷仓位 —— 与 swap-and-zap 配方的形态相同。到最后你将得到一个 ComposeCompileResult,其中包含可供签名的 transactionRequest.data(calldata)。 有关 inputs、handle、materialiser、guard、前置条件(precondition)和提交的完整讲解,请在阅读本页后参见 Build a Flow
你不需要先学会每一个概念。 Composer 有它自己的术语 —— Flowoperationresourceinputmaterialiserguard —— 但本页会在每个术语首次出现在代码中时用一行话解释它。快速浏览一遍,运行示例,只有在你想深入时才去跟进那些链接的概念页面。仅凭这一个示例就足以开始构建和试用 Composer。

先决条件

  • Node.js ≥ 20 和一个 TypeScript 项目(tsctsxts-node 都可以)。
  • 一个在 Ethereum 主网上持有少量 WETH 的 EVM 账户(本示例使用 1 WETH 作为演示)。
  • 签名者的 0x 前缀地址。本快速入门不会发送交易;它止步于已编译的 calldata。签名者接线(viem、ethers 等)在 Build a Flow 中介绍。
  • 一个 LI.FI API key。Composer 处于技术预览阶段,每个请求都经过认证。在 portal.li.fi 注册,并从你的仪表盘创建一个 key。
基础 URL。 公开的 compose 端点由一个专用主机提供;SDK 默认为 https://composer.li.quest。如果你的集成使用暂存或内部环境,请向你的 LI.FI 联系人索取正确的 baseUrl

步骤

1

Install the SDK

@lifi/composer-sdk 包已发布在 npm 上。在稳定版本发布之前,请锁定 alpha 范围。
2

Create the SDK

createComposeSdk 返回一个句柄,其中包含一个 flow 工厂、一个低层 client,以及一个用于自定义 transport 的 request 辅助函数。在技术预览期间,apiKey必需的
3

Build the flow

一个 Flow 就是你在这里构建的文档:一个有序的步骤列表,会编译成一笔交易。你先声明它的 inputs,然后在 builder 上链式调用 operations
  • 一个 input 是 flow 所消费的值。这里的 amountIn 是一个 resource —— 一个代币余额(1 WETH),Composer 会在它于各步骤之间移动时对其进行跟踪。(Input 也可以是普通的标量,比如一个 uint256 或一个 address。)
  • 一个 operationop)是 flow 中的一个具名步骤,比如一次交换或一次存入。builder.lifi.swapbuilder.lifi.zap 都是 op;zapswap 的输出绑定为它自己的输入,把两者串接在一起。这两个只是完整 op 目录中的一小部分。
Input 名称和节点 id(每个 op 的第一个参数)由你自行选择 —— 它们会成为你绑定运行时值的键,以及下游 op 引用的句柄。
有关 import 和地址常量,请参见下方的完整示例
4

Compile the flow

builder.compile(run) 会将 flow 发送到 POST /compose,对其进行模拟,并返回一个 ComposeCompileResult,其中包含你的用户签名所需的 calldata。这里的 inputs 映射为 flow 声明的每个 input 提供了具体的运行时值。directDeposit 是一个 materialiser —— 一个小描述符,告诉 Composer 在执行时如何获取代币(这里是通过 transferFrom 将恰好 1 WETH 拉进代理)。sweepTo 说明当 flow 结束时剩余余额去往何处。
result.transactionRequest 就是你交给钱包的东西:
to 地址是你的每用户执行代理 —— 与 userProxy 相同的值。在代理首次使用时,它反而是代理工厂,工厂会部署你的代理并在一笔交易中运行 flow。无论哪种方式,代理都会 delegatecall 共享的 Composer VM,因此 flow 在你自己代理的余额和存储上下文中执行。每条链上的 VM 和代理工厂地址在 Addresses 页面上。除了 transactionRequest,结果还携带 userProxy(执行地址)、producedResources(每个终端资源的模拟金额),以及签名者必须首先授予的任何 approvals

完整示例

改编自 composer-sdk-examples 仓库中的 swapAndZap.ts
完整示例增加了步骤中没有的一个术语:一个 guard。zap 上的 guards.slippage({ port: 'amountOut', bps: 100 }) 是一个 Composer 在执行期间强制执行的不变量 —— 这里是对 zap 输出的 1% 滑点下限 —— 因此 flow 会安全地失败,而不是以糟糕的条件执行。交换不需要 guard:它的 slippage: 0.03 配置已经将一个下限烘焙进了报价。

SDK 构建了什么

builder.compile(run) 不只是调用端点 —— 它会将带类型的 builder 状态序列化为线格式(wire-format)的 Flow 文档,将其发送到 POST /compose,并解析响应。如果你想看看线上实际是什么样子,把 builder.compile(run) 换成 builder.build()
这就是 compose 端点接收到的 Flow 文档。你在这里看到的每个 input 名称(amountIn)、节点 id(swapzap)和 $ref 都恰好是你在上面 builder 中所写的 —— SDK 不会重命名或重写。有关完整的线格式参考,请参见 Flow Structure

你拿回了什么

ComposeCompileResult 是一个基于 status可辨识联合(discriminated union)。在读取形态专属字段之前先对它进行分支:
status: 'success' 时,载荷包含:
  • transactionRequest —— { to, data, value, gasLimit? }to 是你的执行代理(在代理首次使用时是代理工厂);data 是代理 delegatecall 进 VM 的 calldata。
  • userProxy —— 预测的执行代理地址(由代理工厂派生的一个确定性的每签名者合约;参见 Account model)。
  • producedResources —— 终端资源名称到每个资源记录的映射。模拟金额位于 <resource>.simulated?.amountOut<resource>.simulated?.amountOutMin
  • approvals —— 签名者在执行交易之前必须授予的 ERC-20 授权(不需要时省略)。
  • priceImpact —— 当在 run 上设置了 maxPriceImpactBps 时,可选的美元价格影响明细。
status: 'partial' 时,载荷还额外携带 error{ kind, message })和 simulationRevert。仅当你在 run 上传入 simulationPolicy: 'allow-revert' 时才会返回这种形态;在默认的 'strict' 策略下,回滚会转而抛出一个 ComposeError

后续步骤

你现在已经在实践中见过每一个核心概念 —— Flow、operation、resource、input、materialiser、guard。上面的示例足以开始试用。当你想要全面了解其中任何一个时,以下页面会更深入:
  • Build a Flow —— inputs、handle、materialiser、guard、前置条件和提交的完整讲解。
  • Flow Structure —— 你的 builder 所产生的 JSON 文档形态。
  • References —— handle 如何在线上变成 $ref 字符串。
  • Recipes —— 三种典型的 flow 形态(Dust Sweep、Swap and Deposit、Split Deposits)。