SDK 可编译
测试覆盖率
| 发言 | 分支 | 职能 | 行数 |
|---|---|---|---|
这个软件包为CoW协议提供了高级的有条件和可编程的命令功能. 它通过在满足特定条件时自动执行的有条件命令,得以制定、管理和执行复杂的交易战略.
安装
npm install @cowprotocol/sdk-composable
or
pnpm add @cowprotocol/sdk-composable
or
yarn add @cowprotocol/sdk-composable
读取 TWAP 历史
import { ProgrammaticOrderApi } from '@cowprotocol/sdk-composable'
import { SupportedChainId } from '@cowprotocol/sdk-config'
const api = new ProgrammaticOrderApi()
const { items: twaps } = await api.getTwapOrders({
resolvedOwner: '0x...',
chainId: SupportedChainId.GNOSIS_CHAIN,
})
const { items: parts } = await api.getTwapPartOrders(
{
eventId: twaps[0].eventId,
chainId: SupportedChainId.GNOSIS_CHAIN,
},
{
offset: 0,
limit: 10,
direction: 'desc',
},
)
两种方法返回 QueryPage<T> 并接受可选 QueryOptions (单位:千美元)offset, (中文(简体) ), limit, (中文(简体) ), direction) (中文(简体) ). 父结果包括执行总数和索引部分计数;通过返回 eventId 以获取部件.
核心组成部分
有条件的命令事实
以登记为基础的制造不同类型的有条件订单的工厂:
import { ConditionalOrderFactory } from '@cowprotocol/sdk-composable'
const factory = new ConditionalOrderFactory(registry, adapter)
const conditionalOrder = factory.fromParams(orderParams)
多轴
使用 merkle 树管理批次的有条件订单 :
import { Multiplexer } from '@cowprotocol/sdk-composable'
const multiplexer = new Multiplexer(chainId, orders, root, location)
const proofs = multiplexer.dumpProofsAndParams()
有条件的命令
执行自定义条件排序类型的基础类 :
import { ConditionalOrder } from '@cowprotocol/sdk-composable'
class CustomOrder extends ConditionalOrder<DataType, StaticType> {
// Implement custom conditional logic
}
JIT 波尔勒
一揽子出口公用事业需要与部署的公用事业结合起来 ComposableCowPoller. Poller 移动从一个供资账户(通常为EOA)及时向可编译的 CoW 订单拥有者/交易者出售代币。 这避免了要求交易员账户为全程预留资金,减少了设置摩擦和闲置资本.
该套件暴露出两个Poller API:低等 ComposableCowPoller 下面只读到状态和编码调用数据,而 ComposableCowPollerSdk 通过配置的适配器添加签名和交易提交.
import { ComposableCowPoller, type ComposableCowPollerSchedule } from '@cowprotocol/sdk-composable'
import { setGlobalAdapter } from '@cowprotocol/sdk-common'
setGlobalAdapter(adapter)
const poller = new ComposableCowPoller(pollerAddress)
const schedule: ComposableCowPollerSchedule = {
handler,
authEpoch,
funder,
owner,
salt,
staticInput,
}
const scheduleId = poller.getScheduleId(schedule)
// Submit this calldata to pollerAddress from schedule.funder.
const registerCalldata = poller.encodeRegister(schedule)
// Anyone may submit this calldata to pollerAddress when the next order part needs funding.
const pollFundsCalldata = poller.encodePollFunds(scheduleId)
// Or authorize registration for submission by another account.
const deadline = Math.floor(Date.now() / 1000) + 15 * 60
const typedData = poller.getRegisterTypedData({ chainId, schedule, deadline })
const signature = await adapter.signer.signTypedData(typedData.domain, typedData.types, typedData.message)
const signedRegisterCalldata = poller.encodeRegisterWithSignature(schedule, deadline, signature)
// Direct revocation must be submitted by schedule.funder.
const revokeCalldata = poller.encodeRevoke(schedule)
// Or authorize revocation for submission by another account.
const revokeAuthorization = {
handler: schedule.handler,
authEpoch: schedule.authEpoch,
funder: schedule.funder,
owner: schedule.owner,
salt: schedule.salt,
}
const revokeDeadline = Math.floor(Date.now() / 1000) + 15 * 60
const revokeTypedData = poller.getRevokeTypedData({
chainId,
...revokeAuthorization,
deadline: revokeDeadline,
})
const revokeSignature = await adapter.signer.signTypedData(
revokeTypedData.domain,
revokeTypedData.types,
revokeTypedData.message,
)
const signedRevokeCalldata = poller.encodeRevokeWithSignature(revokeAuthorization, revokeDeadline, revokeSignature)
安装 CowShed 软件包以获取一个与 Poller 兼容的账户 :
npm install @cowprotocol/sdk-cow-shed
配置 CowShedSdk 与可编译的CoW工厂. 它必须匹配 poller.getCowShedFactoryAddress()。 。 。 .
import {
COW_SHED_FACTORY_FOR_COMPOSABLE_COW,
COW_SHED_IMPLEMENTATION_FOR_COMPOSABLE_COW,
COW_SHED_LATEST_VERSION,
CowShedSdk,
} from '@cowprotocol/sdk-cow-shed'
const cowShedSdk = new CowShedSdk(adapter, {
factoryAddress: COW_SHED_FACTORY_FOR_COMPOSABLE_COW[COW_SHED_LATEST_VERSION],
implementationAddress: COW_SHED_IMPLEMENTATION_FOR_COMPOSABLE_COW[COW_SHED_LATEST_VERSION],
})
const cowShed = cowShedSdk.getCowShedAccount(chainId, funder)
从出资人自己的CowShed注册, 将Poller的呼叫包含在一个签名的捆绑。 计程车的车主必须和牛舍一样 签名前刷新此调度 ID 的时代 .
const shedSchedule = { ...schedule, owner: cowShed }
const { authEpoch: shedAuthEpoch } = await poller.getSchedule(poller.getScheduleId(shedSchedule))
const registration = await cowShedSdk.signCalls({
chainId,
signer,
calls: [
{
target: pollerAddress,
callData: poller.encodeRegisterFromShed({ ...shedSchedule, authEpoch: shedAuthEpoch }),
value: 0n,
isDelegateCall: false,
allowFailure: false,
},
],
})
从出资人自己的"牛舍"中撤销,将"波勒"的电话收录在了签名的捆绑中. 使用原始调度身份并刷新其签署前的时代 。 退位并不要求日程所有者与"牛舍"持平.
const { authEpoch: revokeAuthEpoch } = await poller.getSchedule(scheduleId)
const revocation = await cowShedSdk.signCalls({
chainId,
signer,
calls: [
{
target: pollerAddress,
callData: poller.encodeRevokeFromShed({ ...schedule, authEpoch: revokeAuthEpoch }),
value: 0n,
isDelegateCall: false,
allowFailure: false,
},
],
})
使用 ComposableCowPollerSdk 通过配置的适配器签名或提交交易。 内容 poller 属性暴露出相同的低等调用数据并读取上述方法。 用这个 schedule,在下面选择直接流或签名流;不为同一登记运行两者.
import { ComposableCowPollerSdk } from '@cowprotocol/sdk-composable'
const pollerSdk = new ComposableCowPollerSdk({ chainId, pollerAddress, signer }, adapter)
const deadline = Math.floor(Date.now() / 1000) + 15 * 60
// Direct flow: use the SDK signer, or the adapter signer when none was configured.
const transaction = await pollerSdk.register({ schedule })
await transaction.wait()
// Signature flow: keep the intended schedule and refresh only its replay-protection epoch.
const { authEpoch } = await pollerSdk.poller.getSchedule(scheduleId)
const currentSchedule = { ...schedule, authEpoch }
const authorization = await pollerSdk.signRegister({ schedule: currentSchedule, deadline })
// authorization.calldata is ready for a hook or relayed transaction.
// authorization.typedData and authorization.signature are also available for inspection.
// Alternatively, submit the authorization now with a relayer signer.
const relayedTransaction = await pollerSdk.registerWithSignature({
schedule: currentSchedule,
deadline,
signature: authorization.signature,
signer: relayerSigner,
})
await relayedTransaction.wait()
signRevoke 遵循相同的签名流程并签名所提供的时间表身份 authEpoch仅刷新 authEpoch 与 pollerSdk.poller.getSchedule(scheduleId) 在签署之前; 一个不活动的时间表保留其时代而不是其他字段.
考克谢德注册,请通过 cowShedSdk 上方配置 。 SDK 使用它配置的标志器, 当没有配置时使用适配器标志器, 或每个调用 signer 超过。 那个签人必须是日程的出资人,日程的主人必须是它的"牛舍".
const registrationSchedule = { ...schedule, owner: cowShed }
const { authEpoch: registrationEpoch } = await pollerSdk.poller.getSchedule(
pollerSdk.poller.getScheduleId(registrationSchedule),
)
const shedRegistrationParams = {
cowShedSdk,
schedule: { ...registrationSchedule, authEpoch: registrationEpoch },
deadline: BigInt(Math.floor(Date.now() / 1000) + 15 * 60),
}
// Sign only: hand this factory transaction to a relayer or hook.
const signedRegistration = await pollerSdk.signRegisterFromShed(shedRegistrationParams)
// signedRegistration includes cowShedAccount, signedMulticall and gasLimit.
// Alternative: sign and submit now; the resolved signer pays transaction gas.
const shedRegistrationTx = await pollerSdk.registerFromShed(shedRegistrationParams)
await shedRegistrationTx.wait()
选择其中的一种流 。 两人都签了"牛舍"捆绑单波勒电话. 工厂根据需要创建了"牛舍"(CowShed),并从中执行注册. 他们接受牛舍德的 nonce, (中文(简体) ), deadline, (中文(简体) ), signingScheme, (中文(简体) ), gasLimit,以及 defaultGasLimit 选项。 没有气体覆盖, CowShed 估计气体; 失败拒绝调用, 除非提供倒计时。 对于包含其他呼叫的捆绑,使用 pollerSdk.poller.encodeRegisterFromShed 与 cowShedSdk.signCalls。 。 。 .
对于CowShed的撤销,保留原始的排行表身份,包括它的主人,即使它不同于CowShed. 决心的签名者必须是资助者. 签名前刷新时代 :
const { authEpoch: revocationEpoch } = await pollerSdk.poller.getSchedule(scheduleId)
const shedRevocationParams = {
cowShedSdk,
handler: schedule.handler,
funder: schedule.funder,
owner: schedule.owner,
salt: schedule.salt,
authEpoch: revocationEpoch,
deadline: BigInt(Math.floor(Date.now() / 1000) + 15 * 60),
}
// Sign only: return the factory bundle for a relayer or hook.
const signedRevocation = await pollerSdk.signRevokeFromShed(shedRevocationParams)
// Alternative: sign and submit now; the resolved signer pays transaction gas.
const shedRevocationTx = await pollerSdk.revokeFromShed(shedRevocationParams)
await shedRevocationTx.wait()
选择一流. signRevokeFromShed 返回时 cowShedAccount, (中文(简体) ), signedMulticall,以及 gasLimit 不提交。 两种方法都接受与注册相同的签注和CowShed选项. 对于包含其他通话的捆绑,请使用 pollerSdk.poller.encodeRevokeFromShed 与 cowShedSdk.signCalls。 。 。 .
时间表字段为:
handler: 注册的有条件命令的处理者.authEpoch: 调度 ID 当前重放保护时代; 它从零开始,并在撤销时递增.funder: Poller从中提取出销售信使的账户.owner: 接收这些令牌的可编程 CoW 有条件命令所有者 .salt:注册的有条件订单的盐.staticInput:已注册的条件令被编码为静态输入.
低层 ComposableCowPoller 仅编码这些交易;其消费者拥有签名、天然气政策、提交和确认。 将直接注册和撤销调用数据提交 pollerAddress 从 schedule.funder,或提交 signedRegisterCalldata 或者说 signedRevokeCalldata 通过中继器。 已签名的注册呼叫数据包含时间表、截止日期和签名。 已签名的撤销调用数据包含处理者、供资者、所有者、盐、, authEpoch、截止日期和签名。 重放保护范围为列表 ID 通过 authEpoch启用 poller.getComposableCowAddress() 财务报告和审定财务报表 poller.getSchedule(scheduleId) 读取 Poller 状态.
使用量
import { ConditionalOrderFactory, Multiplexer, ConditionalOrder, ProofLocation } from '@cowprotocol/sdk-composable'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
// Configure the adapter
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
// Create a conditional order factory
const registry = {
twap: TWAPOrderFactory,
dca: DCAOrderFactory, // WIP: not implemented
// ... other order types
}
const factory = new ConditionalOrderFactory(registry, adapter)
// Create conditional orders
const twapOrder = factory.fromParams({
handler: TWAP_HANDLER_ADDRESS,
salt: '0x...',
staticInput: encodedTWAPData,
})
// Create multiplexer for batch management
const orders = {
order1: twapOrder,
// ... more orders
}
const multiplexer = new Multiplexer(SupportedChainId.MAINNET, orders, merkleRoot, ProofLocation.PRIVATE)
// Generate proofs for off-chain storage
const proofs = multiplexer.dumpProofsAndParams()
有条件的顺序类型
TWAP(时间加权平均价格)
逐步执行交易,以达到更好的平均价格:
const twapOrder = new TWAPOrder({
handler: TWAP_HANDLER,
sellToken: '0x...',
buyToken: '0x...',
sellAmount: '1000000000000000000',
numOfParts: 10,
timeInterval: 3600, // 1 hour intervals
startTime: Math.floor(Date.now() / 1000),
span: 0, // Execute indefinitely
})
DCA(Dollar Cost Avering)——世界投资方案
DCAOrder尚未执行或导出.
按预定的间隔定期买卖资产:
const dcaOrder = new DCAOrder({
handler: DCA_HANDLER,
sellToken: '0x...', // USDC
buyToken: '0x...', // ETH
sellAmount: '100000000', // $100 USDC
timeInterval: 86400, // Daily
numOfParts: 30, // For 30 days
})
停止损失命令——WIP
StopLossOrder尚未执行或导出.
价格低于阈值时自动销售 :
const stopLossOrder = new StopLossOrder({
handler: STOP_LOSS_HANDLER,
sellToken: '0x...', // ETH
buyToken: '0x...', // USDC
sellAmount: '1000000000000000000', // 1 ETH
strikePrice: '2000000000', // Trigger at $2000
})
高级特性
默克勒树管理
// Create multiplexer with multiple orders
const multiplexer = new Multiplexer(
SupportedChainId.MAINNET,
conditionalOrders,
undefined, // Will generate merkle root
ProofLocation.PRIVATE,
)
// Get merkle root for on-chain storage
const root = multiplexer.getOrGenerateTree().root
// Generate proofs for specific orders
const proofs = multiplexer.dumpProofsAndParams((order) => {
return order.isActive // Only include active orders
})
顺序验证
// Check if conditional order is valid
const validationResult = await conditionalOrder.isValid({
owner: userAddress,
ctx: contextData,
})
if (validationResult.isValid) {
// Order can be executed
const tradeableOrder = await conditionalOrder.poll({
owner: userAddress,
proof: merkleProof,
provider: provider,
})
}
依附关系
// Orders that depend on external data
const conditionalOrder = new PriceBasedOrder({
handler: PRICE_HANDLER,
// ... order parameters
})
// Get context dependency (e.g., price oracle)
const contextDependency = conditionalOrder.getContextDependency()
// Poll with off-chain input
const [orderData, signature] = await ConditionalOrder.poll(
owner,
proofWithParams,
chainId,
provider,
async (owner, params) => {
// Fetch off-chain data (prices, etc.)
return await fetchOffChainInput(params)
},
)
登记管理
// Register custom order types
const registry = {
'custom-twap': CustomTWAPOrder,
'limit-order': LimitOrder,
'bracket-order': BracketOrder,
}
const factory = new ConditionalOrderFactory(registry, adapter)
// Register new order type dynamically
Multiplexer.registerOrderType('new-order-type', NewOrderClass)
智能合同集成
可编程 CoW 一体化
// Set merkle root on ComposableCoW contract
const composableCowContract = adapter.getContract(COMPOSABLE_COW_CONTRACT_ADDRESS[chainId], ComposableCowABI)
// Set root with context
await composableCowContract.setRootWithContext(root, contextFactory, contextData)
证明生成和储存
// Generate proofs for watchtowers/indexers
const proofsData = multiplexer.dumpProofs((order) => {
// Filter criteria for proof inclusion
return order.status === 'active'
})
// Store proofs off-chain (IPFS, etc.)
await uploadProofs(proofsData)
// Verify proofs on-chain when executing
const isValidProof = multiplexer.getOrGenerateTree().verify(proof, leafData)
完成 TWAP 设置
// 1. Create TWAP order
const twapOrder = new TWAPOrder({
sellToken: WETH_ADDRESS,
buyToken: USDC_ADDRESS,
sellAmount: parseEther('10'), // 10 WETH
numOfParts: 24, // 24 parts
timeInterval: 3600, // 1 hour intervals
startTime: Math.floor(Date.now() / 1000),
})
// 2. Create multiplexer
const multiplexer = new Multiplexer(SupportedChainId.MAINNET)
multiplexer.addOrder('twap-1', twapOrder)
// 3. Set root on ComposableCoW
const root = multiplexer.getOrGenerateTree().root
await composableCowContract.setRoot(root)
// 4. Generate proofs for watchtower
const proofs = multiplexer.dumpProofsAndParams()
await storeProofsOffChain(proofs)
说明: 这个软件包通过可编程的有条件订单,可以实现高级交易策略. 它为需要自动执行复杂交易逻辑的精密用户所设计. 大多数基本贸易需要可以通过贸易SDK来解决.