Jupiter
连接Solana链上的Jupiter聚合器,把兑换映射为现货交易函数。一个交易所对象对应一个Solana钱包:报价和兑换交易由Jupiter Swap API生成(它在Solana上的众多DEX和做市商之间拆单选路),托管者用配置的私钥签名后经Solana节点广播。不填Jupiter API Key时使用免费的lite-api.jup.ag,填写后使用api.jup.ag;注意:填写API Key后,计价币为USDC、USDT的原生限价单与定投默认改用Jupiter Trigger V2,资金要存入Jupiter托管的vault(不再留在链上自己的订单账户);要保持非托管的v1,在策略开头调用exchange.IO("trigger.api", "v1")。见下文「限价单」「定投」。
同一个交易所对象还提供Meteora DLMM、Raydium CLMM与Orca Whirlpools池子的集中流动性(exchange.IO("lp.*", ...),见下文「集中流动性」):交易由连接器自己构造、签名并经Solana节点广播,指令与返回字段对齐Uniswap交易所对象的LP指令。
pump.fun打新(exchange.IO("pump.*", ...),见下文「Pump.fun打新」):在链上发现刚创建的币,直接在pump.fun的联合曲线上报价、买卖(连接器自己构造、模拟、签名交易),币毕业迁到PumpSwap后自动改走Jupiter兑换。新币风险极高,见该节的风险说明。
名称与配置
exchange.GetName():Jupiter(现货)。
| 配置项 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| 钱包私钥 | 是 | — | Solana钱包私钥:Phantom、Solflare导出的base58字符串,或solana-keygen生成的JSON字节数组。 |
| 节点地址 | 否 | https://api.mainnet-beta.solana.com,https://solana-rpc.publicnode.com | Solana RPC节点,多个用逗号分隔,某个节点出错时自动换下一个。默认为官方公共节点和publicnode。 |
| Jupiter API Key | 否 | — | 可选。(详见表下) |
| 流动性来源 | 否 | — | 可选。(详见表下) |
表中长说明的其余部分:
- Jupiter API Key:不填时使用免费的
lite-api.jup.ag;填写后使用api.jup.ag,请求速率可按套餐提高(见exchange.IO("rps", ...)),并且计价币为USDC、USDT的原生限价单与定投默认改用Jupiter Trigger V2(资金存入Jupiter托管的vault,见「限价单」「定投」;要保持非托管的v1,调用exchange.IO("trigger.api", "v1"))。API Key在Jupiter开发者平台申请;设置了接口权限的Key要包含Trigger。 - 流动性来源:只经过这些流动性来源兑换,例如
pump(pump.fun的bonding curve与PumpSwap)、meteora、raydium、orca,或Jupiter的来源名;不填表示全部来源。运行中可用exchange.IO("dexes", ...)修改。
交易对与合约代码
交易对示例:SOL_USDC、JUP_USDC、BONK_SOL
SOL为原生币,兑换时自动包装、解包。内置代币:SOL、USDC、USDT、JUP、BONK、WIF、JTO、PYTH、RAY、JitoSOL、mSOL、JupSOL、TRUMP、PENGU、POPCAT。其它代币有三种写法:直接写代币名,按Jupiter代币列表中经过认证、名称完全一致的代币识别(同名的多个认证代币时报错);直接写mint地址;或者先用exchange.IO("token", ...)登记。交易对不转大写(mint地址与mSOL这类币名区分大小写),按原样书写,例如DB5QKorV9KHY54y73h5xWQqYyuD8P3jC1p5Ea8DBpump_SOL。
专属IO指令
| 指令 | 参数 | 说明 | 返回值 |
|---|---|---|---|
route | symbol, side, qty | 只询价不下单,口径与下单相同:卖出(sell)按精确输入询价卖出qty个基础币;买入(buy)按精确输出询价买到qty个基础币,没有精确输出路由时(Meteora、PumpSwap等来源不支持精确输出)改按精确输入估价,与限价买单的退路相同(市价买单本身也是精确输入)。见子页exchange.IO("route", ...)。 | {symbol, side, qty, route, quote, price, priceImpactPct, swapMode, baseQty}:swapMode为ExactIn或ExactOut;baseQty为这个报价实际买入或卖出的基础币数量(买入按精确输入估价时可能与qty略有差异),price为quote除以baseQty。(详见表下) |
token | [name, mint] | 登记代币(只在本次运行中有效),登记后的代币名可以直接写在交易对里;不传参数时列出代币表。见子页exchange.IO("token", ...)。 | 登记时返回{symbol, mint, decimals},列表时返回{symbol, mint, decimals, native}数组。 |
transfer | to, amount | 从钱包转出SOL;amount可传all转出全部余额(扣除手续费)。只支持SOL,第三个参数传其它代币会报错。只等广播,不等上链。见子页exchange.IO("transfer", ...)。 | {signature, amount, lastValidBlockHeight} |
receipt | signature[, waitMs] | 查询一笔Solana交易的状态,可等待到确认或失败(最多10分钟)。查询订单时传订单ID中逗号后面的交易签名。见子页exchange.IO("receipt", ...)。 | {signature, state, slot, confirmationStatus, err, fee, blockTime},state为success、failed或pending;fee、blockTime只在确认或失败后才有。(详见表下) |
dca.create | params | 创建定投。见子页exchange.IO("dca.*", ...)。 | {id, version, signature, symbol, side, total, perOrder, numberOfOrders, interval, minPrice, maxPrice, startAt, priorityFeeLamports}:version为v1或v2;v1的id为定投订单账户地址,V2的id为Jupiter的订单UUID,signature为存入交易,另有vault。 |
dca.list | [params] | 列出钱包的定投(v1在前;配置了API Key或trigger.api为v2时再列V2):params.status为active(缺省,进行中)或history(已结束),params.symbol只列这个交易对。见子页exchange.IO("dca.*", ...)。 | [{id, version, symbol, side, state, total, perOrder, numberOfOrders, ordersFilled, interval, minPrice, maxPrice, spent, received, filledQty, avgPrice, fee, createdAt, updatedAt, openTx, closeTx, info}]:state为active、completed或canceled,V2另有pending(存入中)、canceling(已撤销、未取回)、failed(存入失败),V2行另有nextFillAt,fee为null(手续费已含在换到的币里);spent为已花出的输入币,received为已换到的输出币(fee为其中被扣的手续费,输出币计),filledQty、avgPrice为按基础币折算的成交量与均价;info为Jupiter的原始行。(详见表下) |
dca.cancel | id | 撤销一笔进行中的定投,剩余的输入币退回钱包,按id的形状分v1、V2(V2的定投号是UUID,要配置API Key)。见子页exchange.IO("dca.*", ...)。 | v1:{id, version, signature, priorityFeeLamports[, indexed]};V2:{id, version, signature, refund, refundCurrency, roundsRemaining, info},signature为取回交易,refund为退回的输入币数量。 |
dca.simulate | params[, wallet] | 按dca.create的参数生成交易,用节点的simulateTransaction执行(不签名、不广播),用来在下单前检查余额、最低金额等;params写成{cancel: id}时模拟撤销这笔定投。见子页exchange.IO("dca.*", ...)。 | {ok, err, reason, logs, unitsConsumed, version, wallet, id, plan, priorityFeeLamports}(version为v1或v2;V2另有vault,没有id):ok为模拟是否成功,失败时reason为原因(付款钱包一个SOL都没有时节点只回err为AccountNotFound,reason注明the paying wallet has no SOL);id为将要新建的定投账户地址;plan为换算后的定投参数。 |
trigger.simulate | params[, wallet] | 生成Jupiter限价单的挂单交易并用节点的simulateTransaction执行(不签名、不广播):params为{symbol, side, price, amount, expiry, slippage},含义同下单(amount为基础币数量,expiry、slippage同下单附加参数);写成{cancel: orderId}时模拟撤销这张限价单。见子页exchange.IO("trigger.*", ...)。 | v1:{ok, err, reason, logs, unitsConsumed, wallet, order, makingAmount, takingAmount, priorityFeeLamports},order为订单账户地址,makingAmount、takingAmount为付出、换回的最小单位数量;V2:{ok, err, reason, logs, unitsConsumed, version, wallet, vault, inputMint, inputAmount, triggerPriceUsd, triggerCondition, expiresAt, priorityFeeLamports}。(详见表下) |
trigger.api | [mode] | 新挂的原生限价单(tif为gtc)与新建的定投用哪套接口:auto(缺省)为配置了API Key且计价币为USDC或USDT时用Trigger V2(托管vault),否则用v1;v1为一律用v1(非托管,资金在链上订单账户),配置了API Key也一样;v2为一律用V2,计价币不是USDC、USDT时下单报错,没有配置API Key也照用(Jupiter目前放行不带Key的V2调用,但官方文档写的是必须带Key,随时可能收紧)。见子页exchange.IO("trigger.*", ...)。 | 当前模式:auto、v1或v2。 |
trigger.vault | [action] | 查询本钱包在Jupiter Trigger V2的托管vault及其中的余额(需要配置API Key,或exchange.IO("trigger.api", "v2"))。见子页exchange.IO("trigger.*", ...)。 | 还没有vault时为{wallet, registered: false};否则为{wallet, registered: true, vault, sol, tokens, info},tokens为[{mint, symbol, amount, raw}](symbol只对代币表中的币给出),info为Jupiter返回的vault信息。 |
slippage | [ratio] | 市价单的滑点保护比例,范围[0, 0.5),默认0.005(0.5%),由链上程序强制执行。限价单不使用这个设置。不传参数时查询。见子页exchange.IO("slippage", ...)。 | 当前滑点比例。 |
priorityFee | [sol] | 每笔兑换交易的优先费上限(SOL),范围0到0.1,默认0.001;实际优先费由Jupiter按网络拥堵情况估算,不超过上限。不传参数时查询。见子页exchange.IO("priorityFee", ...)。 | 当前上限(SOL)。 |
dexes | [sources] | 限定兑换经过的流动性来源(逗号分隔):分组简写pump、meteora、raydium、orca,或Jupiter的来源名(区分大小写);""表示不限定。行情、询价和下单都只经过这些来源。不传参数时查询。见子页exchange.IO("dexes", ...)。 | 当前限定的来源名数组(分组已展开;空数组表示不限定)。 |
rps | [n] | 请求Jupiter API的每秒最多请求数,范围0.1到500,默认1。请求依次排队,相邻两次至少间隔1/n秒。不传参数时查询。见子页exchange.IO("rps", ...)。 | 当前每秒最多请求数。 |
base | [url] | 不传参数时返回当前Solana节点地址;传入地址时切换节点(多个用逗号分隔)。 | 切换前的地址。 |
address | — | 钱包地址(base58)。 | — |
pump.new | [options] | 最近在pump.fun上新建的币,从链上发现:查pump.fun mint authority(TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM,只出现在创建交易里)的最近签名,逐笔取交易解析其中的CreateEvent,新的在前。见子页exchange.IO("pump.*", ...)。 | [{signature, slot, time, mint, name, symbol, uri, creator, user, bondingCurve, tokenProgram, quote, quoteMint, mayhem, cashback, holderReward, devBuy}]:time为区块时间(毫秒);user为发起创建的钱包(一般就是creator);tokenProgram为spl-token或token-2022;quote为SOL、USDC或报价代币的mint(只有SOL的币能用pump.buy、pump.sell);devBuy为同一笔交易里的首买{tokens, quoteAmount}(quoteAmount含费,报价币不是SOL或USDC时为null),没有首买为null。(详见表下) |
pump.info | mint | 币的联合曲线(bonding curve)状态,一次getMultipleAccounts读曲线、mint、全局配置与费率表。不是pump.fun的币时报错。见子页exchange.IO("pump.*", ...)。 | {mint, bondingCurve, creator, tokenProgram, decimals, quote, quoteMint, complete, migrated, virtualTokenReserves, virtualQuoteReserves, realTokenReserves, realQuoteReserves, tokenTotalSupply, price, marketCap, progress, fees, mayhem, cashback, holderReward}:储备与供应量为可读单位;price为1个币值多少报价币(SOL),marketCap为price乘总供应量;progress为曲线已卖出的比例(%),到100时曲线完成(complete),随后迁移到PumpSwap(migrated,储备清零,price、marketCap、fees为null);fees为当前费率{protocolBps, creatorBps}(万分之几)。 |
pump.quote | mint, side, amount | 在联合曲线上本地报价(不发交易),公式与费用同链上程序:buy时amount为要花的SOL(含费),sell时为要卖的币数。见子页exchange.IO("pump.*", ...)。 | {venue, mint, side, quote, amountIn, amountOut, price, spotPrice, priceAfter, priceImpactPct, fees, protocolFeeBps, creatorFeeBps, crossesCurve}:venue为pump(联合曲线)或jupiter(已毕业,另带route为经过的流动性来源);price为含费成交均价(SOL/币),priceImpactPct为不含费均价相对现价spotPrice的偏离(%),fees为协议费加创作者费(SOL);crossesCurve为true表示买穿曲线(见下文「Pump.fun打新」)。(详见表下) |
pump.buy | mint, solAmount[, options] | 花solAmount SOL(含协议费与创作者费)在联合曲线上买入:先幂等地建钱包的代币账户,再发buy_exact_quote_in_v3,最少到手数量为本地报价×(1 − slippage),由链上程序强制执行。见子页exchange.IO("pump.*", ...)。 | {txHash, venue, mint, side, solAmount, tokenAmount, price, fee, slot}:venue为pump或jupiter(另带route);solAmount为付出的SOL(含协议费与创作者费,不含网络费与账户押金),tokenAmount为买到的币,fee为网络费(SOL)。(详见表下) |
pump.sell | mint, amount[, options] | 在联合曲线上卖出amount个币(all为全部余额),发sell_v3,最少收回的SOL为本地报价×(1 − slippage)。见子页exchange.IO("pump.*", ...)。 | 同pump.buy:solAmount为到手的SOL(已扣协议费与创作者费)。 |
pump.holdings | [wallet] | 钱包(默认本交易所对象的钱包)持有的pump.fun币:钱包代币余额里有联合曲线的那些,按曲线估值。见子页exchange.IO("pump.*", ...)。 | [{mint, amount, quote, complete, price, value}]:value为现在按曲线全部卖出可得的报价币(已扣费);曲线已完成或超出曲线能买回的量时price、value为null(已毕业的币用exchange.IO("route", ...)估值)。 |
lp.pools | token[, quote] | 列出代币的Meteora DLMM、Raydium CLMM与Orca Whirlpools池子(指定计价币,或SOL、USDC、USDT):费率、bin步长与active bin(DLMM)或tick间距与当前tick(CLMM)、现价、池子两种代币的余额与TVL;24小时成交与手续费、美元TVL分别取自Meteora的数据API(dlmm.datapi.meteora.ag)、Raydium API v3(api-v3.raydium.io)与Orca的公开API(api.orca.so),现价、余额等从链上读,Raydium的费率取池子所属的AmmConfig账户。见子页exchange.IO("lp.pools", ...)。 | [{id, protocol, dex, symbol, base, quote, fee, feeRate, feeRateNow, binStep, activeId, price, reserveBase, reserveQuote, tvlQuote, tvlUsd, volume24hUsd, fees24hUsd, enabled, rewards, empty}]:protocol为meteora;price为计价币/代币;fee为基础费率(百万分之几,与Uniswap的fee同单位),feeRate为比例,feeRateNow为含波动附加费的当前费率;rewards为池子farm奖励代币[{mint, symbol}]。(详见表下) |
lp.select | token, budget[, options] | 按规则自动选池:options.fee(同lp.pools的fee)或options.binStep指定时只在这些池子里选;在美元TVL不低于max(5000美元, 预算)的池子里选24小时成交最大的,没有成交数据时选TVL最大的,都不够门槛时选TVL最大的。见子页exchange.IO("lp.select", ...)。 | lp.pools的一行,另带reason(选择理由)。 |
lp.pool | poolId | 池子实时状态。见子页exchange.IO("lp.pool", ...)。 | {id, protocol, dex, tokenX, tokenY, symbolX, symbolY, decimalsX, decimalsY, price, fee, feeRate, feeRateNow, binStep, activeId, reserveX, reserveY, tvlUsd, volume24hUsd, fees24hUsd, enabled, rewards},price为1个X值多少Y(池子自己的顺序)。(详见表下) |
lp.ticks | poolId[, lowerBinId, upperBinId[, step]] | bin区间内的流动性分布(DLMM没有tick,按bin给):每段两种代币的数量,step为合并成的段宽(bin数,默认1)。见子页exchange.IO("lp.ticks", ...)。 | {pool, activeId, binStep, price, tokenX, tokenY, symbolX, symbolY, segments: [{binLower, binUpper, priceLower, priceUpper, amountX, amountY, current}]},价格为Y/X。(详见表下) |
lp.plan | params | 建仓计划(只读,不花钱)。见子页exchange.IO("lp.plan", ...)。 | {params, symbol, pool, protocol, fee, feeRate, price, shape, strategy, budget, budgetUsd, binStep, activeId, lowerBinId, upperBinId, bins, positions: [{lowerBinId, upperBinId, priceLower, priceUpper, amountBase, amountQuote, share}], needBase, needQuote, haveBase, haveQuote, swap, shortfall, shareOfPool, volume24hUsd, estDailyFeesUsd, slippageBps, maxActiveBinSlippage, binArraysToCreate, rentSol, rentRefundableSol, warning?}:swap为建仓前需要换的币({side, amount, currency}或null);shareOfPool为本计划在active bin里的份额,estDailyFeesUsd = 24小时成交 × 费率 × 这个份额(假设价格一直在区间内);rentSol为建仓要押的租金,其中rentRefundableSol是仓位账户的(撤仓关账户时退回),其余是新建BinArray的(binArraysToCreate,不退)。(详见表下) |
lp.simulate | plan[, payer] | 按计划构造完整的建仓交易(新建BinArray、建仓位、建ATA、包装SOL、加流动性、解包),用节点的simulateTransaction执行(不验签、不广播),每个仓位一笔。见子页exchange.IO("lp.simulate", ...)。 | {pool, protocol, payer, ok, positions: [{position, lowerBinId, upperBinId, amountBase, amountQuote, ok, err, error, logs, unitsConsumed, txBytes}], swapNeeded, shortfall, note}:logs为程序日志尾部,error为失败原因(DLMM、Raydium CLMM、Orca Whirlpool的错误码附名字);Raydium与Orca的行用tickLower、tickUpper代替bin字段,position为仓位NFT的mint。 |
lp.add | plan | 按计划建仓:需要时先用Jupiter市价单换币并等确认,再按最新池价与余额重算;每个仓位一笔交易(仓位账户或Raydium、Orca的仓位NFT mint用新生成的密钥创建并签名),发送前先模拟,模拟失败不发送;等确认后按交易前后余额给出实际存入的数量。见子页exchange.IO("lp.add", ...)。 | {txHash, txHashes, swapTxHash, pool, protocol, symbol, positions: [{id, txHash, lowerBinId, upperBinId, priceLower, priceUpper, amountBase, amountQuote, rentSol, feeSol}]},仓位id为meteora:仓位地址、raydium:仓位NFT的mint或orca:仓位NFT的mint;Raydium与Orca的行用tickLower、tickUpper代替bin字段。 |
lp.increase | positionId, budget[, options] | 给仓位加仓:budget(计价币)按仓位的bin区间与现价拆成两种代币,缺的那种先换。见子页exchange.IO("lp.increase", ...)。 | {txHash, swapTxHash, id, symbol, amountBase, amountQuote, feeSol} |
lp.decrease | positionId, ratio[, options] | 按比例(0到1,换算成万分比)从仓位每个有流动性的bin撤出,同时领取全部手续费与farm奖励,仓位保留。见子页exchange.IO("lp.decrease", ...)。 | {txHash, txHashes, positions: [{id, symbol, txHashes, principalBase, principalQuote, feesBase, feesQuote, receivedBase, receivedQuote, rewards, rentRefundSol, feeSol}], sells}:received*按交易前后余额计算,手续费部分按发送前链上可领的量拆出。 |
lp.collect | positionIds[, sell] | 领取手续费与farm奖励(DLMM为claim_fee2、claim_reward2,Raydium为流动性为0的decrease_liquidity_v2,Orca为update_fees_and_rewards + collect_fees_v2 + collect_reward_v2),每个仓位一笔交易;sell为true时把领到的基础币卖成计价币。见子页exchange.IO("lp.collect", ...)。 | 同lp.decrease。 |
lp.remove | positionIds[, ratio[, sell]] | 撤出流动性并领取手续费与奖励,每个仓位各自的交易;ratio默认1:全部撤出后关掉仓位账户(Raydium为close_position:烧掉NFT、关NFT账户、NFT mint与仓位账户),退回租金(rentRefundSol);小于1时只撤一部分。见子页exchange.IO("lp.remove", ...)。 | 同lp.decrease。 |
lp.positions | [filter[, wallet]] | 钱包的全部Meteora DLMM仓位(节点getProgramAccounts按主人查,需要节点支持)、Raydium CLMM与Orca Whirlpools仓位(getTokenAccountsByOwner找钱包里数量为1的NFT,再读它们的仓位账户;Orca另列出钱包持有的Position Bundle里的仓位):bin区间、是否在区间内、两种代币当前数量(按每个bin里的份额折算)、价值、未领手续费与farm奖励、押的租金。见子页exchange.IO("lp.positions", ...)。 | [{id, pool, protocol, symbol, fee, lowerBinId, upperBinId, activeId, binStep, width, priceLower, priceUpper, price, inRange, liquidity, amountBase, amountQuote, value, feesBase, feesQuote, feesValue, rewards, rentSol, feeOwner, closed}],value、feesValue按计价币计,rewards为[{mint, symbol, amount}],liquidity为各bin份额之和。(详见表下) |
lp.track | positionIds | 登记仓位(meteora:地址、raydium:NFT mint、orca:NFT mint或只写地址——Raydium、Orca也认仓位账户地址;先核对是对应协议的仓位),之后lp.positions也会查这些仓位(主人每次按链上核对,转走的、已关掉的不列)。(详见表下) | 本进程记住的全部仓位地址。 |
bridge.chains | — | 跨链桥(LI.FI)支持的链:EVM链与Solana,缓存1小时。见子页exchange.IO("bridge.*", ...)。 | {id, key, name, chainType, nativeToken}数组,chainType为EVM或SVM。 |
bridge.tokens | [chain] | LI.FI认识的某条链上的代币(缺省为Solana),缓存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 | 重新报价,用本钱包签名LI.FI给出的序列化交易后simulateTransaction(核对签名),不广播。见子页exchange.IO("bridge.*", ...)。 | bridge.quote的结果,另有simulated(true)、unitsConsumed、signature。 |
bridge.send | params|quote | 跨链转出:重新报价 → 检查余额 → 用本钱包签名LI.FI给出的序列化交易(本钱包不是签名者时报错)→ simulateTransaction → 经Solana节点广播。见子页exchange.IO("bridge.*", ...)。 | {txHash, tool, fromChain, toChain, toChainName, fromToken, toToken, fromAmount, toAmount, toAmountMin, toAddress, transactionId},txHash为源链交易签名,可用receipt查状态。 |
bridge.status | signature[, 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(布尔值)。 |
表中长说明的其余部分:
lp.track:三家的仓位按主人就能查到,一般不需要登记;保留这个指令与Uniswap一致,本进程lp.add建的仓位会自动记住。查别的钱包的Orca仓位要用节点的getTokenLargestAccounts找NFT持有人(公共节点对它限流很紧)。
通用指令currency见exchange.IO。
不支持通用指令api(调用时报错并返回空值)。
函数支持差异
不支持(调用时报错并返回空值):exchange.GetTickers、exchange.GetTrades、exchange.CreateConditionOrder、exchange.ModifyConditionOrder、exchange.CancelConditionOrder、exchange.GetConditionOrder、exchange.GetConditionOrders、exchange.GetHistoryConditionOrders。
以回退方式支持:
exchange.GetRecords:原生周期为1分钟、5分钟、15分钟、1小时、4小时、12小时、1天(GeckoTerminal的周期);其它分钟级以上的周期由托管者合成,秒级周期不可用(没有成交记录接口可供合成)。
注意事项
| 函数 | Jupiter交易所的行为 |
|---|---|
| exchange.GetTicker() | 买一、卖一为约1000美元规模的实际可成交价(两次询价);吃不下1000美元的小币依次缩小到100、10美元,卖方规模不够时再缩小,实际规模见Info的sizeQuote、bidSize。没有24小时统计,High、Low、Open为当前价,Volume为0 |
| exchange.GetDepth() | 由约1000美元起逐档递增规模的询价推算,每档两次询价。买盘价格严格递减、卖盘严格递增。买卖两边是不同时刻、不同方向的询价,偶尔会交叉(买一不低于卖一):这时取两者的中间价,把交叉的档位并成一档(买一、卖一分别为中间价下浮、上浮0.0001%,数量不丢),原来的买一、卖一见Info的crossed,没有交叉时为null |
| exchange.GetRecords() | K线来自GeckoTerminal的池子级数据:Jupiter是聚合器,取GeckoTerminal上两边正好是这两个代币(SOL按wSOL)的池子里美元流动性最深的一个(不限DEX,在两个代币各自靠前的20个池子里找,选中的池子缓存1小时)。价格为该池子的逐笔成交价(含池子手续费,与exchange.GetTicker()的中间价可能相差约一个池子费率),单位为计价币/基础币,Volume为基础币数量;没有成交的周期按上一根收盘价补平、成交量为0,最后一根可能尚未收盘。GeckoTerminal的数据有几十秒到1分钟的延迟,公开接口约每分钟10次:同一周期的K线缓存1分钟,请求在托管者内排队,被限频时等待重试,仍不行时报错。找不到该交易对的池子时报错 |
| exchange.GetMarkets() | 代币表中的币与USDC、USDT、SOL组成的交易对(不逐个验证路由)。数量精度为基础币的代币精度,最小下单量为一个最小单位,价格精度固定为8位 |
| exchange.GetAssets() | SOL与代币表中各代币的钱包余额,单独持有的wSOL记为WSOL;代币表以外的持仓不进余额列表,列在Info的unlisted中({mint, amount}) |
| exchange.CreateOrder() | 立即兑换:限价为最差成交价,由链上程序按滑点强制执行,当前报价已经达不到时直接报错、不发交易;市价按滑点保护;市价买入时数量为要花费的计价币。下单附加参数slippage覆盖本单滑点。Jupiter生成交易时会先模拟一遍,余额不足等会直接报错。广播前Solana节点按最新状态再模拟一遍:模拟失败时交易没有发出,连接器重新询价、生成交易再试,最多重试2次(第二次重试起避开失败路由经过的流动性来源,不会因此超出exchange.IO("dexes", ...)的限定),仍失败时报错,错误信息中带模拟的err与相关程序日志;成功时Info的preflightRetries为重试次数。下单选项tif为gtc时不立即兑换,改挂Jupiter原生限价单(配置了API Key且计价币为USDC、USDT时为Trigger V2,否则v1;可用exchange.IO("trigger.api", ...)强制其一),见下文「限价单」 |
| exchange.GetOrder() | 订单ID形如SOL_USDC,5VERv8…(交易对、逗号、交易签名)。交易确认后为已成交,成交数量按交易前后的钱包余额计算;链上执行失败为已撤销(手续费照扣);超过有效期(约1分钟)仍未上链为已撤销。不是本程序发出的交易只能查已确认成功的(方向按余额变化判断),尚未确认或链上失败的报错。限价单的订单ID为交易对加订单账户地址(v1)或Jupiter的订单UUID(V2),见下文「限价单」 |
| exchange.GetOrders() | 本程序发出、尚未确认也未过期的兑换,加上钱包的全部活动限价单(不限于本程序挂的;V2限价单只在配置了API Key时列出) |
| exchange.CancelOrder() | 只能撤限价单。兑换单不支持:Solana交易发出后无法撤回,未上链的交易约1分钟后自动过期 |
| exchange.ModifyOrder() | 只能改V2限价单的价格(及下单附加参数slippage),见下文「限价单」。v1限价单与兑换单不支持 |
| exchange.GetHistoryOrders() | 只有已成交、已撤销的限价单,以及V2的过期单(钱还在vault,状态为未成交,见下文「限价单」),不含兑换单(兑换单用exchange.GetOrder()查)。不传since、limit时v1买卖两个方向各取最近10条、V2取最近10条;传since时取创建时间不早于它的全部,传limit时取够为止。v1与V2合并后按创建时间倒序 |
- 请求速率:Jupiter按每秒请求数限流,超过后返回429。连接器按
exchange.IO("rps", ...)(默认每秒1次)给请求排队,同一个托管者进程中使用同一个Jupiter API地址的交易所对象共用这个节奏。默认设置下exchange.GetTicker()约需2秒,5档exchange.GetDepth()约需10秒;需要更快时申请Jupiter API Key,并按套餐调高rps。 - 手续费:每笔交易的Solana基础费与优先费(上限见
exchange.IO("priorityFee", ...))从SOL余额中扣除,订单的Info中有fee。第一次买入某个代币时,钱包需要新建该代币的账户,押金约0.002 SOL;押金仍归钱包所有,不计入成交。
Pump.fun打新
exchange.IO("pump.*", ...)直接交易pump.fun(程序6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P)联合曲线上的币,不经过Jupiter。账户、指令与报价公式按pump.fun官方公开文档(GitHub pump-fun/pump-public-docs的IDL与说明)。
- 新币:
pump.new从链上发现新币,策略循环轮询它(见下例)。公共节点按秒限流、延迟高(20笔约需4秒),抢新请在「节点地址」里配置自己的付费节点。 - 只交易SOL报价的币:pump.fun也有以USDC或其它pump币为报价的币(
pump.new的quote),pump.buy、pump.sell对它们报错;cashback币(已停止新建)也报错,可用exchange.Buy、exchange.Sell经Jupiter交易。 - 价格保护:买入是精确输入(花
solAmount,含费),最少到手 = 本地报价×(1 −slippage);卖出最少收回 = 本地报价×(1 −slippage)。默认滑点5%,由链上程序强制执行,达不到时整笔失败,只扣网络费。 - 费用:协议费与创作者费按Pump Fees程序的费率表随市值分档(2026年10月为0.95% + 0.30%;
pump.info、pump.quote返回实际费率,没有创作者的币不收创作者费),另有Solana网络费与优先费。第一次买某个币要建代币账户(押金约0.002 SOL,pump.sell卖all时默认关掉账户退回);钱包第一次在pump.fun交易时程序还会建它的成交量账户(约0.0018 SOL,不退)。 - 买穿曲线:买入预算超过曲线剩余可卖量时(mayhem币除外),超出部分按迁移后PumpSwap池子的价格成交(官方的「合成迁移」),
pump.quote的crossesCurve为true;之后到迁移完成前曲线不能再交易。mayhem币买入超过剩余量时报错。 - 毕业:曲线完成(
complete)的币,pump.buy、pump.sell改用本交易所对象的Jupiter市价兑换(交易对MINT_SOL,价格保护用本单的slippage,Jupiter要求小于0.5),返回的venue为jupiter;这时priorityFee、computeUnitLimit选项不适用(报错),优先费上限按exchange.IO("priorityFee", ...),dryRun也不支持(用pump.quote询价,它对毕业币同样走Jupiter)。曲线刚完成、还没迁移的短时间内两条路都可能失败。 - 每笔交易发送前都用节点模拟,模拟失败不发送并报出原因(pump.fun的错误码附名字,如
BuySlippageBelowMinTokensOut);广播与「是否已发出」的判断同兑换下单,等确认的规则同集中流动性(定不下来时报outcome is unknown并附签名,不说没发生)。 - 抢新时优先费要给足(
options.priorityFee),否则在拥堵时可能过期不上链。
抢新轮询示例(JavaScript):
javascript
var seen = {}
var start = Date.now()
while (true) {
var coins = exchange.IO("pump.new", {limit: 20, since: start})
for (var i = 0; coins && i < coins.length; i++) {
var c = coins[i]
if (seen[c.mint] || c.quote != "SOL" || c.mayhem) continue
seen[c.mint] = true
if (c.devBuy && c.devBuy.quoteAmount > 1) continue // 创作者首买过大,跳过
var r = exchange.IO("pump.buy", c.mint, 0.01, {slippage: 0.2, priorityFee: 0.0005})
if (r) Log("bought", r.tokenAmount, c.symbol, "for", r.solAmount, "SOL", r.txHash)
}
Sleep(1000)
}
风险:
- 绝大多数新币很快归零;创作者或与它捆绑的钱包常在创建同笔或随后几个区块里买入,随时砸盘跑路(rug pull)。
- 抢新机器人与MEV竞争激烈:同一区块里的先后顺序取决于优先费与小费,滑点设得大会被三明治夹击,按最差价成交。
- 名称、符号、元数据链接由创建者随意填写,可以冒充知名项目;请以mint地址为准。
- 协议费、创作者费、网络费与优先费在每次买卖都要付,频繁进出的成本很高。
限价单(tif gtc)
exchange.CreateOrder(symbol, side, price, amount, {tif: "gtc"})(或exchange.Buy、exchange.Sell带同样的下单选项)不立即兑换,而是挂一张Jupiter原生限价单,由Jupiter的keeper在价格到达后异步成交。不带tif或tif为其它值时行为不变(立即兑换)。有两套接口:
| Trigger v1 | Trigger V2 | |
|---|---|---|
何时使用(trigger.api为缺省的auto) | 没有配置API Key,或计价币不是USDC、USDT | 配置了API Key且计价币为USDC或USDT |
| 资金存放 | 链上订单账户(程序j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X),挂单信息链上公开 | 存入Jupiter托管(Privy)的vault,一个钱包一个,所有V2订单共用;订单存在Jupiter链下,成交前不公开 |
| 触发与成交 | 按两种代币的兑换比率,按限价成交(默认0滑点),换回数量有保证 | 按基础币的美元价触发,到价后按当时市价经Jupiter路由兑换:换回数量不保证,可以部分成交;滑点缺省由Jupiter自动设定 |
| 订单ID | SOL_USDC,订单账户地址 | SOL_USDC,订单UUID |
| 最低金额 | 付出或换回的一边至少值5美元 | 付出的一边至少值10美元 |
| 到期 | 可选,缺省不过期;过期后Jupiter不会自动关单,订单仍挂着、钱仍锁在订单账户里,要撤单取回 | 必须有,缺省30天;过期后不再成交,钱留在vault,要撤单取回 |
| 改单 | 不支持 | exchange.ModifyOrder()改价格 |
填写API Key后默认就是托管的V2:挂单的钱离开钱包、存进Jupiter托管的vault。要保持非托管的v1,调用exchange.IO("trigger.api", "v1");反过来exchange.IO("trigger.api", "v2")在没有API Key时也强制用V2(Jupiter目前放行不带Key的V2调用,但官方文档要求带Key)。
Jupiter官方已把v1标为不再开发(只做关键修复,尚未公布停用),新功能都在V2。已挂的v1单不受配置影响,照常可查、可撤(订单ID的形状决定走哪套接口,与trigger.api无关;V2订单要配置API Key或trigger.api为v2才能查、撤、改)。
通用规则:
- 数量:
amount为基础币数量,买入付出amount × price计价币(向下取整到最小单位,不多付),卖出付出amount基础币(v1另要求换回amount × price计价币,向上取整,不少收)。不支持市价单(price为-1或type为market时报错)。 - 下单附加参数:
expiry为到期时间戳(毫秒);slippage为允许的滑点比例(如0.003)。v1缺省0(按限价精确成交),给了可以提高成交率但可能低于限价成交;V2缺省由Jupiter按市场自动设定,给了就用固定滑点。 - 状态:挂着为未成交,有部分成交为部分成交;全部成交为已成交;已撤销为已撤销。
Info为Jupiter的原始订单行。 - 过期:Jupiter不会替你关掉过期的单,钱一直锁着,直到
exchange.CancelOrder()取回(v1退回本金与订单账户租金,V2从vault取回)。所以过期但还没撤的单仍为未成交(或部分成交),Info.expired为true,Info.note写明要撤单取回。v1过期单照样列在exchange.GetOrders()中(Jupiter仍把它当挂单);V2过期单被Jupiter归入历史,不在exchange.GetOrders()中,用exchange.GetOrder()或exchange.GetHistoryOrders()查到。撤单取回后为已撤销。 - 撤单:订单已经成交或撤销时
exchange.CancelOrder()返回false,原因见GetLastError()。 exchange.GetOrders()每次调用都会请求一次v1限价单列表(配置了API Key时再请求一次V2列表),受exchange.IO("rps", ...)节流。- 带转账税(transfer fee)或transfer hook扩展的Token-2022代币不能挂限价单(Jupiter不支持)。
- 挂单前可以用
exchange.IO("trigger.simulate", ...)只模拟。
Trigger v1:
- 挂单与撤单都是连接器签名后经Solana节点广播的链上交易,节点预检(模拟)失败时没有发出并报错;各付一次Solana交易费与优先费,第一次挂某种币的单时要新建代币账户等,押金归钱包。撤单只等广播,结果用
exchange.GetOrder()确认。 - 手续费:Jupiter从换回的币中扣手续费(官方说明稳定币对0.03%,其它0.1%,以每笔成交记录为准),订单的
AvgPrice按扣费前计算,实际到账见Info的trades。 exchange.GetOrder()先查活动单再查历史单;本程序刚挂、Jupiter还没收录的单按链上状态给出(订单账户存在为挂单中)。
Trigger V2:
- 认证:连接器用钱包私钥签名Jupiter的登录挑战(只签以Jupiter固定登录文本开头、写明本钱包地址的消息),换取15分钟的访问令牌并自动续期,令牌只在内存中。令牌泄露也不能转走资金(取回要钱包签名交易),但可以撤单、改价。
- 下单:连接器先查本钱包的vault,没有就注册一个(在Jupiter为钱包新建托管账户;也可以事先用
exchange.IO("trigger.vault", "register")注册);再请Jupiter生成存入交易,逐条核对(钱包是付费者,只调用系统、代币、关联代币账户、计算预算、Memo程序,钱包转出的币只进vault一侧、合计正好是下单金额;钱包出租金新建的账户只能是交给vault的本单输入账户(Jupiter用以vault为base的CreateAccountWithSeed建它,撤单或成交后关掉、租金退回钱包)和钱包、vault的关联代币账户),签名后先用节点模拟(模拟失败时没有发出并报错),再连同订单参数交给Jupiter,Jupiter在这次调用中把存入交易上链并返回订单UUID。这次调用出错时存入交易可能已经上链,错误信息中带存入交易签名,请用exchange.IO("receipt", ...)与exchange.IO("trigger.vault")确认后再重试。 - 触发:买单为基础币的美元价跌到
price以下时买入,卖单为涨到price以上时卖出。计价币按1美元看待(USDC、USDT脱锚时触发价随之偏离)。Jupiter不检查价格是否合理:买入价高于市价、卖出价低于市价的单会立即按市价成交。 - 数量与成交:订单的
Amount卖单为存入的基础币,买单为存入的计价币÷价格;DealAmount、AvgPrice按实际消耗与换回的数量计算(手续费已含在换回的数量中,V2不单列)。 - 改单:
exchange.ModifyOrder()只改价格(与slippage),只有挂着、未开始成交的普通单能改,追踪止损单不能改价;数量由存入金额决定,不能改(传入的数量必须等于原数量)。买单改价后花费的计价币不变,Amount随之变为金额÷新价格。 - 撤单分两步:Jupiter先停止订单(此后不再成交)并生成取回交易,连接器核对(钱包只付手续费)并签名,交给Jupiter补上vault的签名后上链,未成交的币回到钱包。第二步失败时订单停在待取回状态(仍列在
exchange.GetOrders()中),再撤一次即可取回。过期的单同样用exchange.CancelOrder()取回。 - 托管风险:挂单期间资金在Jupiter通过Privy托管的vault中,不在钱包里,余额不计入
exchange.GetAssets(),用exchange.IO("trigger.vault")查看。取回依赖Jupiter生成取回交易并补签,Jupiter服务异常时无法自行取回。V2接口官方仍标为beta,行为可能变化。 - 费用:存入与取回交易由钱包付网络费;成交由keeper执行并付网络费,Jupiter的兑换手续费已从换回的数量中扣除。没有集成方手续费。
- 请求:每次查询、下单都要先认证(进程内缓存令牌),会多占一两次请求额度;API Key设置了接口权限时必须包含Trigger,否则相关调用报403。
- 订单函数会列出钱包的全部V2限价单,包括在jup.ag等处挂的(止盈止损、OCO的每一条腿都按一张单列出,价格为它的美元触发价,方向见
Info的triggerCondition)。按美元价触发、却不是以USDC或USDT计价、或者不按基础币价格触发的单无法表示为交易对的价格,查询到它们时报错(指定交易对查询时只看这个交易对的单)。
定投(DCA)
exchange.IO("dca.create", ...)、dca.list、dca.cancel、dca.simulate:配置了API Key且计价币为USDC或USDT时新定投默认用Jupiter Trigger V2的DCA(托管vault;exchange.IO("trigger.api", ...)同样适用:v1保持Recurring v1,v2强制V2),否则用Recurring API v1(按时间定投,程序DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M)。Jupiter已不再维护Recurring v1(仍可用),定投功能已并入Trigger V2。dca.list两边都列(V2要配置API Key),dca.cancel按定投ID的形状分v1(地址)、V2(UUID)。定投不进exchange.GetOrders()等订单函数。
- v1:总额一次存入定投订单账户,由Jupiter的keeper每隔
interval秒兑换一份,买到的币自动转回钱包。至少2份、每份至少值50美元;不支持Token-2022代币;Jupiter从换到的币中收0.1%手续费。创建和撤销都是链上交易,要付交易费与优先费;撤销后剩余的币退回钱包。Jupiter收录新定投要几分钟,这期间dca.list按链上账户列出本程序刚建的定投(indexed: false),dca.cancel也照样能撤。 - V2:认证、vault、存入与托管风险同上文V2限价单。总额存入vault,keeper每轮兑换一份,换到的币直接进钱包,网络费由keeper付;滑点由Jupiter按市场自动设定,不能指定;手续费已含在换到的数量中。至少2份、每份至少值10美元,间隔60秒到1年,开始时间最多30天后,每个钱包最多10个进行中的定投。给了
minPrice或maxPrice时只在基础币的美元价落在区间内时兑换,区间外的一轮顺延到下一个间隔。不能修改;撤销分两步(同V2限价单),已成交的轮次不退。
集中流动性(LP)
exchange.IO("lp.*", ...)指令提供Meteora DLMM(程序LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo)、Raydium CLMM(程序CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK)与Orca Whirlpools(程序whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc;这两家与DLMM的不同见下文)池子的集中流动性:选池、规划与模拟、建仓、加减仓、领手续费与farm奖励、撤出和仓位查询。指令名、参数与返回字段对齐Uniswap交易所对象的lp.*,不同之处:
- 价格离散成bin而不是tick:bin
i的价格为(1 + binStep/10000)^i(再按两种代币的精度换算),区间用lowerBinId、upperBinId表示(含两端),现价所在的bin为activeId;range可以写{bins: [lo, hi]}。active bin里两种代币都有,往上的bin只有X、往下的只有Y,所以建仓的形状就是各bin放多少(spot、curve、bidask)。 - 仓位是一个账户,不是NFT:
id写成meteora:仓位地址(也认只写地址);一个仓位最多70个bin,更宽的spot区间拆成多个仓位。 - 租金:每个仓位账户押一份免租额(按节点
getMinimumBalanceForRentExemption,2026年10月约0.042 SOL),lp.remove全部撤出时关掉账户退回;区间里还没有BinArray账户(每个装70个bin)时要先新建,押的租金(2026年10月约0.052 SOL/个)不退。计划的rentSol、rentRefundableSol、binArraysToCreate给出这些数。第一次持有某种代币时还要新建代币账户(约0.0015 SOL,仍归钱包)。 - SOL自动包装、解包:池子一侧是SOL时,交易里先把要存入的SOL包装成wSOL,交易结尾关掉钱包的wSOL账户(钱包里原有的wSOL也一并换回SOL)。
- 换币用本交易所对象的Jupiter兑换(市价单,滑点见
exchange.IO("slippage", ...))。 - 写指令每笔交易发送前都用节点模拟一遍,模拟失败不发送并报出原因(DLMM、Raydium CLMM、Orca Whirlpool的错误码附名字);计算单元上限按模拟用量加余量,优先费按最近写这些账户的交易的费率取第75百分位,不超过
exchange.IO("priorityFee", ...)的上限。广播与「是否已发出」的判断与兑换下单相同;交易确认后返回,实际数量按交易前后余额计算。等确认时向所有节点查交易状态,只有某个节点的区块高度已超过交易的最后有效高度、且已越过它的节点查不到这笔交易时才报过期(expired without being included … nothing happened,交易确实没有执行);落后或出错的节点不会让交易显得过期。120秒内既没确认也证明不了过期时报outcome is unknown并附交易签名:交易可能已经上链,先用exchange.IO("receipt", 签名)核对再决定是否重试。节点预检报BlockhashNotFound(它还没见过这个区块哈希,交易没有发出)时换新区块哈希重签再发,最多2次。 - 撤出没有最少到手量的保护:DLMM按bin撤出的是每个bin里的份额,数量取决于撤出时各bin的构成。
- 不支持带transfer hook的Token-2022代币,以及手续费归属另一个钱包(
feeOwner)的仓位;没有lp.history、lp.stake、lp.unstake、lp.claim(farm奖励随lp.collect、lp.decrease、lp.remove一起领取)。 lp.positions按主人查仓位用节点的getProgramAccounts;官方公共节点支持,有的节点不支持或限流,这时报错。公共节点按秒限流,连接器遇到限流会退避重试;频繁查询建议配置自己的节点。
Raydium CLMM与Orca Whirlpools(与Uniswap V3相同的tick模型)与上面DLMM的不同:
- 价格离散成tick:tick
i的价格为1.0001^i(再按两种代币的精度换算),仓位区间为[tickLower,tickUpper),两端都是池子tick间距(tickSpacing)的整数倍;现价在区间内时两种代币都放,在区间外时只放一种。形状与layers同Uniswap交易所对象:curve、bidask由多个仓位组成。 - 仓位是一个NFT:
id写成raydium:NFT的mint或orca:NFT的mint(也认只写mint或仓位账户地址);NFT在谁的钱包里,仓位就归谁。lp.positions按钱包里数量为1的NFT找仓位,不需要getProgramAccounts。不支持带transfer hook的Token-2022代币。 - Raydium:新仓位是Token-2022的NFT,建仓不建元数据,押金最少:仓位账户、NFT mint、NFT账户三份租金(2026年10月合计约0.0053 SOL),
lp.remove关仓时全部退回。区间两端所在的TickArray(每个装60个tick间距)还没有时由建仓交易新建,押的租金(2026年10月约0.072 SOL/个)不退,计划的tickArraysToCreate给出要新建的。建仓、加仓以一种代币定量(SOL那一侧优先,否则价值大的一侧),另一种的上限为计划量 × (1 +slippage),价格变动使另一种超出上限时程序报PriceSlippageCheck、交易不发;撤出的最少到手量为现价下的数量 × 0.99。池子所有已初始化的奖励(即使已结束)在每次撤出、领取时一起结算,奖励代币的ATA会先建好。超出池子自带范围的tick要用池子的TickArray bitmap extension账户,没有时报错。查看不在本钱包里的单个仓位(lp.track)时用节点的getProgramAccounts按mint找NFT的持有人(官方公共节点支持)。 - Orca:新仓位用Token-2022 NFT(带元数据扩展,同Orca官方SDK);旧的SPL Token NFT仓位与Position Bundle里的仓位也能查询、加减仓、领取和关仓。每个仓位押仓位账户、NFT mint、NFT代币账户的免租额与两个tick的租金(2026年10月合计约0.0084 SOL),
lp.remove关仓时全部退回;区间两端所在的TickArray(每个覆盖88个tick间距)还没有时先新建变长TickArray,押的租金(约0.0019 SOL/个)不退。加流动性把两种币的数量作为上限交给链上(increase_liquidity_by_token_amounts_v2),链上按执行时的价格算出能加的最大流动性,价格越出slippage对应的界限时失败;撤出有最少到手量的保护(按现价估算的数量减1%)。锁仓(lock_position)的仓位减仓、关仓会在模拟时失败;只支持主部署的程序(不含Orca的immutable部署)。池子统计取自Orca公开API(api.orca.so);查看不在本钱包里的单个仓位时用节点的getTokenLargestAccounts找NFT持有人(公共节点对它限流很紧)。
监控与撤退由策略自己做:lp.positions给出是否在区间内、当前价值与未领手续费,策略据此决定调仓或止损。
风险:
- 无常损失:价格偏离建仓价越远,仓位价值相对单纯持有越低;价格上涨时仓位逐个bin卖出X,下跌时买入X。
- 价格出区间后仓位只剩一种代币,不再赚手续费,直到价格回到区间。
- 开仓押的租金:仓位账户(Raydium、Orca还有NFT)的租金撤仓时退回,新建BinArray、TickArray的租金不退;拆成多个仓位时每个都要押一份。
- 每次建仓、调仓、领取、撤出都是链上交易,要付手续费与优先费;频繁调仓的成本可能超过手续费收入。
- 计划中的预估日手续费按过去24小时成交与当前在active bin里的份额估算,不代表未来收益。
跨链桥(bridge)
exchange.IO("bridge.*", ...)经LI.FI聚合的跨链桥(Across、Stargate、CCTP、deBridge、Mayan、Relay、NEAR Intents等)把代币从本交易所对象的链转到另一条链,支持EVM链之间以及EVM与Solana之间(源链为Solana)。报价与交易由LI.FI给出,LI.FI返回序列化交易,由托管者签名、simulateTransaction模拟后广播。请求带集成方标识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 …)。
策略示例
可以直接运行的完整策略:Jupiter限价单网格(原生限价单网格)、DEX定投(原生定投)、pump.fun打新策略、DEX与CEX搬砖,见DEX策略示例。
本章内容整章阅读
| 名称 | 描述 |
| exchange.IO("route", ...) | 在Jupiter交易所对象上询价:返回一笔兑换的报价和路由,不下单。 |
| exchange.IO("token", ...) | 在Jupiter交易所对象上登记代币,或列出代币表。 |
| exchange.IO("transfer", ...) | 从Jupiter交易所对象的钱包转出SOL。 |
| exchange.IO("receipt", ...) | 在Jupiter交易所对象上查询一笔Solana交易的状态,可以等待到确认。 |
| exchange.IO("slippage", ...) | 设置Jupiter交易所对象市价单的滑点保护。 |
| exchange.IO("priorityFee", ...) | 在Jupiter交易所对象上设置兑换交易的优先费上限。 |
| exchange.IO("dexes", ...) | 在Jupiter交易所对象上限定兑换经过的流动性来源,例如只在pump.fun、Meteora或Raydium上成交。 |
| exchange.IO("rps", ...) | 在Jupiter交易所对象上设置请求Jupiter API的速率。 |
| exchange.IO("lp.pools", ...) | 列出一个代币在Meteora DLMM、Raydium CLMM与Orca Whirlpools上的集中流动性池子,按美元TVL从大到小排列。 |
| exchange.IO("lp.select", ...) | 按TVL门槛与24小时成交额,为一个代币自动选出一个集中流动性池子。 |
| exchange.IO("lp.pool", ...) | 读取一个集中流动性池子的实时状态与统计数据。 |
| exchange.IO("lp.ticks", ...) | 查看池子在一段区间内的流动性分布,按bin或tick分段给出两种代币的数量。 |
| exchange.IO("lp.plan", ...) | 按预算、价格区间与形状算出建仓计划:用哪个池子、几个仓位、各放多少两种代币、要不要先换币、押多少租金。 |
| exchange.IO("lp.simulate", ...) | 按建仓计划构造全部建仓交易,用节点模拟执行,不签名、不广播。 |
| exchange.IO("lp.add", ...) | 按建仓计划建立集中流动性仓位:缺哪种代币先用Jupiter换,每个仓位一笔链上交易。 |
| exchange.IO("lp.increase", ...) | 给已有的仓位加仓:按仓位的区间与现价把预算拆成两种代币,缺的那种先换。 |
| exchange.IO("lp.decrease", ...) | 按比例从仓位撤出流动性,同时领取全部手续费与farm奖励,仓位保留。 |
| exchange.IO("lp.collect", ...) | 领取仓位的手续费与farm奖励,不动本金。 |
| exchange.IO("lp.remove", ...) | 撤出仓位的流动性并领取手续费与奖励,全部撤出时关掉仓位、退回租金。 |
| exchange.IO("lp.positions", ...) | 列出钱包的Meteora DLMM、Raydium CLMM与Orca Whirlpools仓位,给出区间、当前数量、价值与未领手续费。 |
| exchange.IO("pump.*", ...) | 在pump.fun的联合曲线上发现新币、查看曲线状态、报价与买卖,币毕业后自动改走Jupiter兑换。 |
| exchange.IO("dca.*", ...) | 用Jupiter的定投(DCA)分批买入或卖出:创建、列出、撤销与模拟。 |
| exchange.IO("trigger.*", ...) | Jupiter原生限价单的辅助指令:选择v1或V2接口、查看V2的托管vault、模拟挂单与撤单。 |
| exchange.IO("bridge.*", ...) | 经LI.FI聚合的跨链桥把代币从Solana转到EVM链:查询链与代币、报价、模拟、发送与查询进度。 |