如何跟踪从 Pump.fun 到 Raydium 的代币转移

  • Team Shyft
  • 更新于 2024-12-12 16:41
  • 阅读 383

利用 Shyft gRPC实时监控代币从 Pump.fun 迁移到 Raydium

Token Transfers from Pump.fun to Raydium with gRPC Cover

在代币完成其在 Pumpfun 上的绑定曲线(bonding curve)活动后,它将迁移到 Raydium 进行交易。使用 gRPC 可以更容易地识别已迁移并在 Raydium 上积极交易的代币。

通过本文,你将学习如何使用 gRPC 和 Shyft APIs 从 Pump.fun 代币迁移到 Raydium。

入门

在你开始构建之前,注册并获取 Shyft RPC/API 和 gRPC 代币访问。

gRPC 服务不直接在 Web 浏览器中支持,因此你需要一个后端应用程序来处理 gRPC 数据。虽然本示例使用 Node.js,你可以根据自己的喜好选择各种服务器端语言,包括 C#、Go、Java、Kotlin、Python 或 PHP。

在本文中,我们将看看如何使用 gRPC 获取 Raydium 上一个代币的价格更新。我们将涵盖以下步骤

  • 设置 gRPC 连接
  • 跟踪 Pumpfun 上已完成的绑定曲线
  • 反序列化我们的 pumpfun 数据
  • 使用 Defi Api 获取流动性详情
  • 结论

与本文相关的所有代码可以在我们的 GitHub Replit 上找到。你可以克隆它并随时跟进。

设置 gRPC 连接

要开始,你需要克隆 Git 仓库。按照以下步骤操作:

  1. 打开终端。
  2. 转到要克隆的目录。

执行以下 git clone 命令:

$ git clone https://github.com/Shyft-to/solana-defi.git

安装

在终端中,导航到包含代码的文件夹,使用 cd grpc-defiapi-liquidityDetails,然后执行 npm install 安装所有依赖项。

cd grpc-pumpfun_migration  
npm install

建立 gRPC 连接

要开始流式传输,你需要配置 gRPC URL访问令牌

const client = new Client(  
    '你所在地区的 Shyft gRPC URL',  
    'Shyft gRPC 访问令牌',  
    undefined,  
  );

是时候开始流式传输了!

跟踪 Pumpfun 上已完成的代币绑定曲线

我们需要根据已经建立的逻辑确认 PumpFun 上的绑定曲线。只有已完成的绑定曲线才有资格在 Raydium 上进行迁移和交易。为了筛选相关数据,我们使用 memcmp 确保只获取已完成的绑定曲线

const req: SubscribeRequest = {  
  slots: {},  
  accounts: {  
    pumpfun: {  
      account: [],  
      filters: [  
        {  
          memcmp: {  
            offset: structure.offsetOf('complete').toString(),  
            bytes: Uint8Array.from([1]),  
          },  
        },  
      ],  
      owner: [pumpfun], //pump-fun 程序 ID  
    },  
  },  
  transactions: {},  
  blocks: {},  
  blocksMeta: {  
    block: [],  
  },  
  accountsDataSlice: [],  
  commitment: CommitmentLevel.PROCESSED,  
  entry: {},  
  transactionsStatus: {},  
};

gRPC 请求的关键组件

让我们逐步分析请求的主要部分:

  1. 账户过滤器: 这里的关键过滤器是 memcmp 过滤器,它检查代币的 complete 状态。这有助于识别已经完成其绑定曲线活动的代币,准备好迁移。
  • offset 指定了账户结构中完成状态的位置。使用 structure.offsetOf('complete') 确保我们根据代币的最终状态进行过滤。
  • 使用 Uint8Array.from([1])bytes 过滤器查找值为 1,表示绑定曲线活动已经完成。

2. 程序拥有者: owner 字段指定了 Pumpfun 程序 IDRaydium 程序 ID。这确保我们只订阅与迁移到 Raydium 的代币相关的事件。

3. 承诺级别: CommitmentLevel.PROCESSED 设置允许你订阅 已处理的块,确保你在交易和代币迁移发生时获得近实时更新。

4. 交易和块: 通过订阅这些字段,你可以跟踪代币的持续活动,监控与其迁移和交易相关的实时事件。

在我们的 stream.on 功能中,console.log 数据变量时,期望输出如下格式

filters: [ 'pumpfun' ],  
account: {  
  account: {  
     pubkey: <Buffer fc 97 83 0f e5 17 be a3 5b b8 40 7a 09 41 30 4a 07 f0 53 8f 4b 76 8e 1c d4 31 1b ee b5 8d 1a 22>,  
     lamports: '85006591115',  
     owner: <Buffer 01 56 e0 f6 93 66 5a cf 44 db 15 68 bf 17 5b aa 51 89 cb 97 f5 d2 ff 3b 65 5d 2b b6 fd 6d 18 b0>,  
     executable: false,  
     rentEpoch: '18446744073709551615',  
     data: <Buffer 17 b7 f8 37 60 d8 ac 60 00 98 12 4c 91 fe 00 00 5b 84 da c6 1a 00 00 00 00 00 00 00 00 00 00 00 5b d8 b6 ca 13 00 00 00 00 80 c6 a4 7e 8d 03 00 01>,  
     writeVersion: '1536398957277',  
     txnSignature: <Buffer 3c 9f 98 aa 21 1e a5 31 fb 9c ae a8 6c 53 df 6d 4a e0 6c d5 bf 2e fa a3 56 48 be 00 b1 ef 23 c3 46 3b 76 72 af 22 28 e1 e0 b9 57 04 d8 59 9b 97 8b 38 ... 14 more bytes>  
  },  
  slot: '300981652',  
  isStartup: false  
},  
  slot: undefined,  
  transaction: undefined,  
  block: undefined,  
  ping: undefined,  
  pong: undefined,  
  blockMeta: undefined,  
  entry: undefined  
}

反序列化 Pump.fun 数据

我们将逐步介绍如何使用提供的代码解码 Pumpfun 交易。交易数据是二进制格式,我们将使用模仿数据布局的结构解码它。

第 1 步:导入所需库

我们首先导入所需的库:


import base58 from "bs58";  
import { struct, bool, u64, Layout } from "@coral-xyz/borsh";
  • base58 用于处理 base58 编码,常用于 Solana 交易。
  • @coral-xyz/borsh 是一个强大的二进制定序/反序列化库,我们将用于定义和解码交易数据的结构。

第 2 步:定义数据结构

我们使用 borshstruct 函数定义绑定曲线交易的数据结构:

export const structure = struct([  
  u64("discriminator"),  
  u64("virtualTokenReserves"),  
  u64("virtualSolReserves"),  
  u64("realTokenReserves"),  
  u64("realSolReserves"),  
  u64("tokenTotalSupply"),  
  bool("complete"),  
]);

以下是字段的 breakdown:

  • discriminator: 数据结构的唯一标识符。
  • virtualTokenReserves: 代币的虚拟储备。
  • virtualSolReserves: Solana (SOL) 中的虚拟储备。
  • realTokenReserves: 代币的真实储备。
  • realSolReserves: SOL 中的真实储备。
  • tokenTotalSupply: 代币的总供应量。
  • complete: 一个布尔值,指示绑定曲线过程是否完成。

每个字段都映射到一个特定的类型,例如 u64(用于无符号 64 位整数)和 bool(用于布尔值)。这确保了二进制数据被正确解释。

第 3 步:解码交易数据

接下来,我们定义一个函数 bondingCurveData,根据结构解码交易缓冲区:

export function bondingCurveData(buffer: Buffer) {  
  let value = structure.decode(buffer);  
  const discriminator = BigInt(value.discriminator);  
  const virtualTokenReserves = BigInt(value.virtualTokenReserves);  
  const virtualSolReserves = BigInt(value.virtualSolReserves);  
  const realTokenReserves = BigInt(value.realTokenReserves);  
  const realSolReserves = BigInt(value.realSolReserves);  
  const tokenTotalSupply = BigInt(value.tokenTotalSupply);  
  const complete = value.complete;

  return {  
    discriminator,  
    virtualTokenReserves,  
    virtualSolReserves,  
    realTokenReserves,  
    realSolReserves,  
    tokenTotalSupply,  
    complete  
  };  
}

解码工作原理

  • 输入:该函数将 Buffer 作为输入,即原始交易数据。
  • 结构解码:我们使用 structure.decode(buffer) 将原始二进制数据解码为基于我们之前定义的字段的结构化对象。
  • BigInt 转换u64 字段被解析为 BigInt 以处理可能无法适应标准 JavaScript 数字类型的大值。
  • 布尔处理complete 字段是一个简单的布尔值,指示绑定曲线过程是否已完成。

第 4 步:处理编码数据(Base58 解码)

在某些情况下,交易数据可能以 Base58 编码。我们可以在将数据传递到 bondingCurveData 函数之前解码此数据。以下 decodeTransact 函数执行此任务:

export function decodeTransact(data) {  
  const output = base58.encode(Buffer.from(data, 'base64'));  
  return output;  
}

此函数将 base64 编码的字符串(这通常是传递交易数据的方式)转换为 Buffer,然后将其编码为 Base58。解码后,交易数据可以传递到 bondingCurveData 函数进行进一步处理。

这是完整的代码:

import base58 from "bs58";  
import { struct, bool, u64, Layout } from "@coral-xyz/borsh";

export const structure = struct([ 
    u64("discriminator"),  
    u64("virtualTokenReserves"),  
    u64("virtualSolReserves"),  
    u64("realTokenReserves"),  
    u64("realSolReserves"),  
    u64("tokenTotalSupply"),  
    bool("complete"),  
]);  

export function decodeTransact(data){  
    const output = base58.encode(Buffer.from(data,'base64'))  
    return output;  
}  

export function  bondingCurveData(buffer: Buffer) {  
    let value = structure.decode(buffer);  
    const discriminator = BigInt(value.discriminator);  
    const virtualTokenReserves = BigInt(value.virtualTokenReserves);  
    const virtualSolReserves = BigInt(value.virtualSolReserves);  
    const realTokenReserves = BigInt(value.realTokenReserves);  
    const realSolReserves = BigInt(value.realSolReserves);  
    const tokenTotalSupply = BigInt(value.tokenTotalSupply);  
    const complete = value.complete;  
    return {  
        discriminator,  
        virtualTokenReserves,  
        virtualSolReserves,  
        realTokenReserves,  
        realSolReserves,  
        tokenTotalSupply,  
        complete  
    };  
}

我们的编码结果应如下所示:

{  
  "signature": null,  
  "pubKey": "DmqJvcKbiH8L1yaFwxzLJQD7z1HrCMSAoWFs3xwEhybA",  
  "owner": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",  
  "poolstate": {  
    "discriminator": 6966180631402821399n,  
    "virtualTokenReserves": 0n,  
    "virtualSolReserves": 0n,  
    "realTokenReserves": 0n,  
    "realSolReserves": 0n,  
    "tokenTotalSupply": 1000000000000000n,  
    "complete": true  
  }  
}

附加:使用 DeFi API 获取流动性详情

Shyft 的 DeFi API 是一个聚合来自各种去中心化交易所(DEX)的数据的 API 服务。通过其 get_by_pair 端点,你可以获取与代币对相关的流动性池的详细信息。

以下是 JavaScript 中的函数:

export async function getTokenInfo(address) {  
  const url = `https://defi.shyft.to/v0/pools/get_by_pair?tokenA=${address}&tokenB=sol`;

  // 发起一个 API 请求以获取池数据  
  const response = await fetch(url, requestOptions);  
  const data = await response.json();  
  // 从响应中提取相关数据  
  const dexes = data?.result?.dexes;  
  const raydium = dexes?.raydiumAmm?.pools[0];  
  // 进一步提取 Raydium 池数据的单个属性  
  const pubKey = raydium?.pubkey;  
  const baseVault = raydium?.baseVault;  
  const quoteVault = raydium?.quoteVault;  
  const lp = raydium?.lpMint;  
  const owner = raydium?.owner;  
  // 以结构化格式返回提取的数据  
  return {  
    pubKey,  
    baseVault,  
    quoteVault,  
    lp,  
    owner  
  };  
}

实时流式传输 Pumpfun 的已迁移代币事件在 Raydium 上

以下代码的主要目标是 实时监控迁移的代币 并提供有关 流动性池绑定曲线 状态的重要细节。具体来说,正在监控 PumpFun 代币,当绑定曲线完成并已迁移到 pumpfun 时,脚本获取更新。

stream.on("data", async (data) => {  
  try{  
    const result = await tOutPut(data);  
    if(!result) return;  
    const tokenInfo = await getTokenBalance(result.pubKey);  
    const poolInfo = await getTokenInfo(tokenInfo?.ca);  
    if(poolInfo.lp === undefined) return;  
    console.log(  
      `  
      PUMPFUN -- RAYDIUM  
      CA : ${tokenInfo?.ca}  
      Name : ${tokenInfo?.name} (${tokenInfo?.symbol})  
      POOL DETAILS : Base Vault ${poolInfo?.baseVault}  
                     Quote Vault ${poolInfo?.quoteVault}  
                     Public Key ${poolInfo?.pubKey}  
                     LP Mint ${poolInfo?.lp}  
      BONDING CURVE STATUS : COMPLETED                      
      `  
   )

我们更新我们的 stream.on 函数以符合我们期望的请求格式

我们的结果应为此格式:

PUMPFUN -- RAYDIUM  
      CA : 4wFZ2by5RWPrck2TBrgpjDpA6FRuNt4Hr8zD2GWyUCVh  
      Name : Chichi (Chichi)  
      POOL DETAILS : Base Vault 9LsYe4HuGBaZMjQZiadgfgN5CWMqY7KSoZp2XoFic1Ns   
                     Quote Vault EAS5XB5NnqSPDPcMNJTNpfYKnDbWG4RYEfebyKjYhsCk  
                     Public Key EbEQF3PtZxE2WSm4vvsiHsBngjzLbesndXnadNBpagDg   
                     LP Mint 2i4BM7e8uTa95fEvq5UNwPDtA2DStfVgdiB1pBwjBo1y      
      BONDING CURVE STATUS : COMPLETED

      PUMPFUN -- RAYDIUM  
      CA : 9Jh1TuT4hat9DW2oJikrikn8R8dwxuFqJZgD1Xx3pump  
      Name : Unknown Token (Token)  
      POOL DETAILS : Base Vault APdNU7jtC6MDjZVhoy9uX9sWmyPiQ3fFhtFiX5vtSivy  
                     Quote Vault 4zwqJM5RhndH3a9j9tzzjYh771KNYh4JhmEyQ3YSFuER  
                     Public Key FEJmFht44kdSuTctSyUhkp8Mp7SuJ5zngcpyAAzH8EFf  
                     LP Mint f3PBsht2jJ2fvt9Wn3NNEVGf7K6vYdNWGG3euFPWv9w  
      BONDING CURVE STATUS : COMPLETED

结论

本质上,我们的方法涉及在 Raydium 去中心化交易所上获取已迁移的 Pumpfun 交易代币。我们利用了 Shyft 的 DeFi API 和 gRpc,这是一个强大的工具,可用于访问实时区块链数据。

如需更多支持,请加入我们的 Discord 服务器 或在 Twitter 上关注我们以获取最新动态。我们的团队在这里帮助你利用这项创新技术。

你可以在我们的 GitHub 仓库 中找到与本文相关的所有代码。你可以克隆并使用它来构建创新解决方案。

有关数据流的更多教程,请查看我们的其他文章: [在 Solana 上流式传输实时数据](https://blogs.shyft.to/how-to-stream-real-time-solana-transactions-using-shyfts-grpc-service-1a8f8ad44da3) [使用 gRPC 进行实时数据流:账户、交易、区块](https://blogs.shyft.to/real-time-data-streaming-with-grpc-accounts-transactions-blocks-734733e491ea) [如何在 Solana 上流式传输实时 Pump.fun 更新](https://medium.com/shyft-to/how-to-stream-real-time-pump-fun-updates-on-solana-29a46922ac5d),以及 [跟踪 Raydium 上的新池](https://blogs.shyft.to/how-to-track-new-pools-on-raydium-with-shyft-grpc-2497df832ea0)

资源

我是 AI 翻译官,为大家转译优秀英文文章,如有翻译不通的地方,在这里修改,还请包涵~

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Team Shyft
Team Shyft
江湖只有他的大名,没有他的介绍。