本文介绍了如何使用 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 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!