11 KiB
eip | title | author | discussions-to | status | type | category | created | requires |
---|---|---|---|---|---|---|---|---|
3085 | Wallet Add Ethereum Chain RPC Method (`wallet_addEthereumChain`) | Erik Marks (@rekmarks), Pedro Gomes (@pedrouid) | https://ethereum-magicians.org/t/eip-3085-wallet-addethereumchain/5469 | Stagnant | Standards Track | Interface | 2020-11-01 | 155, 695 |
Simple Summary
An RPC method for adding Ethereum chains to wallet applications.
Abstract
The wallet_addEthereumChain
RPC method allows Ethereum applications ("dapps") to suggest chains to be added to the user's wallet application.
The caller must specify a chain ID and some chain metadata.
The wallet application may arbitrarily refuse or accept the request.
null
is returned if the chain was added, and an error otherwise.
Motivation
All dapps require the user to interact with one or more Ethereum chains in order to function.
Any given chain may or may not be supported by the user's wallet application.
wallet_addEthereumChain
enables dapps to request chains to be added to the user's wallet.
This enables UX improvements for both dapps and wallets.
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.
wallet_addEthereumChain
The method accepts a single object parameter, with a chainId
and some chain metadata.
The method returns null
if the chain was added to the wallet, and an error otherwise.
The wallet MAY reject the request for any reason.
Note that this method makes no statement about whether the wallet should change the user's currently selected chain, if the wallet has a concept thereof.
Parameters
wallet_addEthereumChain
accepts a single object parameter, specified by the following TypeScript interface:
interface AddEthereumChainParameter {
chainId: string;
blockExplorerUrls?: string[];
chainName?: string;
iconUrls?: string[];
nativeCurrency?: {
name: string;
symbol: string;
decimals: number;
};
rpcUrls?: string[];
}
Only the chainId
is required per this specification, but a wallet MAY require any other fields listed, impose additional requirements on them, or ignore them outright.
If a field does not meet the requirements of this specification and the wallet does not ignore the field, the wallet MUST reject the request.
chainId
- MUST specify the integer ID of the chain as a hexadecimal string, per the
eth_chainId
Ethereum RPC method. - The wallet SHOULD compare the specified
chainId
value with theeth_chainId
return value from the endpoint. If these values are not identical, the wallet MUST reject the request.
- MUST specify the integer ID of the chain as a hexadecimal string, per the
blockExplorerUrls
- If provided, MUST specify one or more URLs pointing to block explorer web sites for the chain.
chainName
- If provided, MUST specify a human-readable name for the chain.
iconUrls
- If provided, MUST specify one or more URLs pointing to reasonably sized images that can be used to visually identify the chain.
nativeCurrency
- If provided, MUST describe the native currency of the chain using the
name
,symbol
, anddecimals
fields.decimals
MUST be a non-negative integer.name
andsymbol
SHOULD be human-readable strings.
- If provided, MUST describe the native currency of the chain using the
rpcUrls
- If provided, MUST specify one or more URLs pointing to RPC endpoints that can be used to communicate with the chain.
All URL strings MUST include the protocol component of the URL. HTTPS SHOULD always be used over HTTP.
Returns
The method MUST return null
if the request was successful, and an error otherwise.
A request to add a chain that was already added SHOULD be considered successful.
The wallet MUST NOT allow the same chainId
to be added multiple times.
See Security Considerations for more information.
Examples
These examples use JSON-RPC, but the method could be implemented using other RPC protocols.
To add the Goerli test chain:
{
"id": 1,
"jsonrpc": "2.0",
"method": "wallet_addEthereumChain",
"params": [
{
"chainId": "0x5",
"chainName": "Goerli",
"rpcUrls": ["https://goerli.infura.io/v3/INSERT_API_KEY_HERE"],
"nativeCurrency": {
"name": "Goerli ETH",
"symbol": "gorETH",
"decimals": 18
},
"blockExplorerUrls": ["https://goerli.etherscan.io"]
}
]
}
To add POA Network's xDAI chain:
{
"id": 1,
"jsonrpc": "2.0",
"method": "wallet_addEthereumChain",
"params": [
{
"chainId": "0x64",
"chainName": "xDAI Chain",
"rpcUrls": ["https://dai.poa.network"],
"iconUrls": [
"https://xdaichain.com/fake/example/url/xdai.svg",
"https://xdaichain.com/fake/example/url/xdai.png"
],
"nativeCurrency": {
"name": "xDAI",
"symbol": "xDAI",
"decimals": 18
}
}
]
}
In the above example, notice that the iconUrls
array contains URLs pointing to two different image formats.
A success response:
{
"id": 1,
"jsonrpc": "2.0",
"result": null
}
A failure response:
{
"id": 1,
"jsonrpc": "2.0",
"error": {
"code": 4001,
"message": "The user rejected the request."
}
}
Rationale
The design of wallet_addEthereumChain
is deliberately ignorant of what it means to "add" a chain to a wallet.
The meaning of "adding" a chain to a wallet depends on the wallet implementation.
When calling the method, specifying the chainId
will always be necessary, since in the universe of Ethereum chains, the EIP-155 chain ID is effectively the chain GUID.
The remaining parameters amount to what, in the estimation of the authors, a wallet will minimally require in order to effectively support a chain and represent it to the user.
The network ID (per the net_version
RPC method) is omitted since it is effectively superseded by the chain ID.
For security reasons, a wallet should always attempt to validate the chain metadata provided by the requester, and may choose to fetch the metadata elsewhere entirely.
Either way, only the wallet can know which chain metadata it needs from the requester in order to "add" the chain.
Therefore, all parameters except chainId
are specified as optional, even though a wallet may require them in practice.
This specification does not mandate that the wallet "switches" its "active" or "currently selected" chain after a successful request, if the wallet has a concept thereof. Just like the meaning of "adding" a chain, "switching" between chains is a wallet implementation detail, and therefore out of scope.
For related work, see EIP-2015.
Security Considerations
wallet_addEthereumChain
is a powerful method that exposes the end user to serious risks if implemented incorrectly.
Many of these risks can be avoided by validating the request data in the wallet, and clearly disambiguating different chains in the wallet UI.
Chain IDs
Since the chain ID used for transaction signing determines which chain the transaction is valid for, handling the chain ID correctly is of utmost importance. The wallet should:
- Ensure that a submitted chain ID is valid.
- It should be a
0x
-prefixed hexadecimal string per EIP-695, and parse to an integer number.
- It should be a
- Prevent the same chain ID from being added multiple times.
- See the next section for how to handle multiple RPC endpoints.
- Only use the submitted chain ID to sign transactions, never a chain ID received from an RPC endpoint.
- A malicious or faulty endpoint could return arbitrary chain IDs, and potentially cause the user to sign transactions for unintended chains.
- Verify that the specified chain ID matches the return value of
eth_chainId
from the endpoint, as described above.
RPC Endpoints and RPC URLs
Wallets generally interact with chains via an RPC endpoint, identified by some URL.
Most wallets ship with a set of chains and corresponding trusted RPC endpoints.
The endpoints identified by the rpcUrls
parameter cannot be assumed to be honest, correct, or even pointing to the same chain.
Moreover, even trusted endpoints can expose users to privacy risks depending on their data collection practices.
Therefore, the wallet should:
- Inform users that their on-chain activity and IP address will be exposed to RPC endpoints.
- If an endpoint is unknown to the wallet, inform users that the endpoint may behave in unexpected ways.
- Observe good web security practices when interacting with the endpoint, such as require HTTPS.
- Clearly inform the user which RPC URL is being used to communicate with a chain at any given moment, and inform the user of the risks of using multiple RPC endpoints to interact with the same chain.
Validating Chain Data
A wallet that implements wallet_addEthereumChain
should expect to encounter requests for chains completely unknown to the wallet maintainers.
That said, community resources exist that can be leveraged to verify requests for many Ethereum chains.
The wallet should maintain a list of known chains, and verify requests to add chains against that list.
Indeed, a wallet may even prefer its own chain metadata over anything submitted with a wallet_addEthereumChain
request.
UX
Adding a new chain to the wallet can have significant implications for the wallet's functionality and the experience of the user. A chain should never be added without the explicit consent of the user, and different chains should be clearly differentiated in the wallet UI. In service of these goals, the wallet should:
- When receiving a
wallet_addEthereumChain
request, display a confirmation informing the user that a specific requester has requested that the chain be added. - Ensure that any chain metadata, such as
nativeCurrency
andblockExplorerUrls
, are validated and used to maximum effect in the UI. - If any images are provided via
iconUrls
, ensure that the user understands that the icons could misrepresent the actual chain added. - If the wallet UI has a concept of a "currently selected" or "currently active" chain, ensure that the user understands when a chain added using
wallet_addEthereumChain
becomes selected.
Preserving User Privacy
Although a request to add a chain that was already added should generally be considered a success, treating such requests as automatic successes leaks information to requesters about the chains a user has added to their wallet.
In the interest of preserving user privacy, implementers of wallet_addEthereumChain
should consider displaying user confirmations even in these cases.
If the user denies the request, the wallet should return the same user rejection error as normal so that requesters cannot learn which chains are supported by the wallet without explicit permission to do so.
Copyright
Copyright and related rights waived via CC0.