Skip to content

Optimize Solana Client RPC Requests #421

@amilz

Description

@amilz

Problem

Solana Client current makes several RPC requests to assemble a payment transaction. Most of these requests are fetching static information, so requests add latency.
There's some balance required here beteween latency/devex/ux/on-chain CU/prio fees.

Existing RPC Calls

  1. simulate for CU estimation
  2. fetchMaybeAccount on the ATA to see if it exists or not
  3. fetchMint to check mint's token program
  4. fetch blockhash for final txn (still required)

At present the scope of the payment transaction generated by the client is very narrow & predictable. We arguably should only be making the blockhash fetch. I think we could do:

  1. Static CU Configuration: Since every transaction gets verified in a very predicitible format, it might make more sense to set CUs as const based on config, e.g.,
  const PAYMENT_COMPUTE_UNITS = {
    tokenProgram: {
      withAta: 20_000, // example placeholder values...would need to check these
      withoutAta: 15_000,
    },
    token2022: {
      withAta: 25_000,
      withoutAta: 20_000,
    },
  };
  1. Idemopotent ATA Ix: Instead of fetching the ATA to see if it exists, I'd suggest using getCreateAssociatedTokenIdempotentInstruction which effectively handles the same check but during program execution.
  2. Token Program Server Response: Token Program is static as well -- having the client helper check token program abstracts this from the client but also adds latency to making a payment. I think better approach here might be to use TOKEN_PROGRAM by default and add tokenProgram to the SPLTokenAmount here which could be passed as an extra in the server response like done for eip72.

Discussion from #416

@notorious-d-e-v

Regarding the client use of RPC -- agree it's probably better as a separate PR.

simulate for CU estimation.

I really like saving an RPC call by having static compute unit estimates. Is it possible that those numbers can change down the line due to solana-side upgrades/changes? If not then seems like a great idea!

fetchMaybeAccount on the ATA to see if it exists or not

The reason we chose to go with two branches (one to create the ATA if needed, and the other one to not create the ATA) was that in most cases you won't need to create an ATA, as the ATA only needs to be created once per (merchant address, token).

So we decided to prioritize a lower network fee in most cases, compared to the one-time setup of creating the ATA (and extra RPC call).

I believe the CreateIdempotentATA instruction added 30,000 or so compute units to each transaction. Table of CU costs

Token Program Server Response: Token Program is static as well -- having the client helper check token program abstracts this from the client but also adds latency to making a payment. I think better approach here might be to use TOKEN_PROGRAM by default and add tokenProgram to the SPLTokenAmount here which could be passed as an extra in the server response like done for eip72.

Does that mean the server will end up doing the lookup? If this then we are just moving the rpc call somewhere else.

Or is the developer expected to type that by hand? If this then we are maybe making devex worse.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions