forked from DecentralizedClimateFoundation/DCIPs
577 lines
23 KiB
Markdown
577 lines
23 KiB
Markdown
|
---
|
||
|
eip: 1193
|
||
|
title: Ethereum Provider JavaScript API
|
||
|
author: Fabian Vogelsteller (@frozeman), Ryan Ghods (@ryanio), Victor Maia (@MaiaVictor), Marc Garreau (@marcgarreau), Erik Marks (@rekmarks)
|
||
|
discussions-to: https://github.com/ethereum/EIPs/issues/2319
|
||
|
status: Final
|
||
|
type: Standards Track
|
||
|
category: Interface
|
||
|
created: 2018-06-30
|
||
|
requires: 155, 695
|
||
|
---
|
||
|
|
||
|
## Summary
|
||
|
|
||
|
A JavaScript Ethereum Provider API for consistency across clients and applications.
|
||
|
|
||
|
## Abstract
|
||
|
|
||
|
A common convention in the Ethereum web application ("dapp") ecosystem is for key management software ("wallets") to expose their API via a JavaScript object in the web page.
|
||
|
This object is called "the Provider".
|
||
|
|
||
|
Historically, Provider implementations have exhibited conflicting interfaces and behaviors between wallets.
|
||
|
This EIP formalizes an Ethereum Provider API to promote wallet interoperability.
|
||
|
The API is designed to be minimal, event-driven, and agnostic of transport and RPC protocols.
|
||
|
Its functionality is easily extended by defining new RPC methods and `message` event types.
|
||
|
|
||
|
Historically, Providers have been made available as `window.ethereum` in web browsers, but this convention is not part of the specification.
|
||
|
|
||
|
## Specification
|
||
|
|
||
|
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).
|
||
|
|
||
|
> Comments like this are non-normative.
|
||
|
|
||
|
### Definitions
|
||
|
|
||
|
_This section is non-normative._
|
||
|
|
||
|
- Provider
|
||
|
- A JavaScript object made available to a consumer, that provides access to Ethereum by means of a Client.
|
||
|
- Client
|
||
|
- An endpoint that receives Remote Procedure Call (RPC) requests from the Provider, and returns their results.
|
||
|
- Wallet
|
||
|
- An end-user application that manages private keys, performs signing operations, and acts as a middleware between the Provider and the Client.
|
||
|
- Remote Procedure Call (RPC)
|
||
|
- A Remote Procedure Call (RPC), is any request submitted to a Provider for some procedure that is to be processed by a Provider, its Wallet, or its Client.
|
||
|
|
||
|
### Connectivity
|
||
|
|
||
|
The Provider is said to be "connected" when it can service RPC requests to at least one chain.
|
||
|
|
||
|
The Provider is said to be "disconnected" when it cannot service RPC requests to any chain at all.
|
||
|
|
||
|
> To service an RPC request, the Provider must successfully submit the request to the remote location, and receive a response.
|
||
|
> In other words, if the Provider is unable to communicate with its Client, for example due to network issues, the Provider is disconnected.
|
||
|
|
||
|
### API
|
||
|
|
||
|
> The Provider API is specified using TypeScript.
|
||
|
> The authors encourage implementers to declare their own types and interfaces, using the ones in this section as a basis.
|
||
|
>
|
||
|
> For consumer-facing API documentation, see [Appendix I](#appendix-i-consumer-facing-api-documentation)
|
||
|
|
||
|
The Provider **MUST** implement and expose the API defined in this section.
|
||
|
All API entities **MUST** adhere to the types and interfaces defined in this section.
|
||
|
|
||
|
#### request
|
||
|
|
||
|
> The `request` method is intended as a transport- and protocol-agnostic wrapper function for Remote Procedure Calls (RPCs).
|
||
|
|
||
|
```typescript
|
||
|
interface RequestArguments {
|
||
|
readonly method: string;
|
||
|
readonly params?: readonly unknown[] | object;
|
||
|
}
|
||
|
|
||
|
Provider.request(args: RequestArguments): Promise<unknown>;
|
||
|
```
|
||
|
|
||
|
The Provider **MUST** identify the requested RPC method by the value of `RequestArguments.method`.
|
||
|
|
||
|
If the requested RPC method takes any parameters, the Provider **MUST** accept them 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.
|
||
|
|
||
|
If resolved, the Promise **MUST** resolve with a result per the RPC method's specification. The Promise **MUST NOT** resolve with any RPC protocol-specific response objects, unless the RPC method's return type is so defined.
|
||
|
|
||
|
If the returned Promise rejects, it **MUST** reject with a `ProviderRpcError` as specified in the [RPC Errors](#rpc-errors) section below.
|
||
|
|
||
|
The returned Promise **MUST** reject if any of the following conditions are met:
|
||
|
|
||
|
- An error is returned for the RPC request.
|
||
|
- If the returned error is compatible with the `ProviderRpcError` interface, the Promise **MAY** reject with that error directly.
|
||
|
- The Provider encounters an error or fails to process the request for any reason.
|
||
|
|
||
|
> If the Provider implements any kind of authorization logic, the authors recommend rejecting with a `4100` error in case of authorization failures.
|
||
|
|
||
|
The returned Promise **SHOULD** reject if any of the following conditions are met:
|
||
|
|
||
|
- The Provider is disconnected.
|
||
|
- If rejecting for this reason, the Promise rejection error `code` **MUST** be `4900`.
|
||
|
- The RPC request is directed at a specific chain, and the Provider is not connected to that chain, but is connected to at least one other chain.
|
||
|
- If rejecting for this reason, the Promise rejection error `code` **MUST** be `4901`.
|
||
|
|
||
|
See the section [Connectivity](#connectivity) for the definitions of "connected" and "disconnected".
|
||
|
|
||
|
### Supported RPC Methods
|
||
|
|
||
|
A "supported RPC method" is any RPC method that may be called via the Provider.
|
||
|
|
||
|
All supported RPC methods **MUST** be identified by unique strings.
|
||
|
|
||
|
Providers **MAY** support whatever RPC methods required to fulfill their purpose, standardized or otherwise.
|
||
|
|
||
|
If an RPC method defined in a finalized EIP is not supported, it **SHOULD** be rejected with a `4200` error per the [Provider Errors](#provider-errors) section below, or an appropriate error per the RPC method's specification.
|
||
|
|
||
|
#### RPC Errors
|
||
|
|
||
|
```typescript
|
||
|
interface ProviderRpcError extends Error {
|
||
|
code: number;
|
||
|
data?: unknown;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- `message`
|
||
|
- **MUST** be a human-readable string
|
||
|
- **SHOULD** adhere to the specifications in the [Error Standards](#error-standards) section below
|
||
|
- `code`
|
||
|
- **MUST** be an integer number
|
||
|
- **SHOULD** adhere to the specifications in the [Error Standards](#error-standards) section below
|
||
|
- `data`
|
||
|
- **SHOULD** contain any other useful information about the error
|
||
|
|
||
|
##### Error Standards
|
||
|
|
||
|
`ProviderRpcError` codes and messages **SHOULD** follow these conventions, in order of priority:
|
||
|
|
||
|
1. The errors in the [Provider Errors](#provider-errors) section below
|
||
|
|
||
|
2. Any errors mandated by the erroring RPC method's specification
|
||
|
|
||
|
3. The [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes)
|
||
|
|
||
|
#### Provider Errors
|
||
|
|
||
|
| Status code | Name | Description |
|
||
|
| ----------- | --------------------- | ------------------------------------------------------------------------ |
|
||
|
| 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. |
|
||
|
|
||
|
> `4900` is intended to indicate that the Provider is disconnected from all chains, while `4901` is intended to indicate that the Provider is disconnected from a specific chain only.
|
||
|
> In other words, `4901` implies that the Provider is connected to other chains, just not the requested one.
|
||
|
|
||
|
### Events
|
||
|
|
||
|
The Provider **MUST** implement the following event handling methods:
|
||
|
|
||
|
- `on`
|
||
|
- `removeListener`
|
||
|
|
||
|
These methods **MUST** be implemented per the Node.js [`EventEmitter` API](https://nodejs.org/api/events.html).
|
||
|
|
||
|
> To satisfy these requirements, Provider implementers should consider simply extending the Node.js `EventEmitter` class and bundling it for the target environment.
|
||
|
|
||
|
#### message
|
||
|
|
||
|
> 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:
|
||
|
|
||
|
```typescript
|
||
|
interface ProviderMessage {
|
||
|
readonly type: string;
|
||
|
readonly data: unknown;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
##### Subscriptions
|
||
|
|
||
|
If the Provider supports Ethereum RPC subscriptions, e.g. [`eth_subscribe`](https://geth.ethereum.org/docs/rpc/pubsub), the Provider **MUST** emit the `message` event when it receives a subscription notification.
|
||
|
|
||
|
If the Provider receives a subscription message from e.g. an `eth_subscribe` subscription, the Provider **MUST** emit a `message` event with a `ProviderMessage` object of the following form:
|
||
|
|
||
|
```typescript
|
||
|
interface EthSubscription extends ProviderMessage {
|
||
|
readonly type: 'eth_subscription';
|
||
|
readonly data: {
|
||
|
readonly subscription: string;
|
||
|
readonly result: unknown;
|
||
|
};
|
||
|
}
|
||
|
```
|
||
|
|
||
|
#### connect
|
||
|
|
||
|
See the section [Connectivity](#connectivity) for the definition of "connected".
|
||
|
|
||
|
If the Provider becomes connected, the Provider **MUST** emit the event named `connect`.
|
||
|
|
||
|
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:
|
||
|
|
||
|
```typescript
|
||
|
interface ProviderConnectInfo {
|
||
|
readonly chainId: string;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
`chainId` **MUST** specify the integer ID of the connected chain as a hexadecimal string, per the [`eth_chainId`](./eip-695.md) Ethereum RPC method.
|
||
|
|
||
|
#### disconnect
|
||
|
|
||
|
See the section [Connectivity](#connectivity) for the definition of "disconnected".
|
||
|
|
||
|
If the Provider becomes disconnected from all chains, the Provider **MUST** emit the event named `disconnect` with value `error: ProviderRpcError`, per the interfaced defined in the [RPC Errors](#rpc-errors) section. The value of the error's `code` property **MUST** follow the [status codes for `CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes).
|
||
|
|
||
|
#### chainChanged
|
||
|
|
||
|
If the chain the Provider is connected to changes, the Provider **MUST** emit the event named `chainChanged` with value `chainId: string`, specifying the integer ID of the new chain as a hexadecimal string, per the [`eth_chainId`](./eip-695.md) Ethereum RPC method.
|
||
|
|
||
|
#### accountsChanged
|
||
|
|
||
|
If the accounts available to the Provider change, the Provider **MUST** emit the event named `accountsChanged` with value `accounts: string[]`, containing the account addresses per the `eth_accounts` Ethereum RPC method.
|
||
|
|
||
|
The "accounts available to the Provider" change when the return value of `eth_accounts` changes.
|
||
|
|
||
|
## Rationale
|
||
|
|
||
|
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
|
||
|
|
||
|
The Provider API specification consists of a single method and five events.
|
||
|
The `request` method and the `message` event alone, are sufficient to implement a complete Provider.
|
||
|
They are designed to make arbitrary RPC requests and communicate arbitrary messages, respectively.
|
||
|
|
||
|
The remaining four events can be separated into two categories:
|
||
|
|
||
|
- Changes to the Provider's ability to make RPC requests
|
||
|
- `connect`
|
||
|
- `disconnect`
|
||
|
- Common Client and/or Wallet state changes that any non-trivial application must handle
|
||
|
- `chainChanged`
|
||
|
- `accountsChanged`
|
||
|
|
||
|
These events are included due to the widespread production usage of related patterns, at the time of writing.
|
||
|
|
||
|
## Backwards Compatibility
|
||
|
|
||
|
Many Providers adopted a draft version of this specification before it was finalized.
|
||
|
The current API is designed to be a strict superset of the legacy version, and this specification is in that sense fully backwards compatible.
|
||
|
See [Appendix III](#appendix-iii-legacy-provider-api) for the legacy API.
|
||
|
|
||
|
Providers that only implement this specification will not be compatible with Ethereum web applications that target the legacy API.
|
||
|
|
||
|
## Implementations
|
||
|
|
||
|
At the time of writing, the following projects have working implementations:
|
||
|
|
||
|
- [buidler.dev](https://github.com/nomiclabs/buidler/pull/608)
|
||
|
- [ethers.js](https://github.com/ethers-io/ethers.js/blob/56af4413b1dd1787db68985e0b612b63d86fdf7c/packages/providers/src.ts/web3-provider.ts)
|
||
|
- [eth-provider](https://www.npmjs.com/package/eth-provider)
|
||
|
- [MetaMask](https://github.com/MetaMask/inpage-provider)
|
||
|
- [WalletConnect](https://github.com/WalletConnect/walletconnect-monorepo/blob/d33fd2070d7a67f74de50fd10ca4217f4e2f22f3/packages/providers/web3-provider/README.md)
|
||
|
- [web3.js](https://web3js.readthedocs.io/)
|
||
|
|
||
|
## Security Considerations
|
||
|
|
||
|
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 Ethereum Client.
|
||
|
In practice, we call these middleware applications "Wallets," 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. a website).
|
||
|
|
||
|
### Handling Adversarial Behavior
|
||
|
|
||
|
Since it is a JavaScript object, consumers can generally perform arbitrary operations on the Provider, and all its properties can be read or overwritten.
|
||
|
Therefore, it is best to treat the Provider object as though it is controlled by an adversary.
|
||
|
It is paramount that the Provider implementer protects the user, Wallet, and Client by ensuring that:
|
||
|
|
||
|
- 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.
|
||
|
|
||
|
### Chain Changes
|
||
|
|
||
|
Since all Ethereum operations are directed at a particular chain, it's important that the Provider accurately reflects the Client's configured chain, per the `eth_chainId` Ethereum RPC method (see [EIP-695](./eip-695.md)).
|
||
|
|
||
|
This includes ensuring that `eth_chainId` has the correct return value, and that the `chainChanged` event is emitted whenever that value changes.
|
||
|
|
||
|
### User Account Exposure and Account Changes
|
||
|
|
||
|
Many Ethereum write operations (e.g. `eth_sendTransaction`) require a user account to be specified.
|
||
|
Provider consumers access these accounts via the `eth_accounts` RPC method, and by listening for the `accountsChanged` event.
|
||
|
|
||
|
As with `eth_chainId`, it is critical that `eth_accounts` has the correct return value, and that the `accountsChanged` event is emitted whenever that value changes.
|
||
|
|
||
|
The return value of `eth_accounts` is ultimately controlled by the Wallet or Client.
|
||
|
In order to protect user privacy, the authors recommend not exposing any accounts by default.
|
||
|
Instead, Providers should support RPC methods for explicitly requesting account access, such as `eth_requestAccounts` (see [EIP-1102](./eip-1102.md)) or `wallet_requestPermissions` (see [EIP-2255](./eip-2255.md)).
|
||
|
|
||
|
## References
|
||
|
|
||
|
- [Initial discussion in `ethereum/interfaces`](https://github.com/ethereum/interfaces/issues/16)
|
||
|
- [Deprecated Ethereum Magicians thread](https://ethereum-magicians.org/t/eip-1193-ethereum-provider-javascript-api/640)
|
||
|
- [Continuing discussion](https://github.com/ethereum/EIPs/issues/2319)
|
||
|
- Related EIPs
|
||
|
- [EIP-1102: Opt-in Account Exposure](./eip-1102.md)
|
||
|
- [EIP-1474: Remote Procedure Call Specification](./eip-1474.md)
|
||
|
- [EIP-1767: GraphQL Interface to Ethereum Node Data](./eip-1767.md)
|
||
|
- [EIP-2255: Wallet Permissions](./eip-2255.md)
|
||
|
|
||
|
## Copyright
|
||
|
|
||
|
Copyright and related rights waived via [CC0](../LICENSE.md).
|
||
|
|
||
|
## Appendix I: Consumer-Facing API Documentation
|
||
|
|
||
|
### request
|
||
|
|
||
|
Makes an Ethereum RPC method call.
|
||
|
|
||
|
```typescript
|
||
|
interface RequestArguments {
|
||
|
readonly method: string;
|
||
|
readonly params?: readonly unknown[] | object;
|
||
|
}
|
||
|
|
||
|
Provider.request(args: RequestArguments): Promise<unknown>;
|
||
|
```
|
||
|
|
||
|
The returned Promise resolves with the method's result or rejects with a [`ProviderRpcError`](#errors). For example:
|
||
|
|
||
|
```javascript
|
||
|
Provider.request({ method: 'eth_accounts' })
|
||
|
.then((accounts) => console.log(accounts))
|
||
|
.catch((error) => console.error(error));
|
||
|
```
|
||
|
|
||
|
Consult each Ethereum RPC method's documentation for its `params` and return type.
|
||
|
You can find a list of common methods [here](./eip-1474.md).
|
||
|
|
||
|
#### RPC Protocols
|
||
|
|
||
|
Multiple RPC protocols may be available. For examples, see:
|
||
|
|
||
|
- [EIP-1474](./eip-1474.md), the Ethereum JSON-RPC API
|
||
|
- [EIP-1767](./eip-1767.md), the Ethereum GraphQL schema
|
||
|
|
||
|
### Events
|
||
|
|
||
|
Events follow the conventions of the Node.js [`EventEmitter` API](https://nodejs.org/api/events.html).
|
||
|
|
||
|
#### connect
|
||
|
|
||
|
The Provider emits `connect` when it:
|
||
|
|
||
|
- first connects to a chain after being initialized.
|
||
|
- first connects to a chain, after the `disconnect` event was emitted.
|
||
|
|
||
|
```typescript
|
||
|
interface ProviderConnectInfo {
|
||
|
readonly chainId: string;
|
||
|
}
|
||
|
|
||
|
Provider.on('connect', listener: (connectInfo: ProviderConnectInfo) => void): Provider;
|
||
|
```
|
||
|
|
||
|
The event emits an object with a hexadecimal string `chainId` per the `eth_chainId` Ethereum RPC method, and other properties as determined by the Provider.
|
||
|
|
||
|
#### disconnect
|
||
|
|
||
|
The Provider emits `disconnect` when it becomes disconnected from all chains.
|
||
|
|
||
|
```typescript
|
||
|
Provider.on('disconnect', listener: (error: ProviderRpcError) => void): Provider;
|
||
|
```
|
||
|
|
||
|
This event emits a [`ProviderRpcError`](#errors). The error `code` follows the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes).
|
||
|
|
||
|
#### chainChanged
|
||
|
|
||
|
The Provider emits `chainChanged` when connecting to a new chain.
|
||
|
|
||
|
```typescript
|
||
|
Provider.on('chainChanged', listener: (chainId: string) => void): Provider;
|
||
|
```
|
||
|
|
||
|
The event emits a hexadecimal string `chainId` per the `eth_chainId` Ethereum RPC method.
|
||
|
|
||
|
#### accountsChanged
|
||
|
|
||
|
The Provider emits `accountsChanged` if the accounts returned from the Provider (`eth_accounts`) change.
|
||
|
|
||
|
```typescript
|
||
|
Provider.on('accountsChanged', listener: (accounts: string[]) => void): Provider;
|
||
|
```
|
||
|
|
||
|
The event emits with `accounts`, an array of account addresses, per the `eth_accounts` Ethereum RPC method.
|
||
|
|
||
|
#### message
|
||
|
|
||
|
The Provider emits `message` to communicate arbitrary messages to the consumer.
|
||
|
Messages may include JSON-RPC notifications, GraphQL subscriptions, and/or any other event as defined by the Provider.
|
||
|
|
||
|
```typescript
|
||
|
interface ProviderMessage {
|
||
|
readonly type: string;
|
||
|
readonly data: unknown;
|
||
|
}
|
||
|
|
||
|
Provider.on('message', listener: (message: ProviderMessage) => void): Provider;
|
||
|
```
|
||
|
|
||
|
##### Subscriptions
|
||
|
|
||
|
[`eth_` subscription methods](https://geth.ethereum.org/docs/rpc/pubsub) and [`shh_` subscription methods](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_subscribe) rely on this event to emit subscription updates.
|
||
|
|
||
|
For e.g. `eth_subscribe` subscription updates, `ProviderMessage.type` will equal the string `'eth_subscription'`, and the subscription data will be the value of `ProviderMessage.data`.
|
||
|
|
||
|
### Errors
|
||
|
|
||
|
```typescript
|
||
|
interface ProviderRpcError extends Error {
|
||
|
message: string;
|
||
|
code: number;
|
||
|
data?: unknown;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Appendix II: Examples
|
||
|
|
||
|
These examples assume a web browser environment.
|
||
|
|
||
|
```javascript
|
||
|
// Most Providers are available as window.ethereum on page load.
|
||
|
// This is only a convention, not a standard, and may not be the case in practice.
|
||
|
// Please consult the Provider implementation's documentation.
|
||
|
const ethereum = window.ethereum;
|
||
|
|
||
|
// Example 1: Log chainId
|
||
|
ethereum
|
||
|
.request({ method: 'eth_chainId' })
|
||
|
.then((chainId) => {
|
||
|
console.log(`hexadecimal string: ${chainId}`);
|
||
|
console.log(`decimal number: ${parseInt(chainId, 16)}`);
|
||
|
})
|
||
|
.catch((error) => {
|
||
|
console.error(`Error fetching chainId: ${error.code}: ${error.message}`);
|
||
|
});
|
||
|
|
||
|
// Example 2: Log last block
|
||
|
ethereum
|
||
|
.request({
|
||
|
method: 'eth_getBlockByNumber',
|
||
|
params: ['latest', true],
|
||
|
})
|
||
|
.then((block) => {
|
||
|
console.log(`Block ${block.number}:`, block);
|
||
|
})
|
||
|
.catch((error) => {
|
||
|
console.error(
|
||
|
`Error fetching last block: ${error.message}.
|
||
|
Code: ${error.code}. Data: ${error.data}`
|
||
|
);
|
||
|
});
|
||
|
|
||
|
// Example 3: Log available accounts
|
||
|
ethereum
|
||
|
.request({ method: 'eth_accounts' })
|
||
|
.then((accounts) => {
|
||
|
console.log(`Accounts:\n${accounts.join('\n')}`);
|
||
|
})
|
||
|
.catch((error) => {
|
||
|
console.error(
|
||
|
`Error fetching accounts: ${error.message}.
|
||
|
Code: ${error.code}. Data: ${error.data}`
|
||
|
);
|
||
|
});
|
||
|
|
||
|
// Example 4: Log new blocks
|
||
|
ethereum
|
||
|
.request({
|
||
|
method: 'eth_subscribe',
|
||
|
params: ['newHeads'],
|
||
|
})
|
||
|
.then((subscriptionId) => {
|
||
|
ethereum.on('message', (message) => {
|
||
|
if (message.type === 'eth_subscription') {
|
||
|
const { data } = message;
|
||
|
if (data.subscription === subscriptionId) {
|
||
|
if ('result' in data && typeof data.result === 'object') {
|
||
|
const block = data.result;
|
||
|
console.log(`New block ${block.number}:`, block);
|
||
|
} else {
|
||
|
console.error(`Something went wrong: ${data.result}`);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
})
|
||
|
.catch((error) => {
|
||
|
console.error(
|
||
|
`Error making newHeads subscription: ${error.message}.
|
||
|
Code: ${error.code}. Data: ${error.data}`
|
||
|
);
|
||
|
});
|
||
|
|
||
|
// Example 5: Log when accounts change
|
||
|
const logAccounts = (accounts) => {
|
||
|
console.log(`Accounts:\n${accounts.join('\n')}`);
|
||
|
};
|
||
|
ethereum.on('accountsChanged', logAccounts);
|
||
|
// to unsubscribe
|
||
|
ethereum.removeListener('accountsChanged', logAccounts);
|
||
|
|
||
|
// Example 6: Log if connection ends
|
||
|
ethereum.on('disconnect', (code, reason) => {
|
||
|
console.log(`Ethereum Provider connection closed: ${reason}. Code: ${code}`);
|
||
|
});
|
||
|
```
|
||
|
|
||
|
## Appendix III: Legacy Provider API
|
||
|
|
||
|
This section documents the legacy Provider API, which is extensively used in production at the time of writing.
|
||
|
As it was never fully standardized, significant deviations occur in practice.
|
||
|
The authors recommend against implementing it except to support legacy Ethereum applications.
|
||
|
|
||
|
### sendAsync (DEPRECATED)
|
||
|
|
||
|
This method is superseded by [`request`](#request).
|
||
|
|
||
|
`sendAsync` is like `request`, but with JSON-RPC objects and a callback.
|
||
|
|
||
|
```typescript
|
||
|
Provider.sendAsync(request: Object, callback: Function): void;
|
||
|
```
|
||
|
|
||
|
Historically, the request and response object interfaces have followed the [Ethereum JSON-RPC specification](./eip-1474.md).
|
||
|
|
||
|
### send (DEPRECATED)
|
||
|
|
||
|
This method is superseded by [`request`](#request).
|
||
|
|
||
|
```typescript
|
||
|
Provider.send(...args: unknown[]): unknown;
|
||
|
```
|
||
|
|
||
|
### Legacy Events
|
||
|
|
||
|
#### close (DEPRECATED)
|
||
|
|
||
|
This event is superseded by [`disconnect`](#disconnect).
|
||
|
|
||
|
#### networkChanged (DEPRECATED)
|
||
|
|
||
|
The event `networkChanged` is superseded by [`chainChanged`](#chainchanged).
|
||
|
|
||
|
For details, see [EIP-155: Simple replay attack protection](./eip-155.md) and [EIP-695: Create eth_chainId method for JSON-RPC](./eip-695.md).
|
||
|
|
||
|
#### notification (DEPRECATED)
|
||
|
|
||
|
This event is superseded by [`message`](#message).
|
||
|
|
||
|
Historically, this event has been emitted with e.g. `eth_subscribe` subscription updates of the form `{ subscription: string, result: unknown }`.
|