KyberSwap
接入KyberSwap聚合器:报价和交易数据来自KyberSwap Aggregator API(在众多DEX和做市商之间拆单选路,API Key可选,见下文「API Key与限频」),由托管者用配置的私钥签名后发给KyberSwap的路由合约MetaAggregationRouterV2(0x6131B5fae19EA4f9D964eAc0408E4408b66337b5)。一个交易所对象对应一条链,可选Ethereum、Arbitrum、Base、BNB Chain、Unichain、Polygon、OP Mainnet、Robinhood。
它与Uniswap交易所对象是同一套实现的聚合器版本:代币表、余额、授权、订单、撤单、转账与包装的用法都相同,区别是兑换路径由KyberSwap给出。
名称与配置
exchange.GetName():KyberSwap(现货);别名:Kyber。
| 配置项 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| 链 | 是 | Ethereum | 可选:Ethereum、Arbitrum、Base、BNB Chain、Unichain、Polygon、OP Mainnet、Robinhood |
| 钱包私钥 | 是 | — | 钱包私钥(十六进制)。 |
| 节点地址 | 否 | https://ethereum-rpc.publicnode.com,https://eth.drpc.org | RPC节点地址;多个节点用逗号分隔,某个节点出错或缺少数据时自动换下一个;不填时使用各链内置的默认节点(主节点加备用节点,逗号分隔)。(详见表下) |
| 节点认证 | 否 | — | RPC节点认证:Header-Name: value形式的请求头,或Basic认证值。 |
| KyberSwap Api Key | 否 | — | KyberSwap Aggregator API的API Key,可选。(详见表下) |
表中长说明的其余部分:
- 节点地址:查询订单状态需要节点能查到已上链交易的回执:publicnode的Base、BNB Chain、Arbitrum公共节点查不到回执(要求归档权限),不要单独使用。
- KyberSwap Api Key:填写后报价与生成交易走KyberSwap的API网关(请求头
X-Api-Key),限频更高;不填使用公开端点(每秒约3次)。获取方式与限频见下文「API Key与限频」,运行中可用exchange.IO("kyberApiKey", key)更换。
交易对与合约代码
交易对示例:ETH_USDC、WETH_USDC、ETH_USDG
交易对写作ETH_USDC,原生币(ETH、BNB、POL)与包装币(WETH、WBNB、WPOL)是两个不同的资产。Polygon的原生币为POL;Robinhood链上没有USDC和USDT,主流稳定币为USDG,交易对写作ETH_USDG;Unichain、Polygon上的USDT写作USDT0。
代币表沿用该链Uniswap交易所对象的代币表,表外的代币用exchange.IO("token", name, address)登记后即可写在交易对里;exchange.GetMarkets()列出代币表中在该链Uniswap上有池子的交易对。
专属IO指令
| 指令 | 参数 | 说明 | 返回值 |
|---|---|---|---|
transfer | to, amount[, token] | 从配置的钱包转出原生币或ERC20代币(token为代币名或合约地址,不传为原生币);amount可传all转出全部(原生币扣除手续费)。只等交易广播,不等上链。见子页exchange.IO("transfer", ...)。 | {txHash, from, to, token, tokenAddress, amount, raw} |
receipt | txHash[, waitMs] | 查询本链任意交易的回执(不限本交易所对象发出的),可以等待上链(最多10分钟)。查询订单时传订单ID中逗号后面的交易哈希。见子页exchange.IO("receipt", ...)。 | 已上链返回{txHash, status, blockNumber, gasUsed, fee}(status为success或reverted),未上链返回{txHash, pending: true, known}。 |
route | symbol, side, qty | 只询价不下单。聚合器只有一条候选路径(形如kyberswap:ETH-USDC);buy按买到qty个base询价(由多次精确输入询价近似),sell按卖出qty个base询价。见子页exchange.IO("route", ...)。 | {symbol, side, qty, best, quote, price, candidates} |
simulate | symbol, side, qty[, price[, stateOverride]] | 按下单逻辑(询价、价格保护、向KyberSwap生成交易)构造兑换交易,只用eth_call模拟执行,不签名、不广播、不花费gas;这时的路径描述中列出经过的流动性来源。见子页exchange.IO("simulate", ...)。 | {route, exactIn, amountIn, amountOut, quoted, executed, value, calls},补过授权时另有allowanceOverride。 |
token | [name, address] | 登记代币,登记后的代币可以直接写在交易对里;不传参数时列出代币表。见子页exchange.IO("token", ...)。 | 登记时返回{symbol, address, decimals},列表时返回{symbol, address, decimals, native}数组。 |
wrap | amount | 原生币包装成包装币(例如ETH→WETH),1:1、无滑点、只花gas;不接受all(要留gas)。见子页exchange.IO("wrap", ...)。 | {txHash, action, from, to, amount, raw} |
unwrap | amount | 包装币解包成原生币(例如WETH→ETH),amount可传all。见子页exchange.IO("unwrap", ...)。 | {txHash, action, from, to, amount, raw} |
approve | ["exact" | "max"] | 代币授权模式(代币直接授权给KyberSwap路由合约,不经过Permit2):exact(默认)每次只授权本次兑换需要的数量,max授权无限额度。不传参数时查询。见子页exchange.IO("approve", ...)。 | 当前模式。 |
slippage | [ratio] | 市价单的滑点保护比例,范围[0, 0.5),默认0.005(0.5%)。不传参数时查询。见子页exchange.IO("slippage", ...)。 | 当前滑点比例。 |
deadline | [seconds] | 交易有效期(秒),范围10到86400,默认120。不传参数时查询。生成兑换交易时把有效期传给KyberSwap。见子页exchange.IO("deadline", ...)。 | 当前截止时间(秒)。 |
cancelWait | [seconds] | 撤单时等待结果的最长时间(秒),范围0到600,默认30;0表示发出撤单交易后立即返回。不传参数时查询。见子页exchange.IO("cancelWait", ...)。 | 当前等待时间(秒)。 |
gasMultiplier | [x] | gas上限倍数,范围1到5,默认1.2:交易的gasLimit为节点估算的gas乘以该倍数。gasLimit只是上限,实际按用量扣费。不传参数时查询。见子页exchange.IO("gasMultiplier", ...)。 | 当前倍数。 |
base | [url] | 不传参数时返回当前节点地址;传入地址时切换节点。多个节点写成逗号分隔的字符串(传数组时只使用第一个地址)。换节点后第一次请求会核对节点所在的链,与配置的链不一致时报错。 | 切换前的地址。 |
sendBase | url | 设置只用来广播交易的节点(私有交易通道)。与Web3不同:不返回设置前的地址,不传参数时不查询,传空字符串不会清除设置。 | true |
address | — | 配置的私钥对应的钱包地址(0x开头的小写地址)。 | — |
contracts | — | 本链上的部署信息,字段与Uniswap交易所对象相同:dex为KyberSwap,router为KyberSwap路由合约;quoterV2、v3Factory、v4等是该链Uniswap的部署(用来列出市场、估算美元价),aerodrome为null;tokenList给出内置代币表的生成时间与本链代币数量。 | — |
bridge.chains | — | 跨链桥(LI.FI)支持的链:EVM链与Solana,缓存1小时。见子页exchange.IO("bridge.*", ...)。 | {id, key, name, chainType, nativeToken}数组,chainType为EVM或SVM。 |
bridge.tokens | [chain] | LI.FI认识的某条链上的代币(缺省为本链),缓存1小时。见子页exchange.IO("bridge.*", ...)。 | {symbol, address, decimals, name, priceUSD}数组。 |
bridge.quote | params | 跨链报价(只读),源链为本交易所对象的链。见子页exchange.IO("bridge.*", ...)。 | {tool, toolName, fromChain, toChain, toChainName, fromToken, toToken, fromAmount, toAmount, toAmountMin, fromAmountRaw, toAmountRaw, toAmountMinRaw, fromAmountUSD, toAmountUSD, slippage, toAddress, feeCosts, gasCosts, executionDuration, approvalAddress, steps, transactionId, request}:数量为代币单位(*Raw为最小单位原值);toAmountMin为扣除滑点后保证到手的数量;feeCosts为[{name, amount, token, amountUSD, percentage, included}](included为false的费用另付);gasCosts为源链gas估算;executionDuration为预计耗时(秒);approvalAddress为需要授权的合约(原生币、Solana为null);steps为各步骤(cross为跨链,swap为兑换);request为参数原样回显。 |
bridge.simulate | params|quote[, stateOverride] | 重新报价,用eth_call执行LI.FI给出的交易,不签名、不广播、不花gas。见子页exchange.IO("bridge.*", ...)。 | bridge.quote的结果,另有simulated(true)、to、value、walletBalance,补过授权时有allowanceOverride。 |
bridge.send | params|quote | 跨链转出:重新报价 → 检查余额 → 代币对LI.FI的approvalAddress授权不够时先授权(按exchange.IO("approve")的exact/max,USDT这类先清零,等授权上链;授权过就再报价一次)→ eth_call模拟 → 签名广播;gasLimit取eth_estimateGas估算×gasMultiplier与LI.FI建议的gasLimit中较大的一个(桥合约还会调用别的合约,估算可能偏少),实际只按用量扣费。见子页exchange.IO("bridge.*", ...)。 | {txHash, tool, fromChain, toChain, toChainName, fromToken, toToken, fromAmount, toAmount, toAmountMin, toAddress, value, transactionId},txHash为源链交易哈希,可用receipt查回执。 |
bridge.status | txHash[, options] | 跨链进度(LI.FI /status),参数为bridge.send返回的源链交易哈希;options可给{toChain, bridge}加快查找。见子页exchange.IO("bridge.*", ...)。 | {status, substatus, substatusMessage, tool, sending, receiving, fromAddress, toAddress, explorer, bridgeExplorer}:status为NOT_FOUND、INVALID、PENDING、DONE、FAILED;DONE时substatus为COMPLETED(按报价到账)、PARTIAL(收到的是别的代币)或REFUNDED(已退回);sending、receiving为{txHash, txLink, chainId, amount, amountRaw, token, timestamp},receiving.amount与receiving.token为实际到账的数量与代币。 |
bridge.apiKey | [key] | 设置LI.FI的API Key(请求头x-lifi-api-key,只对本交易所对象生效,不回显),传""清除;不传参数只查询。没有Key时按出口IP限频,见下文。见子页exchange.IO("bridge.*", ...)。 | 是否已设置Key(布尔值)。 |
clientId | [id] | 设置请求KyberSwap Aggregator API时携带的客户端标识(请求头x-client-id,设置了API Key时也照发),只能是字母、数字、.、_、-,1到64个字符。(详见表下) | 当前的客户端标识。 |
kyberApiKey | [key] | 设置KyberSwap的API Key(只对本交易所对象生效,不回显),与配置项KyberSwap Api Key相同:设置后报价与生成交易改走KyberSwap的API网关https://api.kyberswap.com/swap,请求头带X-Api-Key,限频更高;传""清除,回到公开端点。(详见表下) | 是否已设置Key(布尔值)。 |
表中长说明的其余部分:
clientId:没有API Key时KyberSwap的公开限频按这个标识计算(每秒3次),共用同一个标识的程序共用这份额度,频繁报HTTP 429时可以换成自己的标识,或设置API Key(见kyberApiKey)。默认值为fmz-加钱包地址哈希的前8位十六进制(同一钱包重启后不变,不包含地址本身;没配私钥时为本次运行随机生成的值)。不传参数时查询。kyberApiKey:Key只能是1到256个不含空格的可见ASCII字符,不合法时报错且原设置不变。不传参数只查询。Key无效或过期时,网关返回HTTP 401,报错KyberSwap API key rejected (HTTP 401: invalid api key),不会自动退回公开端点。
通用指令currency见exchange.IO。
不支持通用指令api(调用时报错并返回空值)。
函数支持差异
不支持(调用时报错并返回空值):exchange.GetTickers、exchange.GetHistoryOrders、exchange.ModifyOrder、exchange.CreateConditionOrder、exchange.ModifyConditionOrder、exchange.CancelConditionOrder、exchange.GetConditionOrder、exchange.GetConditionOrders、exchange.GetHistoryConditionOrders、exchange.GetTrades。
以回退方式支持:
exchange.GetRecords:原生周期为1分钟、5分钟、15分钟、1小时、4小时、12小时、1天(GeckoTerminal的周期);其它分钟级以上的周期由托管者合成,秒级周期不可用(没有成交记录接口可供合成)。
注意事项
| 函数 | KyberSwap交易所的行为 |
|---|---|
| exchange.GetTicker() | 买一、卖一为约1000美元规模的KyberSwap报价;没有24小时统计。两个方向分别询价,最优来源可能不同(如Base上不同的做市商报价),两边各自可成交却偶尔交叉(买一高于卖一),这时两边都给中间价,Info.crossed写明交叉幅度 |
| exchange.GetDepth() | 由KyberSwap在逐档递增规模上的报价推算(每档买卖各询价一次,询价之间排队、限流时退避重试,档数多时耗时相应增加,10档约20秒);中途询价失败时返回已经拿到的档位(不补档),Info.partial说明原因,一档都没拿到才报错;买卖两边的最优来源不同而交叉时,交叉的价格按中间价给出、数量不变,Info.crossed写明中间价与交叉幅度 |
| exchange.GetRecords() | K线来自GeckoTerminal的池子级数据:聚合器没有自己的池子,取GeckoTerminal上该交易对(不限DEX)美元流动性最深的池子(在两个代币各自靠前的20个池子里找两边正好是这对币的,选中的池子缓存1小时)。价格为该池子的逐笔成交价(含池子手续费,与exchange.GetTicker()的中间价可能相差约一个池子费率),单位为计价币/基础币,Volume为基础币数量;没有成交的周期按上一根收盘价补平、成交量为0,最后一根可能尚未收盘。GeckoTerminal的数据有几十秒到1分钟的延迟,公开接口约每分钟10次:同一周期的K线缓存1分钟,请求在托管者内排队,被限频时等待重试,仍不行时报错。GeckoTerminal上找不到该交易对的池子时报错 |
| exchange.GetAssets() | 原生币和代币表中各代币的钱包余额 |
| exchange.CreateOrder() | 立即在链上兑换:限价为最差成交价,市价按滑点保护;市价买入时数量为要花费的计价币。KyberSwap只支持精确输入:限价买入按“最多花费数量×价格、至少买到数量”执行,实际买到的数量可能略多于下单数量。下单附加参数slippage覆盖本单滑点;route对聚合器不适用,传入会报错route is not applicable to the KyberSwap aggregator |
| exchange.GetOrder() | 订单ID形如ETH_USDC,0x…(交易对、逗号、交易哈希),状态来自交易回执;原交易的nonce已被撤单交易(或其它交易)占用时显示为已撤销。成交量取路由合约的Swapped事件(原生币进出也在其中) |
| exchange.GetOrders() | 只列出本交易所对象在本次运行中发出、尚未上链的兑换交易 |
| exchange.CancelOrder() | 发送同nonce的替换交易(向自己转0金额),并等待结果(默认最多30秒,见exchange.IO("cancelWait", ...)):撤单交易先上链返回true;原订单已经上链或先于撤单上链时返回false(撤单没成功,但不是调用错误),原因见exchange.GetLastError();等待超时返回true,表示撤单已提交,最终状态以exchange.GetOrder()为准 |
API Key与限频
- 没有API Key:请求发往公开端点
https://aggregator-api.kyberswap.com,按客户端标识(x-client-id,见exchange.IO("clientId"))限频,每秒3次(应答头为每10秒30次)。托管者在同一进程内给KyberSwap请求排队(相邻请求至少间隔约0.34秒)。 - 有API Key:在配置项
KyberSwap Api Key中填写或用exchange.IO("kyberApiKey", key)设置后,请求发往API网关https://api.kyberswap.com/swap(路径与公开端点相同),请求头带X-Api-Key(同时照发x-client-id),限频更高,具体额度随Key而定(KyberSwap文档没有公开数字)。 - 获取Key:KyberSwap不提供自助申请,需发邮件给KyberSwap商务团队
[email protected]申请;KyberSwap已不再为x-client-id开白名单,提高限频只能通过API Key。 - 被限频(HTTP 429)时,按应答头
x-ratelimit-reset-after给出的时间(最多10秒)或1、2、4秒退避,最多重试3次;仍被限频时报错rate limited (HTTP 429) after 4 attempts,没有Key时报错里提示设置API Key。exchange.GetDepth()逐档询价,档数多时最容易触发限频。 - Key缺失、无效或过期时网关返回HTTP 401,报错
KyberSwap API key rejected (HTTP 401: …);不会自动退回公开端点,可用exchange.IO("kyberApiKey", "")清除Key。
可以直接运行的完整策略(DEX与CEX搬砖、定投)见DEX策略示例。
跨链桥(bridge)
exchange.IO("bridge.*", ...)经LI.FI聚合的跨链桥(Across、Stargate、CCTP、deBridge、Mayan、Relay、NEAR Intents等)把代币从本交易所对象的链转到另一条链,支持EVM链之间以及EVM与Solana之间(源链为本交易所对象的链)。报价与交易由LI.FI给出,由托管者授权、eth_call模拟后签名广播。请求带集成方标识integrator=fmz,不加收任何费用;报价中的LIFI Fixed Fee等是LI.FI与桥自己的费用,已计入toAmount。
典型流程:bridge.quote看报价 → bridge.simulate模拟 → bridge.send发出 → 每10~30秒bridge.status直到DONE或FAILED。
- 跨链是异步的:
bridge.send返回时只是源链交易已广播,到账要几秒到几十分钟(见报价的executionDuration),必须轮询bridge.status确认;PARTIAL表示目标链收到的是别的代币,REFUNDED表示已退回源链。 - 跨虚拟机(EVM↔Solana)必须传
toAddress,地址格式按目标链检查;地址写错的资金无法找回。 - 风险:桥合约与跨链消息的安全风险由各桥承担;报价随时变化,
bridge.send发出前会重新报价;目标链需要有gas才能继续使用到账的代币。先用小额测试。 - 限频:没有API Key时LI.FI按出口IP限频,
/quote两小时75次(bridge.quote、bridge.simulate、bridge.send各用一次,授权后再报价时多一次),其它接口每分钟100次;同一托管者上的策略共用额度。用exchange.IO("bridge.apiKey", key)设置Key后每分钟100次。被限频时报错rate limited (HTTP 429 …)。