EIP-2696: JavaScript `request` method RPC transport
Author | Micah Zoltu, Erik Marks |
---|---|
Discussions-To | https://github.com/ethereum/EIPs/issues/2697 |
Status | Final |
Type | Standards Track |
Category | Interface |
Created | 2020-06-04 |
Table of Contents
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
Copyright and related rights waived via CC0.
Citation
Please cite this document as:
Micah Zoltu, Erik Marks, "EIP-2696: JavaScript `request` method RPC transport," Ethereum Improvement Proposals, no. 2696, June 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2696.