利用 Shyft gRPC实时监控代币从 Pump.fun 迁移到 Raydium
- 原文链接:blogs.shyft.to/how-to-track...
- 译者:AI翻译官,校对:翻译小组
- 本文链接:learnblockchain.cn/article…
在代币完成其在 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 上一个代币的价格更新。我们将涵盖以下步骤
要开始,你需要克隆 Git 仓库。按照以下步骤操作:
执行以下 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 URL 和 访问令牌。
const client = new Client(
'你所在地区的 Shyft gRPC URL',
'Shyft gRPC 访问令牌',
undefined,
);
是时候开始流式传输了!
我们需要根据已经建立的逻辑确认 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: {},
};
让我们逐步分析请求的主要部分:
memcmp
过滤器,它检查代币的 complete
状态。这有助于识别已经完成其绑定曲线活动的代币,准备好迁移。offset
指定了账户结构中完成状态的位置。使用 structure.offsetOf('complete')
确保我们根据代币的最终状态进行过滤。Uint8Array.from([1])
的 bytes
过滤器查找值为 1
,表示绑定曲线活动已经完成。2. 程序拥有者: owner 字段指定了 Pumpfun 程序 ID 或 Raydium 程序 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
}
我们将逐步介绍如何使用提供的代码解码 Pumpfun 交易。交易数据是二进制格式,我们将使用模仿数据布局的结构解码它。
我们首先导入所需的库:
import base58 from "bs58";
import { struct, bool, u64, Layout } from "@coral-xyz/borsh";
base58
用于处理 base58 编码,常用于 Solana 交易。@coral-xyz/borsh
是一个强大的二进制定序/反序列化库,我们将用于定义和解码交易数据的结构。我们使用 borsh
的 struct
函数定义绑定曲线交易的数据结构:
export const structure = struct([
u64("discriminator"),
u64("virtualTokenReserves"),
u64("virtualSolReserves"),
u64("realTokenReserves"),
u64("realSolReserves"),
u64("tokenTotalSupply"),
bool("complete"),
]);
以下是字段的 breakdown:
每个字段都映射到一个特定的类型,例如 u64
(用于无符号 64 位整数)和 bool
(用于布尔值)。这确保了二进制数据被正确解释。
接下来,我们定义一个函数 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)
将原始二进制数据解码为基于我们之前定义的字段的结构化对象。u64
字段被解析为 BigInt
以处理可能无法适应标准 JavaScript 数字类型的大值。complete
字段是一个简单的布尔值,指示绑定曲线过程是否已完成。在某些情况下,交易数据可能以 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
}
}
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
代币,当绑定曲线完成并已迁移到 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)。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!