EIP 1193

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
2
3
4
5
6
interface RequestArguments {
readonly method: string
readonly params: readonly unknown[] | object
}

Provider.request(args: RequestArguments): Promise<unknown>

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
2
3
4
interface ProviderMessage {
readonly type: string
readonly data: unknown
}

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
2
3
4
5
6
7
interface EthSubscription extends ProviderMessage {
readonly type: 'eth_subscription'
readonly data: {
readonly subscription: string
readonly result: unknown
}
}

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
2
3
interface ProviderConnectInfo {
readonly chainId: string
}

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

Discussion: EIP-1193

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.

#2673

  • Remove index signature from interfaces
    • i.e. no more [key: string]: unknown, the ability to add properties is implied
  • 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

#2590

  • 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

IMO this is the most meaningful point to take this update: Multiple protocols are served by a single Provider at once.

#2577

  • Deprecates send and sendAsync
  • Specifies a new method request, with the same Promise signature as the send 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.
  • 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.