如何在 Pumpfun 上流式传输 Bonding Curve 交易

  • Shyft_to
  • 发布于 2025-01-15 22:40
  • 阅读 16

本文介绍了如何使用 gRPC 协议来追踪 Solana 链上 Pumpfun 平台 Bonding Curve 的交易。

使用 gRPC 在 Pump Fun 上跟踪 Bonding Curve 交易的全面指南

Streaming Bonding Curve Transactions for Pump.fun

自从去中心化金融 (Defi) 出现以来,理解 bonding curve 及其估值对于参与流动性池和代币经济学的每个人来说都至关重要。Bonding curve 是描述代币价格与其流通供应量之间关系的数学函数,从而在 Defi 协议中实现自动化的做市和流动性提供。

Pumpfun 是 Solana 区块链上的一个平台,允许用户使用 bonding curve 模型创建和交易 meme 币。该模型根据需求动态调整代币价格,确保公平透明的交易体验。当代币的市值达到 69,000 美元或其池价值达到 86 SOL 时,Pumpfun 会自动向去中心化交易所 (DEX) Raydium 添加流动性,以提高交易效率。

在本教程中,我们将探讨如何使用 gRPC 在 Pumpfun 上流式传输 bonding curve 交易。

开始之前

要开始使用,你需要一些必需品:

1. 身份验证:Shyft API 密钥、gRPC 端点和 gRPC Token

  • Shyft API 密钥: 所有 Shyft 服务都需要 API 密钥进行身份验证。你可以通过使用你的电子邮件在 Shyft 网站 上注册来免费获取你的 API 密钥。
  • gRPC 端点和Token: Shyft 的 gRPC 节点在全球范围内可用。要访问它们,你需要特定于区域的 gRPC 端点和访问Token。你可以在你的 Shyft Dashboard 上找到端点和你的访问Token。

2. 用于接收 gRPC 数据的服务器端后端(例如,Node.js)

由于 Web 浏览器不支持 gRPC 服务,因此你需要一个后端应用程序来处理 gRPC 数据。在此示例中,我们使用 Node.js,但也可以使用其他服务器端语言,例如 C#、Go、Java、Kotlin、Python 或 PHP。

简介 - 将要涵盖的主题

在本文中,我们将研究如何使用 gRPC 在 Pumpfun 上流式传输 Bonding Curve 交易。我们将涵盖以下主题,

  • 克隆 git 存储库
  • 安装依赖项
  • 设置到 Solana 网络的 gRPC 连接
  • 检索 Bonding Curve 地址和池价值
  • 确定 Bonding Curve 完成情况
  • 结论

有关在 Solana 上来自 Pumpfun 的流式实时更新的全面指南,请参阅我们的文章:如何在 Solana 上流式传输实时 Pumpfun 更新

克隆 Git 存储库

要开始使用,你需要克隆包含代码的 Git 存储库。请按照下列步骤操作:

  1. 打开你的终端。
  2. 导航到要克隆存储库的目录。
  3. 执行命令 git clone,后跟存储库 URL。 例如:
$ git clone https://github.com/Shyft-to/solana-defi.git

安装依赖项

在你的终端中,通过运行 cd grpc-moonshot 导航到包含代码的文件夹,然后通过执行 npm install 安装所有依赖项。

cd grpc-pump-curveBonding
npm install

与本文相关的所有代码都可以在我们的 GitHub 在这里 获得。欢迎你克隆它并继续学习。

设置到 Solana 网络的 gRPC 连接

要开始使用 gRPC 从 Pumpfun 流式传输数据,你需要建立客户端服务。这涉及两个重要信息:gRPC URLgRPC 访问Token。访问Token是一种安全凭证,通常是一个长的字母数字字符串,而 URL 对应于你特定区域的 gRPC 端点。有了这些详细信息,你就可以配置客户端服务并开始从 Pumpfun 流式传输数据。

const client = new Client(
    'Your Region specific Shyft gRPC URL',
    'Shyft gRPC Access Token',
    undefined,
  );

现在我们可以继续从区块链获取我们的数据。

检索 Bonding Curve 地址

要从 Pumpfun 流式传输数据,仅建立连接是不够的。我们需要获取 bonding curve 交易详细信息,其中包括 Bonding Curve 的合约地址和池代币详细信息,我们使用钱包代币 API 来获取必要的数据。要检索数据,我们将使用 memcmp 来过滤我们的 pumpfun 交易。我们的代码结构如下所示:

const req: SubscribeRequest = {
  "slots": {},
  "accounts": {
    "raydium": {
      "account": [],
      "filters": [],
      "owner": [pumpfun]
    }
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {
    "block": []
  },
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.PROCESSED, // Subscribe to processed blocks for the fastest updates
  entry: {},
  transactionsStatus: {}
}

我们的原始交易应该以全面而详细的格式呈现,以确保清晰度和可访问性

{
  filters: [ 'pumpfun' ],
  account: {
    account: {
      pubkey: <Buffer 94 3c 0a 59 44 07 80 77 53 51 c6 e0 fd 26 20 83 ef ad cb d5 d2 fc 5c 22 84 9d 19 8b 0b 1e e7 a6>,
      lamports: '1232028',
      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 a4 86 a2 47 e3 cf 03 00 6c ac 23 fc 06 00 00 00 a4 ee 8f fb 51 d1 02 00 6c 00 00 00 00 00 00 00 00 80 c6 a4 7e 8d 03 00 00>,
      writeVersion: '1455967774790',
      txnSignature: undefined
    },
    slot: '292282145',
    isStartup: false
  },
  slot: undefined,
  transaction: undefined,
  block: undefined,
  ping: undefined,
  pong: undefined,
  blockMeta: undefined,
  entry: undefined
}

要检索我们的池详细信息,我们将使用 Shyft 的 DeFi API。此过程涉及向为获取池信息而设计的 API 端点发出请求。

var myHeaders = new Headers();
export const api = "api"
myHeaders.append("x-api-key", api);

var requestOptions:any = {
  method: 'GET',
  headers: myHeaders,
  redirect: 'follow'
};
export async function getTokenBalance(address){

 const info = await fetch(`https://api.shyft.to/sol/v1/wallet/all_tokens?network=mainnet-beta&wallet=${address}`, requestOptions)
 const infoJson = await info.json();
 const result = infoJson?.result[0];
 const ca = result?.address
 const name = result?.info?.name
 const symbol = result?.info.symbol
const balance = result?.balance;
 return {
  name,
  symbol,
  ca,
  balance
 };
}

这是我们的结果应该呈现的样子:

{
  name: 'Key Opinion Loser',
  symbol: 'KOL',
  ca: 'KoL17ZJJ8ccwM2zxvpvDuVD9YpMW4KumAsaRFB9JCKe',
  balance: 0
}

解码和定义交易

我们的输出目前采用 Buffer 格式,这种格式不是很用户友好。为了使这些数据更易于访问和理解,我们需要将它们解码并修剪为更易读的文本格式。

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
    };
  }

我们通过定义 pumpfun 帐户数据的 struct 对其进行解码

import { LIQUIDITY_STATE_LAYOUT_V4 } from "@raydium-io/raydium-sdk";
import { bondingCurveData, decodeTransact } from "./decodeTransaction";

/**
 * Deserializes and trims blockchain data to extract relevant information.
 * @param {Object} data - The data object containing blockchain account information.
 * @returns {Object} - An object containing the deserialized signature, public key, owner, and pool state.
 */
export function tOutPut(data) {
    // Ensure data is defined and contains the necessary properties
    if (!data || !data.account || !data.account.account) {
        throw new Error("Invalid data format");
    }

    const dataTx = data.account.account;

    // Safely decode each piece of transaction data
    const signature = dataTx.txnSignature ? decodeTransact(dataTx.txnSignature) : null;
    const pubKey = dataTx.pubkey ? decodeTransact(dataTx.pubkey) : null;
    const owner = dataTx.owner ? decodeTransact(dataTx.owner) : null;

    let poolstate = null;
    try {
        poolstate = bondingCurveData(dataTx.data);

    } catch (error) {
        console.error("Failed to decode pool state:", error);
    }

    return {
        signature,
        pubKey,
        owner,
        poolstate
    };
}

这是我们希望在控制台输出中实现的结果。

{
  signature: '3PfY1M74yoKerd38LV7ZYQejVBxiYGCW2BmhfEr2UGGt5eAWQGRkdFJUniqvr6yyZMVCsYxMTJQmymXT9ECEFR3J',
  pubKey: 'LjCVC9PKfX5WzWTbD6T1tHbHW4EDCuk3cdE53BTwXxa',
  owner: '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P',
  poolstate: {
    discriminator: 6966180631402821399n,
    virtualTokenReserves: 925163590557167n,
    virtualSolReserves: 34793847131n,
    realTokenReserves: 645263590557167n,
    realSolReserves: 4793847131n,
    tokenTotalSupply: 1000000000000000n,
    complete: false
  }
}

确定 Bonding Curve 完成情况

当我们利用 memcmp 来检索 Pumpfun 上的 Bonding Curve 完成情况时,我们的代码变得更加简单。这种方法使我们能够显著简化我们的流程。通过仅关注过滤我们的交易,我们可以有效地隔离我们分析所需的关联数据。 这种优化不仅降低了复杂性,而且提高了性能,使处理我们需要的特定交易细节变得更加容易。

const req: SubscribeRequest = {
  "slots": {},
  "accounts": {
    "raydium": {
      "account": [],
      "filters": [\
        {\
          "memcmp": {\
            "offset": structure.offsetOf('complete').toString(),\
            "bytes" : Uint8Array.from([1])\
          }\
        }\
      ],
      "owner": [pumpfun]
    }
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {
    "block": []
  },
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.PROCESSED, // Subscribe to processed blocks for the fastest updates
  entry: {},
  transactionsStatus: {}
}

我们应该预计从 API 请求中收到以下输出。

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

要继续,我们应该增强我们的 stream.on 函数,以包含检索池详细信息的功能。

 stream.on("data", async (data) => {
    try{
    const result = await tOutPut(data);
    const tokenInfo = await getTokenBalance(result.pubKey);
    console.log(
      `
      CA : ${tokenInfo.ca}
      Name : ${tokenInfo.name} (${tokenInfo.symbol})
      POOL DETAILS : 0 ${tokenInfo.symbol}
                     0 SOL
      BONDING CURVE STATUS : COMPLETE
      `
    )
}catch(error){
  if(error){
    console.log(error)
  }
}
});

我们希望确保我们的控制台输出以清晰且信息丰富的方式格式化。

      CA : 7FhLiAXYaJX1HbpJPqASucasxdRYRUbvR25QVXfxua3G
      Name : VibeAI (VAI)
      POOL DETAILS : 0 VAI
                     0 SOL
      BONDING CURVE STATUS : COMPLETED

      CA : 4iBqSNn9i3PqNv1shXVHjEWkD7MvoaZmcCFpTJSwNqep
      Name : Its Over Cat (OVER)
      POOL DETAILS : 0 OVER
                     0 SOL
      BONDING CURVE STATUS : COMPLETED

结论

我们很高兴推出用于 在 Solana 区块链上流式传输数据的新解决方案:gRPC。这项技术简化了访问链上数据的过程,使开发人员能够专注于创建利用 Solana 区块链的强大应用程序。 gRPC 简化了代码库并减少了延迟,从而使数据传输更快、更高效。传统上,使用专用节点在 Solana 上流式传输数据一直很复杂且资源密集,通常需要更精细的代码库。但是,gRPC 简化了此过程,使开发人员可以轻松构建最复杂的项目。

使用 gRPC 进行 Solana 区块链开发的主要优势包括:

  • 精简的代码库,便于数据流式传输
  • 减少延迟以加快数据传输
  • 简化了复杂项目的开发

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

你可以在我们的 GitHub 存储库 上找到与本文相关的所有代码。请随意克隆并继续学习。有关在 Solana 上进行数据流式传输的更多见解,请浏览我们的其他文章: 在 Solana 上进行实时数据流媒体传输 使用 gRPC 进行实时数据流媒体传输:帐户、交易、区块 如何在 Solana 上进行实时 Pump.fun 更新流媒体传输 跟踪 Raydium 上的新池

资源

  • 原文链接: blogs.shyft.to/how-to-st...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Shyft_to
Shyft_to
在 Solana上更快更智能地构建,使用Shyft的SuperIndexer、gRPC、RPC、API和SDK