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

JsonRpcApiProvider: sendImmediate() #4819

Open
adraffy opened this issue Aug 25, 2024 · 2 comments
Open

JsonRpcApiProvider: sendImmediate() #4819

adraffy opened this issue Aug 25, 2024 · 2 comments
Labels
enhancement New feature or improvement.

Comments

@adraffy
Copy link

adraffy commented Aug 25, 2024

Describe the Feature

Some RPCs cannot be batched. It would be nice to be able to force a send() to only contain one request instead of using batchMaxSize = 1 on the provider.


Maybe something like sendImmediate() (same arguments as send()) except just calls _send() directly and increases #nextId

This can be accomplished currently using _send() and constructing a JsonRpcPayload and handling the JsonRpcResult | JsonRpcError result but the #nextId doesn't get updated.

Code Example

await provider.sendImmediate('eth_getProof', ...)

// alternative idea #1
provider.nextId(); // expose the incrementer

// alternative idea #2:
await provider.flushDrain(); // clears timer and flushes payloads
await provider.send('eth_getProof', ...)
await provider.flushDrain(); // not guaranteed that payloads.length = 1

Possible implementation:

export async function sendImmediate(
  provider: ethers.JsonRpcApiProvider,
  method: string,
  params: any[]
): Promise<any> {
  const payload: ethers.JsonRpcPayload = {
    method,
    params,
    id: 1, // meh
    jsonrpc: '2.0',
  };
  return provider._send(payload).then(([res]) => {
    if ('result' in res) {
      return res.result;
    } else {
      throw provider.getRpcError(payload, res);
    }
  });
}
@adraffy adraffy added the enhancement New feature or improvement. label Aug 25, 2024
@ricmoo
Copy link
Member

ricmoo commented Sep 16, 2024

Why RPC methods cannot be batched? Is that specified in the documentation?

The goal of a JsonRpcProvider is to abstract much of this away from developers and keep a nice clean interface, but requiring a bunch of low-level calls would make the interface very difficult to describe.

My current suggestion for this would be to keep two instances of providers; one that is used normally and one that is "batchless" by setting maxBatchCount to 1, since it seems it is only commands sent using the lower-level .send?

@adraffy
Copy link
Author

adraffy commented Sep 16, 2024

For example, Linea does not handle batched eth_getProof, even [{...}] (a single request in a batch)


When I control the stack, I agree, I can just use 2 providers and this is a non-issue, but almost all tooling/middleware/etc, I don't have that option, I'm given a provider that someone else created, then what? I can't modify batchMaxSize and I can't access #nextId, hence this issue.

Now that I look a bit closer, I think I could switch on the type of provider and create a temporary batchMaxSize = 1 provider by cloning _getConnection() if the provider is HTTP. I guess if it's HTTP I can just use id = 1 and otherwise batching isn't supported. I think that's what my code essentially does.


Isn't the above function general and abstract? It simply gives the developer the ability to bypass the send queue. The code above is valid implementation except it cannot update the internal private state. Here is a more complete solution that triggers all of the appropriate events.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement.
Projects
None yet
Development

No branches or pull requests

2 participants