Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON-RPC batching and request retries #2770

Closed
lithdew opened this issue Jun 4, 2024 · 3 comments
Closed

JSON-RPC batching and request retries #2770

lithdew opened this issue Jun 4, 2024 · 3 comments
Labels
enhancement New feature or request question Add this to close an issue with instructions on how to repost as a question on Stack Exchange

Comments

@lithdew
Copy link

lithdew commented Jun 4, 2024

Motivation

I noticed in the library README for the experimental SDK that two of the motivations for the API design are:

However, it is somewhat rather unclear on how i.e. batching or retrying can be implemented with the current experimental SDK.

  1. How do I have the HTTP transport automatically merge together specific multiple JSON-RPC payloads into a batch request?
  2. How do I synchronously (explicitly) invoke a batch JSON-RPC request with multiple JSON-RPC payloads crafted via. the SDK?
  3. How do I pass individual timeouts/retry options for a single scalar/JSON-RPC request via. the SDK?

Example use case

I currently manually perform fetch calls myself to perform explicit batch JSON-RPC requests. This, however, is error-prone as it would require types and validation to be handled by myself (i.e. how do I handle the case that a response field overflows Number.MAX_SAFE_INTEGER?).

export async function getTokenBalances(ownerPublicKey: string) {
  const sol = {
    jsonrpc: "2.0",
    id: 0,
    method: "getAccountInfo",
    params: [
      ownerPublicKey,
      { commitment: "confirmed", encoding: "jsonParsed" },
    ],
  };

  const usdc = {
    jsonrpc: "2.0",
    id: 1,
    method: "getTokenAccountsByOwner",
    params: [
      ownerPublicKey,
      {
        mint: USDC_TOKEN_PUBLIC_KEY,
      },
      {
        commitment: "confirmed",
        encoding: "jsonParsed",
      },
    ],
  };

  const like = {
    jsonrpc: "2.0",
    id: 2,
    method: "getTokenAccountsByOwner",
    params: [
      ownerPublicKey,
      {
        mint: LIKE_TOKEN_PUBLIC_KEY,
      },
      {
        commitment: "confirmed",
        encoding: "jsonParsed",
      },
    ],
  };

  const request = [sol, usdc, like];

  const response = await fetch(SOLANA_SERVER_RPC_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(request),
  });
  if (!response.ok) {
    throw new Error(`RPC request failed: ${response.statusText}`);
  }

  const json = await response.json();
  if (!checkSchema(getTokenBalancesResponse, json)) {
    throw new Error(`Malformed RPC response: ${JSON.stringify(json)}`);
  }

  const balances = {
    sol: BigInt(json[0].result.value?.lamports ?? 0),
    usdc: json[1].result.value.reduce(
      (
        acc,
        {
          account: {
            data: {
              parsed: { info },
            },
          },
        },
      ) => {
        if (info.state !== "initialized") {
          return acc;
        }
        return acc + BigInt(info.tokenAmount.amount);
      },
      BigInt(0),
    ),
    like: json[2].result.value.reduce(
      (
        acc,
        {
          account: {
            data: {
              parsed: { info },
            },
          },
        },
      ) => {
        if (info.state !== "initialized") {
          return acc;
        }
        return acc + BigInt(info.tokenAmount.amount);
      },
      BigInt(0),
    ),
  };

  return balances;
}

Details

Preliminarily, the only way I can imagine having such a granularity of level of options for retries/timeouts is to expose custom options on .send(). The custom options can be provided via the RpcTransport interface.

To support explicit batching, I can imagine a syntax i.e:

rpc.batch(rpc => [
  rpc.getAccountInfo(),
  rpc.getTokenAccountsByOwner(),
  rpc.getTokenAccountsByOwner(),
]).send()

The batch method can either be directly exposed on top of the Rpc interface, or otherwise be provided as a separate exported helper that takes in a Rpc instance.

@lithdew lithdew added the enhancement New feature or request label Jun 4, 2024
@lithdew lithdew changed the title JSON-RPC batching and exponential-delay request retries in experimental SDK JSON-RPC batching and request retries Jun 4, 2024
@steveluscher steveluscher added the question Add this to close an issue with instructions on how to repost as a question on Stack Exchange label Jun 4, 2024
Copy link
Contributor

github-actions bot commented Jun 4, 2024

Hi @lithdew,

Thanks for your question!

We want to make sure to keep signal strong in the GitHub issue tracker – to make sure that it remains the best place to track issues that affect the development of the Solana JavaScript SDK itself.

Questions like yours deserve a purpose-built Q&A forum. Unless there exists evidence that this is a bug with the Solana JavaScript SDK itself, please post your question to the Solana Stack Exchange using this link: https://solana.stackexchange.com/questions/ask


This automated message is a result of having added the ‘question’ tag.

@github-actions github-actions bot closed this as completed Jun 4, 2024
@steveluscher
Copy link
Collaborator

Happy to answer this over at Stack Exchange. Comment with a link to your question when you post it!

Copy link
Contributor

Because there has been no activity on this issue for 7 days since it was closed, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request question Add this to close an issue with instructions on how to repost as a question on Stack Exchange
Projects
None yet
Development

No branches or pull requests

2 participants