在 EVM 链上搭建意图订单#
意图兑换(Intent Swap)下单前,需要对报价接口返回的 signData 对象进行签名,再把签名结果和 signingScheme 一起提交给 创建意图订单 接口。签名方式取决于你的钱包类型:
- EOA 钱包(私钥直接控制的钱包,如 MetaMask、普通热/冷钱包)→ 使用
signingScheme: "eip712" - 智能合约钱包(如 Safe 多签、AA 钱包)→ 使用
signingScheme: "eip1271",签名需要通过 OKX Intent SDK 生成
1. 获取待签名数据#
调用获取意图兑换价格接口,mode=intent,响应里的 signData 就是需要签名的对象,包含 domain、types、message 三部分(标准 EIP-712 TypedData 结构)。
typescript
const quote = await getIntentQuote({ mode: 'intent', /* ...其他报价参数 */ });
const { signData } = quote.data[0];
// signData = { domain, types, message }
2. 方式一:EIP-712 签名(EOA 钱包)#
适用于普通私钥钱包,直接用钱包对 signData 做 eth_signTypedData_v4 签名即可,无需额外 SDK。
typescript
import { ethers } from 'ethers';
const wallet = new ethers.Wallet(PRIVATE_KEY);
// signData.types 里通常包含一个 EIP712Domain 之外的主类型(如 Order),
// ethers v5 的 _signTypedData 需要去掉 EIP712Domain 再传入
const { EIP712Domain, ...types } = signData.types;
const signature = await wallet._signTypedData(
signData.domain,
types,
signData.message
);
// 提交订单
await createIntentOrder({
...orderParams,
signingScheme: 'eip712',
signature,
});
3. 方式二:EIP-1271 签名(智能合约钱包)#
智能合约钱包(如 Safe)没有私钥,验签逻辑由合约自己的 isValidSignature(hash, signature) 方法实现,因此不能直接用 eth_signTypedData 得到的原始签名——需要按你们合约钱包的签名组装规则来生成,这部分逻辑查看 OKX Intent SDK 了解合约验签规则
EIP-1271 需要额外注意的点#
- 验签依赖链上状态:EIP-1271 的
isValidSignature是一次真实的链上只读调用,结果依赖签名验证时刻的合约状态(比如 Safe 的 owner 集合、阈值、是否已 approveHash)。如果报价和提交订单之间合约状态发生变化(换 owner、改阈值),可能导致验签失败,务必在下单前确认钱包状态稳定。 chainIndex必须与合约部署链一致:合约钱包在不同链上地址可能相同但状态不同(不是所有合约钱包都是 CREATE2 counterfactual 部署且状态同步的),下单时的chainIndex决定了会去哪条链验签。- Gas 与延迟:EIP-1271 验签比 EIP-712 纯离线验证多一次 RPC 调用,接入方如果做前端预校验,需要考虑这次调用的延迟和失败重试。
4. 提交订单#
不管哪种签名方式,最终都调用同一个创建意图订单接口,只是 signingScheme 和 signature 的值不同:
typescript
const result = await axios.post(
'https://web3.okx.com/api/v6/dex/aggregator/intent/create-order',
{
chainIndex,
fromTokenAddress,
toTokenAddress,
fromTokenAmount,
toTokenAmount,
userWalletAddress,
validTo,
quoteId,
appData,
signingScheme, // 'eip712' | 'eip1271'
signature,
},
{ headers }
);
