CAIPs
CAIPs copied to clipboard
Add chain-agnostic RPC
caip:
title: Chain-Agnostic JSON-RPC Interface
author: Dan Finlay [email protected]
discussions-to: TBA
status: Draft
type: Interface Standard
created: 2020-10-13
Simple Summary
As most Ethereum provider methods today use the eth_
prefix, we could further standardize this to allow any protocol prefix within a JSON-RPC method, and allow providers to support an arbitrarily extensible interface, like filecoin_
, xDai_
, starkware_
, or any other protocol identifier.
Abstract
We will need some kind of standard protocol identifier to use as a prefix for any protocol, and I would stress that since this is only application-facing (and not user-facing) it does not need to be hotly contentious meriting a name system, and instead can even be strongly unique identifiers of a given interface. For example:
// Arbitrary protocol-specific identifier as prefix:
const PREFIX = 'aowiehafidhashaiuwehfa45729298';
const accounts = await provider.send({
method: `${PREFIX}_accounts`
});
I'll leave the definition of these prefixes as out of the scope of this proposal, as I think arbitrary but unique prefixes can be safe and useful.
Any method with a reserved prefix would then be reserved for interacting with that given protocol. For example, while today eth_accounts
can refer to any EVM chain, we might add some more specific prefixes, like EthMainnet_accounts
or EthRopsten_accounts
, or wallets could even support CAIP-2 compatible prefixes, like caip2:eip155:1_accounts
.
While some new providers are being written without protocol prefixes, it is trivial to add a prefix to all methods of any given JSON-RPC interface, making it easy for a new provider to be constructed from a provider that is compatible with this proposal, and making it trivial for this proposal to wrap any given JSON-RPC interface.
Motivation
The Ethereum JSON-RPC protocol has established JSON-RPC as the standard for new blockchains, with new chains introducing their own JSON-RPC interfaces:
For wallets looking to support multiple protocols at once, a popular approach for the short-term has been for wallets to manage multiple networks (like in EIP-2015), but this has drawbacks:
- It puts a UX burden on users to think about networks.
- It prevents the creation of multi-chain applications, since each is connected to only a single network.
- It creates race conditions in applications where the provider's chain could change definition while a method call is in-flight.
Two other approaches would be:
- Allow the provider to return additional providers in response to methods.
- Allow the provider to handle multiple simultaneous networks at once itself.
Allowing a provider to return additional providers is a nice developer experience, but it breaks outisde the scope of JSON-RPC, and so I would argue it should be built at the convenience library layer, and instead the JSON-RPC interface itself should define how to handle multiple providers.
Specification
The specification is very simple:
Providers that want to support multiple networks should use unique prefixes to namespace the methods for those various networks. As those prefixes and underlying interfaces are defined, they should be publicized so that they can be more widely adopted by other providers and wallets.
Additionally, the provider should allow detecting what interfaces are supported, and so I will suggest one feature detection method, which will return an array of the supported interface identifiers:
{
method: 'getSupportedProtocols',
}
// returns:
['EtherMain', 'EtherRopsten', 'EtherXDai', 'Bitcoin']
Rationale
Opening this CAIP as a discussion point, there are many variations that could be adopted to the proposal; Maybe this proposal itself should be behind a namespace, for example. Otherwise, I think the Motivation above covers the rationale adequatel.
Backwards Compatibility
As long as new network identifiers do not overlap with existing prefixes, providers adopting this should be backwards compatible with older providers. This backwards compatibility safety could be enhanced by putting this proposal itself behind another namespace, like caipN_${PROTOCOL_PREFIX}_${METHOD}
.
Links
This proposal was spurred by a question asked on Twitter by Philippe Castonguay.
Partly inspired by some work I was exploring with adding new protocols to MetaMask in our Snaps beta.
Copyright
Copyright and related rights waived via CC0.
Personally I think that we should be able to design a CAIP authentication pattern instead.
EIP-1102 is ubiquitous but obviously it assumes EVM chains only. This assumptions comes with two standards in this interaction: EIP-155 chainId and EIP-1474 JSON-RPC methods
What if we created an equivalent to EIP-1102 that did not make no assumption of these standards. I've described something very similar here.
What I envision is something called caip_authenticate
which included two parameters: requested chainId's (CAIP-2 compatible) and expected JSON-RPC methods. Here is how I envision for example the EIP-1102 being replicated in this JSON-RPC method
// Request
{
"id": 1,
"jsonrpc": "2.0",
"method": "caip_authenticate",
"params": {
"chains": ["eip155:1"],
"methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "personal_sign"]
}
}
// Response
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"accounts": ["0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb@eip155:1"],
}
}
What are we achieving with this new method? Request accounts in a chain-agnostic manner and explicit permission of the JSON-RPC methods to be used for this "session"
This could be further improved with the work that Metamask is doing with JSON-RPC capabilities
I think that we should be able to design a CAIP authentication pattern instead.
My impression is that these proposals are distinct and could be compatible, as long as the methods being requested are strongly linked to the chain they are associated with.
How would this pattern as you're imagining it support connections that require multiple blockchains? (imagine an ETH-xDai bridge, for example)
Good point, my proposal makes the assumption that methods are uniquely to a chainId.
In that case I will make a separate CAIP proposal for authentication specifically as yours is regarding for the procedure of calling methods targetted to a chainId
Consequently we can create a third proposal for a CAIP provider API which inherits from these two standards and potentially includes events as well (analogous to EIP-1193)
On that note would it be more beneficial to target requests to chainId's or accountId's??
A provider session could have two accounts exposed with the same chainId.
Cool, thanks for the feedback, requested changes have been made.
Would be good if there was a registry of well known prefixes. Could be a simple *.csv
file in this repo?
{ method: 'getSupportedProtocols', }
// returns: ['EtherMain', 'EtherRopsten', 'EtherXDai', 'Bitcoin']
This should be changed to be synonymous with other CAIPs including the recently proposed CAIP-25. Instead I would include a method prefixed with caip
then I would use CAIP-2 chainId's:
// Response
{
"id": 1,
"jsonrpc": "2.0",
"method": "caip_getSupportedChains",
"params": {}
}
// Result
{
"id": 1,
"jsonrpc": "2.0",
"result": ["eip155:1", "eip155:3", "eip155:100", "bip122:000000000019d6689c085ae165831e93"]
}
@pedrouid I didn't get a chance to comment on your other CAIP for getSupportedChains
but I think it excludes use cases. For example, the did_*
prefix is not associated with any particular "chain". Same things for L2s which are not really "chains". getSupportedProtocols
seems more generic and inclusive.
@pedrouid I didn't get a chance to comment on your other CAIP for getSupportedChains
should we leave the window open for longer? It is kind of a trade-off "waiting for feedback" vs. "getting CAIPs merged in time" - not yet sure if the current timing is OK - feedback welcome
getSupportedChains but I think it excludes use cases. For example, the did_* prefix is not associated with any particular "chain". Same things for L2s which are not really "chains". getSupportedProtocols seems more generic and inclusive.
@oed I get your point but then we need to define some standard for protocol definition that isn't a chain. Technically CAIPs should be about blockchains hence its name but I would like to include other distributed network protocols given they have their own namespace and reference that could be compatible with CAIP-2 or similar.
For example, could it be reasonable that did
is the namespace and the reference would be a DID method?
// Response
{
"id": 1,
"jsonrpc": "2.0",
"method": "caip_getSupportedProtocols",
"params": {}
}
// Result
{
"id": 1,
"jsonrpc": "2.0",
"result": ["did:3", "did:key"]
}
Technically CAIPs should be about blockchains hence its name but I would like to include other distributed network protocols given they have their own namespace and reference that could be compatible with CAIP-2 or similar.
Yeah I think limiting it to blockchains is kind of arbitrary. CAIP is just the name that we ended up with, and I'd rather have this be more around any protocol where you have a wallet with keys that signs things.
Your example there makes sense except that you wouldn't need specific prefixes for different DID methods :)
Alternatively why don't we just call it caip_getSupportedMethods
?
No matter if you are specifying eip155:1
for Ethereum Mainnet or did
for Decentralized Identities. You are not explicitly saying which methods you support.
The most common example on Ethereum is eth_signTypedData
which is not finalized therefore it would technically not be part of Ethereum JSON-RPC API but it's still widely used and it should be expected by some applications.
I would proposed instead that similarly to CAIP-25 that it should explicitly describe all methods individually in an array.
// Response
{
"id": 1,
"jsonrpc": "2.0",
"method": "caip_getSupportedMethods",
"params": {}
}
// Result
{
"id": 1,
"jsonrpc": "2.0",
"result": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "personal_sign"]
}
We should update this PR to introduce caip_getSupportedMethods
and also add a new PR to add caip_getSupportedChains
Largely overtaken by events-- see #25, #217 (updating 25 substantially after months of work in the RPC WG with MetaMask and others), and #104 for namespacing RPC methods across multiple VMs/types of chain