使用Shyft GraphQL API查询Solana上的程序账户

  • Shyft_to
  • 发布于 2023-11-18 10:19
  • 阅读 7

本文介绍了Shyft GraphQL Program APIs,它提供了一种更简单有效的方式来查询Solana程序账户数据,作为传统getProgramAccounts()的替代方案,Shyft GraphQL Program APIs允许开发者轻松查询任何程序的账户数据,并支持过滤、排序和分页等功能,从而优化用户体验并简化Solana应用开发流程。

在本集中,我们将探讨如何使用 Shyft GraphQL API 在 Solana 上获取和查询整个 GovernanceV2 程序

在 Solana 上查询程序数据,graph ql api

getProgramAccounts() 的问题

作为 Solana 开发者,我们都熟悉这个重要但具有挑战性的 RPC 调用,getProgramAccounts()。虽然它是查询程序账户数据的首选方法,但其缺点不容忽视。它运行缓慢,你无法像在数据库中那样进行分页和应用过滤器。本质上,它不是生产的理想工具,如果你渴望提供无缝的用户体验,那么仅仅依靠 getProgramAccounts() 是不可行的。

缓慢的 get program accounts rpc 调用

Shyft GraphQL 程序 API:简单的解决方案

Shyft GraphQL 程序 API 来了,它改变了你与 Solana 程序账户数据交互的方式。简而言之,我们的解决方案允许你轻松地查询任何程序的账户数据,从而为传统的 getProgramAccounts() 提供强大的替代方案

Twitter 小部件 Iframe

开始使用

Shyft GraphQL 程序 API 允许你访问 mainnetdevnet 程序数据。可以从以下 URL 访问它。

Mainnet

https://programs.shyft.to/v0/graphql/?api_key={你的-api-key}&network=mainnet-beta

Devnet

https://programs.shyft.to/v0/graphql/?api_key={你的-api-key}&network=devnet

如果你不想设置代码,或者只是想看看它是如何工作的,你可以访问这些 UI 工具,它们允许你轻松地与我们的 GraphQL 程序 API 交互:

一旦你将你的 GraphQL 端点粘贴到上面的 UI 中,它将自动触发一个自省调用,获取我们当前托管的所有程序的整个 schema。它看起来会像这样

我们现在可以开始利用 Shyft GraphQL 程序 API 从 SPL Governance 程序 中检索提案数据。

要开始,我们需要一些东西。

注册你的 Shyft 账户并获得你自己的 Shyft API 密钥。

x-api-key 是一个身份验证参数,它使你有权访问 Shyft API你可以从 Shyft 网站获得你自己的 API 密钥 只需在此处使用你的电子邮件 ID 注册,你就可以免费获得它。如果你已经拥有 Shyft API 密钥,请跳过此步骤。

支持 API 调用的 NextJs 或任何开发环境/堆栈

我们在此项目中使用的是 Next JS,但这可以在任何应用程序开发环境中完成。有关 如何在 Next.js 1 3 中设置 GraphQL 的更多信息,请参阅此链接。

你可以从此 repo 克隆本文的完整源代码。

构建查询

如果你已经熟悉 GraphQL,那么构建查询非常简单。要从 SPL Governance 程序中获取提案,请使用如下查询:

query MyQuery {
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2 {
    abstainVoteWeight
    closedAt
    denyVoteWeight
    descriptionLink
    draftAt
    executingAt
    executionFlags
    governance
    governingTokenMint
    lamports
    maxVoteWeight
    maxVotingTime
    name
    options
    reserved1
    signatoriesCount
    signatoriesSignedOffCount
    signingOffAt
    startVotingAt
    state
    tokenOwnerRecord
    vetoVoteWeight
    voteThreshold
    voteType
    votingAt
    votingAtSlot
    votingCompletedAt
    pubkey
  }
}

请注意,我们已包含所有可用的数据字段;但是,你可以随意挑选对你有用的字段。例如,如果你只想要提案的 namepubkey,则查询将如下所示:

query MyQuery {
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2 {
    name
    pubkey
  }
}

要检索数据,@apollo/client 包提供了几个 React hooks,使我们能够从 GraphQL API 获取数据。在本教程中,我们将使用 useLazyQuery hook。之所以做出此选择,是因为我们希望在用户单击“搜索”按钮时手动执行查询,而不是在组件挂载时自动执行查询。

const query = gql`
  query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2 {
    name
    pubkey
  }
`;

const [getProposals, { loading, data, fetchMore }] = useLazyQuery(query);
const handleSearch = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    getProposals();
};

结果数据将如下所示

{
  "data": {
    "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2": [\
      {\
        "name": "Pay 0.1 SOL to HAzL8…tEaqf",\
        "pubkey": "H8y3YLzB3jVbx5UCY5DBXz2R5rizCBB9uUVoNMacJBRK"\
      },\
      {\
        "name": "NFT",\
        "pubkey": "3LGcrfPxtGzM25MGaKzUxefkPrage9EiWK5Dg7RRjtFF"\
      },\
      {\
        "name": "Hackathon_1.0 Prize Split",\
        "pubkey": "69Nbj3BH3kji5saLnrDJbvWKwNBqEUWtEV6vEs32nUze"\
      }\
    ]
  }
}

应用过滤器

我们不仅仅想获取所有提案;我们特别想检索那些名称包含一些用户输入文本的提案。为此,我们需要更新我们的查询以能够接受 variables

query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
  $where: GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_bool_exp
) {
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2(where: $where) {
    name
    pubkey
  }
}

现在我们可以开始获取数据了。此时,getProposals 函数需要接受变量,即用户输入的文本。

const query = gql`
  query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
    $where: GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_bool_exp
  ) {
    GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2(where: $where) {
      name
      pubkey
    }
  }
`;

const [getProposals, { loading, data, fetchMore }] = useLazyQuery(query);
const handleSearch = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();
  getProposals({
    variables: {
      where: {
        name: {
          _regex: text,
        },
      }
    }
  });
};

排序数据

我们的 GraphQL API 支持根据我们选择的数据字段对数据进行排序。例如,如果我们想按草案日期按升序对提案进行排序,我们需要更新我们的查询,使其如下所示:

query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
  $where: GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_bool_exp
  $orderBy: [GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_order_by!]
) {
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2(
    where: $where
    order_by: $orderBy
  ) {
    name
    pubkey
  }
}

与过滤数据类似,此时,我们的 getProposals 函数需要接受一个用于排序的附加变量。

const query = gql`
  query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
    $where: GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_bool_exp
    $orderBy: [GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_order_by!]
  ) {
    GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2(
      where: $where
      order_by: $orderBy
    ) {
      name
      pubkey
    }
  }
`;

const [getProposals, { loading, data, fetchMore }] = useLazyQuery(query);
const handleSearch = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();
  getProposals({
    variables: {
      where: {
        name: {
          _regex: text,
        },
      },
      orderBy: [\
        {\
          draftAt: "ASC"\
        },\
      ],
    }
  });
};

分页数据

众所周知,getProgramAccounts() 目前不支持分页。在单个调用中处理大量数据非常困难,大多数时候会导致连接超时。使用 GraphQL,分页变得非常容易。让我们获取上一个查询并尝试对 proposals account 数据进行分页。

要实现分页,我们可以在查询中指定 limitoffset 字段。limit 表示返回的行数,默认为 1000,offset 表示结果集的起始点。

query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
  $where: GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_bool_exp
  $orderBy: [GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_order_by!]
  $limit: Int
  $offset: Int
) {
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2(
    where: $where
    order_by: $orderBy
    limit: $limit
    offset: $offset
  ) {
    name
    pubkey
  }
}

现在,我们更新 getProposals 函数以接受 limitoffset 变量。

const query = gql`
  query GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
    $where: GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_bool_exp
    $orderBy: [GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2_order_by!]
    $limit: Int
    $offset: Int
  ) {
    GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_ProposalV2(
      where: $where
      order_by: $orderBy
      limit: $limit
      offset: $offset
    ) {
      name
      pubkey
    }
  }
`;

const handleSearch = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();
  getProposals({
    variables: {
      where: {
        name: {
          _regex: text,
        },
      },
      orderBy: [\
        {\
          draftAt: "ASC"\
        },\
      ],
      limit: 10,
      offset: 0,
    }
  });
};

设置好所有内容并运行应用程序后,我们会收到如下视频所示的结果。

结论

总之,处理 Solana 的 getProgramAccounts() 具有其挑战性——它速度慢、缺乏过滤等功能,并且不适合流畅的用户体验。但是 Shyft GraphQL 程序 API 来解救了!这些 API 提供了一种更简单、更好的方法来获取 Solana 中的程序账户数据。它们修复了我们使用 getProgramAccounts() 时面临的问题,并使 Solana 开发更灵活、更用户友好。随着 Solana 的发展,Shyft GraphQL 程序 API 等工具对于更顺畅、更高效的开发之旅至关重要。

我们真诚地希望你喜欢阅读这篇博客文章!如果你有任何疑问或想法,请随时访问我们的 Discord 社区。

非常感谢你抽出时间阅读本文!

资源

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

0 条评论

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