如何解码Solana上Orca池onProgramAccountChange返回的sqrtPrice数据?
解码Orca流动池sqrtPrice的方法
第一步:过滤目标池的更新数据
你的当前代码会订阅所有Whirlpool程序下的账户变更,首先要在回调里判断账户地址是否匹配目标池,避免处理无关数据:
const targetPoolPubkey = new PublicKey(poolAddress); // 在回调中添加过滤逻辑 (A) => { if (A.accountId.equals(targetPoolPubkey)) { // 仅处理目标池的数据 decodeSqrtPrice(A.accountInfo.data); } }
方法一:使用Orca Whirlpool官方SDK(最省心)
官方SDK已封装好完整的解码逻辑,直接调用即可:
- 安装依赖:
npm install @orca-so/whirlpools-sdk @solana/web3.js bn.js
- 修改代码实现解码:
const { Connection, PublicKey } = require('@solana/web3.js'); const { WhirlpoolAccount } = require('@orca-so/whirlpools-sdk'); const BN = require('bn.js'); const poolAddress = 'FpCMFDFGYotvufJ7HrFHsWEiiQCGbkLCtwHiDnh7o28Q'; const orcaTokenProgramId = 'whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc'; const solanaConnection = new Connection(HTTP_ENDPOINT,{wsEndpoint:WSS_ENDPOINT}); const targetPoolPubkey = new PublicKey(poolAddress); function decodeSqrtPrice(data) { // 解码Whirlpool账户数据 const whirlpool = WhirlpoolAccount.decode(data); // 获取sqrtPrice(BN类型,可转字符串输出) const sqrtPrice = whirlpool.sqrtPrice; console.log("实时sqrtPrice:", sqrtPrice.toString()); // 如需转换为代币对的实际价格,可使用SDK工具方法 // const price = PriceMath.sqrtPriceX64ToPrice(sqrtPrice, whirlpool.tokenDecimalsA, whirlpool.tokenDecimalsB); // console.log("实际代币价格:", price.toString()); } (async()=>{ const subscriptionId = await solanaConnection.onProgramAccountChange( new PublicKey(orcaTokenProgramId), (A) => { if (A.accountId.equals(targetPoolPubkey)) { decodeSqrtPrice(A.accountInfo.data); } }, 'processed' ); })()
方法二:手动解码(了解底层逻辑)
如果不想依赖SDK,可根据Whirlpool的账户结构手动解析。sqrtPrice是uint64类型,存储在数据的第64-71字节位置(对应结构体中sqrt_price字段的偏移量):
const BN = require('bn.js'); function decodeSqrtPriceManual(data) { // 截取sqrtPrice对应的8字节数据(小端序) const sqrtPriceBuffer = data.slice(64, 64 + 8); // 转换为BN数值 const sqrtPrice = new BN(sqrtPriceBuffer, 'le'); console.log("手动解码sqrtPrice:", sqrtPrice.toString()); }
内容的提问来源于stack exchange,提问作者user23169468
相关产品推荐
相关产品推荐

