Summary
A JavaScript Ethereum Provider API for consistency across clients and applications.
This EIP formalizes an Ethereum Provider API to promote wallet interoperability. The API is designed to be minimal, event-driven, and agonstic of transport and RPC protocols
It’s functionality is easily extended by defining new RPC methods and message event types
Terminology
- Provider: a JavaScript object made available to a consumer, that provides access to Ethereum by menas of Clients
- e.g. window.ethereum
- Client: An endpoint that receives Remote Procedure Call (RPC)
- e.g. server of MetaMask
- Wallet: An end-user application that manages private keys, performs signing operations, and acts as a middleware between the Provider and the Client
- e.g. MetaMask
- Application send message via provider to wallet and wallet proxy the message to the client
- Remote Procedure Call (RPC)
API
request
The
request
method is intended as a transport- and protocol-agnostic wrapper function for Remote Procedure Calls
1 | interface RequestArguments { |
The provider must identify requested RPC method by the value of RequestArguments.method
If the requested RPC method takes any parameters, the Provider must accept as the value of RequestArguments.params
RPC requests must be handled such that the returned Promise either resolves with a value per the requested RPC method’s specification, or rejects with an error.
Events
The provider must implement the following event handling methods:
- on
- removeListener
These methods must be implemented per the Node.js EventEmitter
API
To satisfy these requirements, Provider implementers should consider simply extending the Node.js
EventEmitter
class and bundling it for the target environment.
Message Event
The
message
event is intended for arbitrary notifications not covered by other events.
When emitted, the message
event must be emitted with an object argument of the following form:
1 | interface ProviderMessage { |
Subscriptions Event
If the provider supports Ethereum RPC subscriptions, the provider must emit the message
event when it receives a subscription notification.
If the provider receives a subscription message, the provider must emit a message
event with a ProviderMessage
object of the following form:
1 | interface EthSubscription extends ProviderMessage { |
Connect Event
If the provider becomes connected, the provider must emit the event named connected
.
This includes when:
- The provider first connects to a chain after initialization.
- The provider connects to a chain after the
disconnect
event was emitted.
This event must be emitted with an object of the following form:
1 | interface ProviderConnectInfo { |
Disconnect Event
If the provider becomes disconnected from all chains, the provider must emit the event named disconnect
with value error: ProviderRpcError
, per the interface defined in teh RPC Errors.
ChainChanged Event
If the chain the provider is connected to changes, the provider must emit the event named chainChanged
with the value chainId: string
.
AccountsChanged
If the accounts available to the provider change, the provider must emit the event named accountsChanged
wth value accounts: string[]
, containing the account addresses per the eth_accounts
Ethereum RPC method.
Rational
The purpose of a Provider is to provide a consumer with access to Ethereum. In general, a Provider must enable an Ethereum web application to do two things:
- Make Ethereum RPC requests
- Respond to state changes in the Provider’s Ethereum chain, Client, and Wallet.
Backwards Compatibility
Many providers adopted a draft version of this specification before it was finalized.
Providers that only implement this specification will not be compatible with Ethereum web applications that target the legacy API.
The Provider is intended to pass messages between an Ethereum Client and an Ethereum application. It is not responsible for private key or account management; It merely processes RPC messages and emits events.
Consequently, account security and user privacy need to be implemented in middlewares between the Provider and its client. In practice, we call these middleware applications “Wallet”, and they usually manage the user’s private keys and accounts.
The Provider can be thought of as an extension of the Wallet, exposed in an untrusted environment, under the control of some third party(e.g. website)
Rules
- The Provider does not contain any private user data
- The Provider and Wallet programs are isolated from each other
- The Wallet and/or Client rate-limit requests from the Provider
- The Wallet and/or Client validate all data sent from the Provider
Discussion
Key Updates
#2702 - Normative change, don’t require Provider to implement the emit
method since it’s an implementation detail.
#2695 - Remove all deprecated methods and events from teh API documentation, since they were only specified in the API documentation.
- Remove index signature from interfaces
- i.e. no more
[key: string]: unknown
, the ability to add properties is implied
- i.e. no more
RequestArguments
params?: unknown
->params?: unknown[] | object
- Explicitly define relationship between
RequstArguments
fields and RPC method names and parameters
: request
takes a single, options bag argument, to make it as extensible as possible. We are extremely unlikely to have to revisit it ever again.- If devs find the options bag unergonomic, they can define their wrapper functions
- New signature for the
request
method,Provider.request(args: RequestArguments): Promise<unknown>
- This is motivated by discussions with @frozeman and others, and enables a future for the Provider interface generally and the
request
method specifically where any of the following holds: - Multiple chains are served by a single Provider at once.
- Multiple protocols are served by a single Provider at once
- The Provider needs some kind of metadata submitted along with
request
calls, for reasons we are unable to anticipate today
- This is motivated by discussions with @frozeman and others, and enables a future for the Provider interface generally and the
IMO this is the most meaningful point to take this update: Multiple protocols are served by a single Provider at once.
- Deprecates
send
andsendAsync
- Specifies a new method
request
, with the same Promise signature as thesend
currently, per @MicahZoltu’s suggestion- On the topic of alternate names, perhaps,
ethereum.request(...)
?. Since JSON-RPC is a request-response pairing I think this name makes sense.
- On the topic of alternate names, perhaps,
- Changes the interface of the
notification
event, such that a generalized object is emitted. - Makes the spec transpot- and RPC protocol-agnostic, per the contributions of @ryanio
- Add the
message
event for generalized messaging.