新消息:Helius 收购 Light Protocol
重磅推出:更快的 getProgramAccounts (gPA) 调用
博客/更新

重磅推出:更快的 getProgramAccounts (gPA) 调用

Developer Experience EngineerX 上的 0xIchigoLinkedIn 上的 0xIchigoGitHub 上的 0xIchigo
阅读需 3 分钟

getProgramAccounts (gPA) 调用一直以来问题重重。这个 RPC 方法开销大且效率低,需要查询节点以获取指定公钥拥有的所有账户。这类调用通常速度很慢,并受到严格的速率限制。如果结果尚未缓存,有时甚至会被直接禁止调用(例如对 Serum 程序发起 gPA 调用)。这些问题迫使开发者费力寻找其他效率不高的替代方案。 

今天,这一切将发生改变。

Helius 现面向所有 Solana 开发者推出更快的 getProgramAccounts 调用。 

以下是本次更新:

  • 我们大幅改进了账户索引
  • gPA 调用速度预计可提升至原来的 2–10 倍,尤其是在对大型程序使用过滤器时
  • 在任何开发者首次调用某个程序后,我们都会自动为其建立索引,让所有人都能获得更好的性能

开始使用

首先,在 Helius 开发者控制面板注册,并前往“API Keys”部分获取 API 密钥。 

getProgramAccounts 示例

我们来使用 JavaScript 查询 Ore V2 程序拥有的所有账户:

代码
const url = `https://mainnet.helius-rpc.com/?api-key=<API_KEY>`;

const getProgramAccounts = async () => {
  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "test",
        method: "getProgramAccounts",
        params: [
          "oreV2ZymfyeXgNgBdqMkumTqqAprVqgBWQfoYkrtKWQ",
          {
            "encoding": "base64",
          },

        ],

      })
    });

    const data = await response.json();

    console.log(`All Accounts Owned By The Ore v2 Program: ${JSON.stringify(data, null, 2)}`);
  } catch (error) {
    console.error(error);
  }
};

getProgramAccounts();

下面来拆解这段代码的工作原理:

  1. URL 配置:我们创建一个指向 Helius RPC 端点的 URL,并提供 API 密钥
  2. RPC 请求结构
    • method:“getProgramAccounts**”**表示我们要查询程序拥有的账户
    • params 是一个包含两个元素的数组:要查询的程序 ID(在本例中为 Ore V2 程序)以及查询的配置对象
  3. 编码:我们请求以 base64 编码返回账户数据
  4. 错误处理:我们使用 try/catch 块处理抛出的所有错误

运行这段代码后,Ore V2 程序拥有的所有账户都会输出到控制台。 

不过,这只是一个基础示例。通常,你需要使用过滤器缩小结果范围并提升性能。

使用过滤器的 getProgramAccounts 示例

下面来看一个更实用的示例:使用过滤器查询特定地址拥有的所有代币账户:

代码
const url = `https://mainnet.helius-rpc.com/?api-key=<API_KEY>`;

const getTokenAccounts = async () => {
  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "token-accounts",
        method: "getProgramAccounts",
        params: [
          "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",  // Token Program address
          {
            "encoding": "jsonParsed",  // Get parsed token data
            "filters": [
              {
                "dataSize": 165,  // Size of token account data
              },
              {
                "memcmp": {
                  "offset": 32,  // Location of owner address in the token account
                  "bytes": "YOUR_WALLET_ADDRESS"
                }
              }
            ]
          }
        ]
      })
    });
    const data = await response.json();

    data.result.forEach((account, i) => {
      const parsed = account.account.data.parsed.info;

      console.log(`-- Token Account ${i + 1}: ${account.pubkey} --`);
      console.log(`Mint: ${parsed.mint}`);
      console.log(`Amount: ${parsed.tokenAmount.uiAmount}`);
    });
  } catch (error) {
    console.error("Error fetching token accounts:", error);
  }
};

getTokenAccounts();

这个示例以基础示例为基础,演示了两种重要的过滤方法:使用 dataSize 和 memcmp 过滤器。

dataSize

dataSize 过滤器会检查指定账户的确切数据大小。在本例中,我们关注的是大小为 165 字节的代币账户。这样可以立即过滤掉指定钱包拥有的所有非代币账户。

memcmp 过滤器(内存比较)

memcmp 过滤器也称为内存比较过滤器,可用于比较存储在内存特定位置的数据。我们使用偏移量指定开始比较数据的位置。 

在本例中,我们使用 32 的偏移量跳过存储在内存前 32 个字节中的铸币地址,因为我们只关注所有者地址。此过滤器只会返回指定钱包地址拥有的账户。

运行这段代码后,指定钱包地址的所有代币账户及其余额列表都会输出到控制台。得益于 Helius 改进后的索引,这类过滤查询比其他传统 RPC 提供商快得多。

获取更多帮助

准备好告别繁琐问题,体验更快的 getProgramAccounts 调用了吗? 

立即在 Helius 开发者控制面板注册,以更高性能开始构建。需要帮助?如有任何问题或需要支持,请访问 Helius Discord!

如果你读到了这里,感谢你,anon!请务必在下方输入电子邮箱地址,以免错过 Solana 的任何最新动态。正在集中学习?浏览我们博客上的最新文章,加速你的 Solana 探索之旅。

订阅 Helius

及时了解 Solana 开发的最新动态,并在我们发布新内容时收到更新