本文介绍了如何使用 Shyft 的 gRPC 服务实时追踪 Raydium 上新建的流动性池。通过构建交易流管道,并利用特定的编码值和空字节数组进行过滤,可以高效地获取新池创建事件。该方法还可应用于其他 DEX,只需替换程序 ID 和使用相应的交易解析器。

Raydium 是 Solana 区块链上的一个自动化做市商(AMM),它通过利用流动性池来促进去中心化的代币交换。这些池充当虚拟存储库,用户可以在其中直接交换代币,而无需中央订单簿。对于积极交换和交易代币的用户,或者对于交易机器人或在 Raydium 上构建实时应用程序的人来说,及时了解平台事件(例如创建新池、池的当前状态或交换的代币)至关重要。Shyft 的 gRPC 服务可以通过提供实时流式传输功能来满足此需求,确保用户立即了解 Raydium 上任何池的任何变化或更新,从而更有效地监控和有策略地安排交换时间。
在本文中,我们将探讨如何使用 Shyft 的 gRPC 服务实时跟踪 Raydium 上新创建的池。
正在寻找一个完整的可用的示例来配合学习吗?请参考我们创建的这个 replit 项目这里。 请务必从 Shyft Discord 这里 获取你的 gRPC URL 和 访问Token,并在执行之前将其添加到 Secrets 部分。
要开始,我们需要准备一些东西。
身份验证:你的 Shyft API 密钥、gRPC 端点和 gRPC Token
你可以从 Shyft 网站获取你自己的 Shyft API 密钥(Shyft 使用的身份验证参数)。你也可以在你的 Shyft 仪表板上找到你特定区域的 gRPC 端点和访问Token。
服务端后端(如 NodeJS)来接收 gRPC 数据
由于 Web 浏览器不支持 gRPC 服务,因此你需要一个后端应用程序来接收 gRPC 数据。在本例中,我们使用了 NodeJS,但任何其他后端服务器端语言,如 C#、Go、Java、Kotlin、Python 或 PHP 也可以使用。
Shyft 的由 Geyser 驱动的 gRPC 提供流式传输服务,用于帐户更新、交易、区块和槽更新,一旦它们在链上发生。我们的计划包括集成 Shyft 的 gRPC 服务,以建立 Raydium 流动性池 v4 的交易流式传输管道。
一旦我们在后端获得这些数据,我们就可以快速分析它以识别在 Raydium 上创建新池的交易。通过使用特定的编码值和空字节数组进行过滤,我们可以高效地检索我们需要的重要的数据。这样,我们就可以专注于与 SOL 和 Serum 市场相关的流动性池,同时仍然捕获活跃的交易事件。
Shyft 的 gRPC 访问Token可在其 Discord 服务器中找到。请参阅“开始之前”部分了解更多详细信息。
一旦我们获得访问Token和 gRPC URL,我们将从 Yellow Stone 服务导入客户端类。初始化一个新客户端需要两个参数:gRPC URL 和 访问Token。客户端可以按如下方式初始化:
Shyft 提供 Dragonmouth gRPC 节点,最初由 Triton One 作为其 Yellowstone 项目的一部分开发。这些节点可以从 Solana 网络进行实时数据流式传输。
要使用 Node.js 连接到这些节点,你需要 @triton-one/yellowstone-grpc SDK。安装后,你可以初始化一个客户端对象。这包括:
@triton-one/yellowstone-grpc SDK 导入 Client 类。Client 类创建一个新的客户端对象。在初始化期间提供访问Token和 gRPC URL 作为参数。客户端可以按以下方式初始化。
import Client from "@triton-one/yellowstone-grpc";
const client = new Client(
"https://grpc.us.shyft.to", //你的区域特定的 Shyft gRPC URL
"hbdj-asjnf-access-token-asdh", //Shyft gRPC 访问Token
undefined,
);
有关如何使用 gRPC 设置客户端和流式传输交易的更详细的指南,请随时查看这篇关于 流式传输实时 Solana 交易 的文章。
Shyft 的 gRPC 服务利用订阅流来促进来自 Solana 区块链的实时更新。这些流充当持久连接,允许你的应用程序在链上发生事件时持续接收更新。要在上一步中创建的客户端上设置新的订阅流,请使用 client.subscribe() 方法。
const stream = await client.subscribe();
建立订阅流后,就可以指定你要接收哪些数据了。Shyft 的 gRPC 接口提供各种更新,包括帐户更改、交易、新区块,甚至槽更新。为避免信息过载,你可以通过订阅请求指定你实际需要的内容。
这些订阅请求有不同的格式,每种格式都有自己的一组参数,它们看起来有点像这样
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
const req: SubscribeRequest = {
accounts: {},
slots: {},
transactions: {},
transactionsStatus: {},
entry: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
ping: undefined,
commitment: CommitmentLevel.CONFIRMED,
};
大多数请求参数是不言自明的,与它们的名称完全一致,
在本教程中,我们将使用 AccountDataSlice。以下是接收 Raydium 交易的示例订阅请求:
const request: SubscribeRequest = {
"slots": {},
"accounts": {
"raydium": {
"account": [],
"filters": [\
{\
"memcmp": {\
"offset": LIQUIDITY_STATE_LAYOUT_V4.offsetOf('quoteMint').toString(), // 仅过滤与 SOL 配对的代币\
"base58": "So11111111111111111111111111111111111111112"\
}\
},\
{\
"memcmp": {\
"offset": LIQUIDITY_STATE_LAYOUT_V4.offsetOf('marketProgramId').toString(), // 仅过滤包含 Serum 引用的 Raydium 市场\
"base58": "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX"\
}\
},\
{\
"memcmp": {\
"offset": LIQUIDITY_STATE_LAYOUT_V4.offsetOf('swapQuoteInAmount').toString(), // 用于过滤新代币的黑客。可能有一种更好的方法\
"bytes": Uint8Array.from([0])\
}\
},\
{\
"memcmp": {\
"offset": LIQUIDITY_STATE_LAYOUT_V4.offsetOf('swapBaseOutAmount').toString(), // 用于过滤新代币的黑客。可能有一种更好的方法\
"bytes": Uint8Array.from([0])\
}\
}\
],
"owner": ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"] // 要订阅的 raydium 程序 ID
}
},
"transactions": {},
"blocks": {},
"blocksMeta": {
"block": []
},
"accountsDataSlice": [],
"commitment": CommitmentLevel.PROCESSED, // 订阅处理的区块以获得最快的更新
entry: {},
transactionsStatus: {}
}
在此代码段中,我们正在配置对 Solana 账户的订阅,以监视具有特定过滤器的 Raydium 流动性池。以下是对配置的详细分解:
slots:此参数是一个空对象,表示未订阅任何特定的槽数据。accounts:此部分配置对特定 Solana 帐户的订阅。在本例中,我们关注的是 Raydium 程序:I. raydium:这是我们为其设置过滤器的帐户类别的名称。
a. account:一个空数组,表示没有直接订阅任何特定帐户。
b. filters:这是一组缩小我们感兴趣的帐户的标准:
b.i. : memcmp:此过滤器用于匹配帐户数据中特定字节偏移量处的数据。offset 指定要检查的字节位置,而 base58 或 bytes 指定要匹配的数据,它告诉系统在二进制结构中的哪个位置查找特定信息。即 "offset":LIQUIDITY_STATE_LAYOUT_V4.offsetOf('quoteMint').toString();
c. quoteMint:过滤 quoteMint 字段与特定 base58 编码的 mint 地址(So11111111111111111111111111111111111111112)匹配的帐户。这用于专注于与 SOL 配对的代币。通过将其与 base58 编码的值(如 "So11111111111111111111111111111111111111112") 匹配,你可以过滤掉专门与 SOL 配对的流动性池。这确保你只收到与涉及 SOL 的交易或流动性相关的数据,从而使你的分析更加集中和高效。
d. marketProgramId:过滤 marketProgramId 字段与 base58 编码的 Serum 程序 ID(srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX)匹配的帐户。base58 值(例如 "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX") 对应于 Serum 市场程序。通过过滤此值,你可以确保你只监视与 Serum 去中心化交易所交互的流动性池,这对于跟踪相关的交易活动和价格变动至关重要。
e. swapQuoteInAmount 和 swapBaseOutAmount:这些字段用作粗略的过滤器,通过检查这些值为零的帐户来识别新代币。此方法是一种解决方法,可能不是过滤新代币的最有效方法。
f. owner:指定我们感兴趣的帐户的所有者。在本例中,我们的目标是 Raydium 程序 ID(675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8)拥有的帐户。
3. transactions 、 blocks 、 blocksMeta 、 accountsDataSlice 、 entry 、 transactionsStatus:这些设置为空对象或数组,表示此请求中没有交易数据、区块或其他参数的特定配置或订阅。
4. commitment:此字段定义订阅数据的确认级别:
I. CommitmentLevel.PROCESSED:此级别确保你在 Solana 网络处理更新后立即收到更新,提供最快的更新,但确认程度可能较低。
成功设置流后,必须有一个函数来处理收到的交易以进行进一步操作。stream.on('data', callbackFunc()) 方法处理流,如下所示。
//处理流的回调函数
stream.on("data", async (data) => {
try{
if (data.account != undefined) {
const info = await tOutPut(data);
console.log(
new Date(),
":",
`New transaction https://translator.shyft.to/tx/${info.signature} \n`,
JSON.stringify(info, null, 2) + "\n",
);
}
}catch(error){
if(error){
console.log(error)
}
}
});
虽然 gRPC 流式传输提供了一种可靠的接收实时数据的方式,但意外的网络问题仍然会中断连接。为确保无缝体验,你可以在应用程序中实施重新连接机制。以下示例机制将在 gRPC 流断开连接时自动尝试重新建立连接。
async function subscribeCommand(client: Client, args: SubscribeRequest) {
while (true) {
try {
await handleStream(client, args); //处理流的函数
} catch (error) {
//如果流由于任何错误而断开连接,这将等待一秒钟并重新启动流
console.error("Stream error, restarting in 1 second...", error);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
}
因此,我们已经看到了 Shyft 的 gRPC 服务,你可以轻松地实时流式传输 Solana 交易。以下是从 gRPC 接收的原始交易:
2024-09-07T08:04:52.816Z : New transaction https://translator.shyft.to/tx/2y9VYJ944mZM2LUms5TSNH6cfSjqQMH1sde62bb2KCG6s7xXEDYV6wgCoQAa8ZSUF8AAdM19rvJ6UAnmsqYxPttM
{
"filters": [\
"raydium"\
],
"account": {
"account": {
"pubkey": {
"type": "Buffer",
"data": [\
127,\
210,\
158,\
190,\
141,\
181,\
87,\
182,\
122,\
33,\
191,\
96,\
181,\
133,\
115,\
87,\
254,\
58,\
71,\
41,\
63,\
49,\
147,\
127,\
94,\
42,\
248,\
21,\
104,\
234,\
112,\
121...\
]
},
"lamports": "6124800",
"owner": {
"type": "Buffer",
"data": [\
75,\
217,\
73,\
196,\
54,\
2,\
195,\
63,\
32,\
119,\
144,\
237,\
22,\
163,\
82,\
76,\
161,\
185,\
151,\
92,\
241,\
33,\
162,\
169,\
12,\
255,\
236,\
125,\
248,\
182,\
138,\
205\
]
},
"executable": false,
"rentEpoch": "18446744073709551615",
"data": {
"type": "Buffer",
"data": [\
6,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
254,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
0,\
0..\
]
},
"writeVersion": "1420851011205",
"txnSignature": {
"type": "Buffer",
"data": [\
98,\
111,\
127,\
61,\
204,\
178,\
57,\
89,\
191,\
6,\
80,\
208,\
11,\
5,\
56,\
145,\
243,\
41,\
76,\
253,\
154,\
116,\
203,\
15,\
189,\
83,\
136,\
227,\
86,\
200,\
119,\
38,\
210,\
69,\
229,\
210,\
238,\
115,\
14...\
]
}
},
"slot": "288313982",
"isStartup": false
}
}
与传统的 RPC 响应相比,gRPC 交易流提供类似的数据,但有一些额外的字段。一些 相关的额外字段 包括 加粗isVote加粗,用于识别投票交易,加粗message headers加粗,详细说明签名者信息。响应还表示它是否是 加粗版本化的交易加粗,并且它还为 加粗区块加粗、 加粗ping加粗 和 加粗条目加粗 提供了规定。
要将从 gRPC 接收到的此交易转换为像交易一样的传统 RPC,我们使用 Shyft 创建的以下实用程序函数。
import { TransactionFormatter } from "./utils/transaction-formatter";
const TXN_FORMATTER = new TransactionFormatter();
const txn = TXN_FORMATTER.formTransactionFromJson(
data.transaction,
Date.now(),
);
此函数通过返回 slot、version、blocktime、meta 和 transactions 来镜像传统的 Solana 的 getTransaction,从而 加粗易于与现有 Solana 应用程序集成。
下一步涉及识别创建 Raydium 上新池的交易。每当在 Raydium 中创建新池时,都会在区块链上执行包含 memcmp 指令的特定交易。由于我们已经在实时流式传输与 Raydium 相关的交易,因此我们可以访问与 Raydium 协议相关的所有交易。
但是,我们需要分析从 gRPC 流接收到的这些原始交易,以识别包含 memcmp 指令的交易,并且只有在 解析交易后才有可能。我们使用 Shyft 的交易解析器来解析从 gRPC 接收到的原始 Raydium 交易。

已解析的 Raydium 更新
在我们分解交易(解析)后,我们会得到一个“过滤器”列表,这些过滤器本质上是在执行交易时执行的操作。每个过滤器都有详细信息,例如交换中使用的金额(设置为零值)、它连接到的程序(如 Raydium)以及涉及的帐户(quoteMint、baseMint)。我们的工作是加粗利用 accountDataSlice 并查看是否有具有 memcmp 对象的特定帐户。加粗 如果我们找到其中一个,那么该交易正在创建一个新池!
此池检测方法的妙处在于其适应性!它可以应用于其他去中心化交易所 (DEX),这些交易所使用类似的创建池(初始化)指令来创建池。一些示例包括 Meteora、Orca 和 Jupiter。
核心步骤基本保持不变,但有两个关键调整:

通过实施这些调整,你可以有效地识别 Solana 区块链上各种 DEX 的新池创建事件。这使你能够保持领先地位并探索 DeFi 生态系统中的各种池机会。
这就是关于本文的全部内容。如果你想了解更多关于 gRPC 的信息,请随时查看 如何在 Solana 上设置 gRPC 流式传输,或者 使用 Shyft 构建交易机器人。非常感谢你的阅读时间,请继续关注更多 Defi 开发见解!
如果你想要完整的可用示例,这里是 git 存储库,我们已创建供你试用。请确保在试用之前将你的特定区域的 gRPC url 和 访问Token 添加到“Secrets”部分。
- 原文链接: blogs.shyft.to/how-to-tr...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!