Alert Source Discuss
Standards Track: Interface

EIP-2696: JavaScript `request` method RPC transport

Authors Micah Zoltu (@MicahZoltu), Erik Marks (@rekmarks)
Created 2020-06-04

Simple Summary

A standard for remote procedure calls between an Ethereum Provider and an Ethereum Client when both are able to interface with each other via a shared JavaScript object.

Abstract

This standard provides the description of an object that is made available to JavaScript applications which they can use to communicate with the Ethereum blockchain through. This standard only describes the transport mechanism, it does not specify the payloads that are valid nor does it specify how the client or the provider will discover or agree on payload content.

How/where this Ethereum object is exposed is left to future standards.

Motivation

When working within a JavaScript runtime (such as NodeJS, Electron, Browser, etc.) it may be possible for the runtime or a runtime plugin to inject objects into the runtime. Someone authoring a runtime or a runtime plugin may choose to expose an Ethereum Provider to any JavaScript apps or scripts running within that runtime in order to provide indirect access to an Ethereum-like blockchain and potentially signing tools. In order to achieve maximum compatibility between the provider and the client, a standard is necessary for what the shape of that object is.

Specification

RFC-2119

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC-2119.

Interface

TypeScript interface definition:

interface RequestArguments {
	readonly method: string;
	readonly params?: readonly unknown[] | object;
}

interface EthereumProvider {
	request(args: RequestArguments): Promise<unknown>
}

The Provider MUST implement implement a request method on the exposed EthereumProvider object. The request method MUST be callable with a single parameter which contains the arguments for the request as defined in the TypeScript interface above.

If the Provider supports a JSON-RPC (https://www.jsonrpc.org/specification) request as specified elsewhere, then it MUST accept a request call for that JSON-RPC method with the RequestArguments.method argument matching the JSON-RPC method string for the RPC call and the RequestArguments.params matching the params object of the RPC call. The RequestArguments.params should be encoded as a JavaScript object matching the specified JSON-RPC type, not encoded as a JSON string as would normally be the case when transporting JSON-RPC.

Example

If the JSON-RPC request would contain a payload like:

'{ "jsonrpc": "2.0", "id": 1, "method": "do_work", "params": [ 5, "hello" ] }'

Then the matching EthereumProvider.request call would be:

declare const provider: EthereumProvider
provider.request({ method: 'method', params: [ 5, 'hello' ] })

Results

If the Provider supports a JSON-RPC request as specified elsewhere, then it MUST return an object that matches the expected result definition for the associated JSON-RPC request.

Example

If the JSON-RPC response would contain a payload like:

'{ "jsonrpc": "2.0", "id": 1, "result": { "color": "red", "value": 5 } }'

Then the matching EthereumProvider.request response would be:

{ color: 'red', value: 5 }

Errors

interface ProviderRpcError extends Error {
	message: string;
	code: number;
	data?: unknown;
}
code message meaning
4001 User Rejected Request The user rejected the request.
4100 Unauthorized The requested method and/or account has not been authorized by the user.
4200 Unsupported Method The Provider does not support the requested method.
4900 Disconnected The Provider is disconnected from all chains.
4901 Chain Disconnected The Provider is not connected to the requested chain.

If the Provider is unable to fulfill a request for any reason, it MUST resolve the promise as an error. The resolved error MUST be shaped as a ProviderRpcError defined above whenever possible. While it is impossible to guaranteed that a JavaScript application will never throw an out of memory or stack overflow error, care should be taken to ensure that promise rejections conform to the above shape whenever possible.

If a code is provided that is listed in the list above, or in the JSON-RPC specification (https://www.jsonrpc.org/specification#error_object), or in the associated JSON-RPC request standard being followed, then the error reason MUST align with the established meaning of that code and the message MUST match the provided message

The data field MAY contain any data that is relevant to the error or would help the user understand or troubleshoot the error.

Rationale

While this standard is perhaps not the greatest mechanism for communicating between an application and a blockchain, it is closely aligned with established practices within the community so migration from existing systems to this one should be relatively easy. Most communication is currently done via JSON-RPC, so aligning with the JSON-RPC standard was desired to enable quick integration with existing systems.

Security Considerations

The relationship between Ethereum Provider and client is a trusted one, where it is assumed that the user implicitly trusts the Ethereum Provider which is how it managed to get injected into the client, or the client expressly pulled in a connection to it.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Micah Zoltu (@MicahZoltu), Erik Marks (@rekmarks), "EIP-2696: JavaScript `request` method RPC transport," Ethereum Improvement Proposals, no. 2696, June 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2696.