DCIPs/EIPS/eip-2696.md

101 lines
6.1 KiB
Markdown

---
eip: 2696
title: JavaScript `request` method RPC transport
author: Micah Zoltu (@MicahZoltu), Erik Marks (@rekmarks)
discussions-to: https://github.com/ethereum/EIPs/issues/2697
status: Final
type: Standards Track
category: Interface
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](https://www.ietf.org/rfc/rfc2119.txt).
### Interface
TypeScript interface definition:
```ts
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:
```typescript
'{ "jsonrpc": "2.0", "id": 1, "method": "do_work", "params": [ 5, "hello" ] }'
```
Then the matching `EthereumProvider.request` call would be:
```typescript
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:
```typescript
'{ "jsonrpc": "2.0", "id": 1, "result": { "color": "red", "value": 5 } }'
```
Then the matching `EthereumProvider.request` response would be:
```typescript
{ color: 'red', value: 5 }
```
### Errors
```ts
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](../LICENSE.md).