KIP | Title | Author | Status | Type | Category | Created |
---|---|---|---|---|---|---|
0017 |
walletconnect-v2-sign implementation spec |
Jacquin Mininger @jmininger, Doug Beardsley @mightybyte, Linda Ortega @lindaortega, Jermaine Jong @jermaine150, Albert Groothedde @alber70g |
Final |
Standard |
Interface |
2022-11-15 |
- Motivation
- Kadena's WalletConnect Specification
- Rationale for the spec
- Backwards Compatibility
This KIP proposes that the Kadena ecosystem implement the WalletConnect v2 Sign API. This API allows for establishing a secure channel for communicating between dApps and wallets in a platform-agnostic manner.
This is beneficial to Kadena for the following reasons:
- The Kadena ecosystem doesn't have a standard protocol for wallets and dApps to communicate with each other.
- The WalletConnect (WC) protocol is tried and tested across all devices and it removes the burden of having to maintain a Kadena-specific implementation.
- Wallets and dApps that are already using the WC protocol will have an easier time integrating with the Kadena ecosystem.
- Kadena's previous Signing API required the wallet to be able to run an http server. This is not feasible for some browser-based and mobile wallets.
This specification is built on top of the WalletConnect Specification.
The dApp initiates a pairing with a wallet using WalletConnect as a tunnel. This is done by sending a so called Proposal. This proposal contains the chains, methods, and events the initiator wants to utilize. The wallet responds with the Settlement. This contains information on which of the requested items it supports.
// Proposal Request
{
// ... other properties from the WalletConnect Proposal Request
"requiredNamespaces": {
"kadena": {
"chains": ["kadena:mainnet01", "kadena:testnet04", "kadena:development"],
"methods": [
"kadena_getAccounts_v1",
"kadena_sign_v1",
"kadena_quicksign_v1"
],
"events": []
}
}
}
// Settlement Response
{
// ... other properties from the WalletConnect Settlement Response
"namespaces": {
"kadena": {
"accounts": [
"kadena:mainnet01:38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89",
"kadena:testnet04:38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89",
"kadena:development:22ddc64851718e9d41d98b0f33d5e328ae5bbbbd97aed9885adac0f2d070ff9c"
],
"methods": [
"kadena_getAccounts_v1",
"kadena_sign_v1",
"kadena_quicksign_v1"
],
"events": []
}
}
}
There are also optionalNamespaces
that may be included, but are not required in the settlement from the wallet.
The structure for these is the same as the structure for the requiredNamespaces
.
The dApp uses the requiredNamespaces
and optionalNamespaces
fields to indicate to the wallet what chains, events, and methods it would like permission to.
The main difference being that the wallet must grant access to all the chains, methods, and events specified in the requiredNamespaces
in order to establish an active session.
Also, the WalletConnect library enforces that a Session Response's accounts
field must contain at least one account per chain specified in requiredNamespaces
.
But it is up to the wallet to satisfy all, none, or some of the chains, methods, and events specified in the optionalNamespaces
field.
WalletConnect dictates a requiredNamespaces
property that contains:
requiredNamespaces
:Object
1.1.chains
:Array<string>
- an array of Chain IDs requested.
1.2.methods
:Array<string>
- an array of Methods requested.
1.3.events
:Array<string>
- an array of Events requested.
The response for the Proposal contains a namespaces
object with the following properties:
namespaces
:Object
1.1.accounts
:Array<string>
- an array of Accounts availble for signing.
1.2.methods
:Array<string>
- an array of Methods available.
1.3.events
:Array<string>
- an array of Events available.
Chain IDs are WalletConnect’s way of identifying specific blockchains within an ecosystem.
They are defined by the CAIP-2 standard and are formatted as:
<namespace> + ":" + <reference>
<namespace>
:string
- always defined as "kadena".<reference>
:string
- a unique network ID within the blockchain ecosystem (e.g.testnet04
,mainnet01
).
These are valid Chain IDs:
kadena:mainnet01
- Kadena mainnetkadena:testnet04
- Current Kadena testnetkadena:development
- Kadena devnet
NB:
Chain IDs
, as defined here, are semantically specific to WalletConnect and are not equivalent to a Kadena "Chain ID" (e.g. chain 1). They are more closely related to Kadena'snetworkId
field. We are displaying KadenachainId
information in thekadena_getAccounts_v1
method.
Accounts are WalletConnect's way of specifying control over signing privileges.
They are defined by the CAIP-10 standard, and are formatted as:
<chain_id> + ":" + <account_address>
<chain_id>
:string
- the WalletConnect Chain ID.<account_address>
:string
- the public key available for signing by the wallet.
// WalletConnect Account Example
"kadena:mainnet01:38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89"
NB:
accounts
is semantically specific to WalletConnect. This does not represent an account in a Kadena fungible contract (e.g.coin
). Read the motivation for this in Accounts vs. Public Keys.
After the initial pairing with the wallet via WalletConnect, the Kadena accounts relevant for each public key can be requested by calling getAccounts.
The use of account names that can be derived from the public key (i.e. k:
-accounts that are defined as k:<public_key>
), is highly discouraged as implementing this will limit the end-users flexibility in which account to use, thus making dApps less generic.
WalletConnect methods are ways for dApps to interact with a wallet using predefined method identifiers and an optional payload.
The methods available for Kadena are:
Any additional Kadena method names will be formatted as:
kadena_<methodName>_v<methodVersionNumber>
<methodName>
:string
- name of the method in camelCase format.<methodVersionNumber>
:integer
- the version number of the method. Methods are versioned to allow upgradeability
This method returns the Kadena account names associated with a given WalletConnect account and contract(s) on the Kadena blockchain.
// kadena_getAccounts_v1 Method Request
{
"id": 1,
"jsonrpc": "2.0",
"method": "kadena_getAccounts_v1",
"params": {
"accounts": [
{
"account": "kadena:mainnet01:38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89",
"contracts": ["coin"] // optional, when omitted the wallet returns all known fungible accounts
}
]
}
}
// kadena_getAccounts_v1 Method Response
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"accounts": [
{
"account": "kadena:mainnet01:38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89",
"publicKey": "38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89",
"kadenaAccounts": [
{
"name": "w:aoriestnaoirsetnaorisetn",
"contract": "coin",
"chains": ["0", "1"]
},
{
"name": "bill",
"contract": "coin",
"chains": ["2", "4"]
},
{
"name": "k:38298612cc2d5e841a232bd08413aa5304f9ef3251575ee182345abc3807dd89",
"contract": "coin",
"chains": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19"
]
}
]
}
]
}
}
This method expects a method
field that is set to "kadena_getAccounts_v1"
.
This method also expects a params
object with the following properties:
params
:Object
1.1.accounts
:Array<Object>
__ 1.1.1account
:string
- a WalletConnect Account for which the Kadena account names are requested.
__ 1.1.2contracts
:Array<string>
(optional) - array of contracts for which the Kadena account name is requested. Returns all known Kadena accounts when omitted.
NB: We choose to not add chains to the getAccounts_v1 request since it would add complexity to the interface. The dApp can filter the necessary chains.
The method response expects a result
object with the following properties:
result
:Object
1.1.accounts
:Array<Object>
__ 1.1.1account
:string
- the requested WalletConnect Account.
__ 1.1.2publicKey
:string
- the requested public key, which was extracted from the WalletConnect account.
__ 1.1.3kadenaAccounts
:Array<Object>
____ 1.1.3.1name
:string
- the account name, as stored in the blockchain, for the specified contract.
____ 1.1.3.2contract
:string
- the contract on which this account name is present.
____ 1.1.3.3chains
:Array<string>
- the chains on which this account name is present.
NB: The accounts that are returned are the ones that are available in the scope of the wallet (i.e. only the accounts the wallet knows about).
NB: The same Kadena account name can be used in different contracts (e.g.
coin
,my-fungible
). They require different entries since the chains on which the accounts are present can differ.
QuickSign is part of the Kadena Signing API and was defined in kip-0015 (QuickSign Signing API v1). This method allows the wallet to show the user multiple transactions that need signature approval.
// kadena_quicksign_v1 Method Request
{
"id": 1,
"jsonrpc": "2.0",
"method": "kadena_quicksign_v1",
"params": {
"commandSigDatas": [CommandSigData] // type defined in KIP-15
}
}
// Successful kadena_quicksign_v1 Response
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"responses": [Response] // type defined in KIP-15
}
}
or
// Failed kadena_quicksign_v1 Response
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"error": QuicksignError // type defined in KIP-15
}
}
This method expects a method
field that is set to "kadena_quicksign_v1"
.
This method also expects a params
object with the following properties:
params
:Object
1.1.commandSigDatas
:Array<Object>
- A list ofCommandSigData
to sign.
If signing was successful, then the method response expects a result
object with the following properties:
result
:Object
1.1.responses
:Array<Object>
- A list ofResponse
containing the signed transactions.
If signing was NOT successful, then the result
object will contain the following properties:
result
:Object
1.1.error
:Object
- A list ofQuicksignError
.
Sign is part of the Kadena Signing API. This method allows the wallet to show the user a single transaction that needs signature approval.
// kadena_sign_v1 Method Request
{
"id": 1,
"jsonrpc": "2.0",
"method": "kadena_sign_v1",
"params": {
SigningRequest
}
}
// kadena_sign_v1 Response
{
"id": 1,
"jsonrpc": "2.0",
"result": {
SigningResponse
}
}
This method expects a method
field that is set to "kadena_sign_v1"
.
This method also expects a params
object with the following properties:
params
:Object
- ASigningRequest
containing information the wallet needs to create and sign the transaction.
The method response expects a result
object with the following properties:
result
:Object
- ASigningResponse
that contains a signed command ready to be submitted to the blockchain.
At the moment we see no need to standardize any events and believe that most use cases can be handled at the Kadena protocol level that sits atop Wallet Connect.
This is subject to change in the future as we understand the workflows more through extended use of the protocol.
However, any future Kadena event names will be formatted as:
kadena_<eventName>_v<eventVersionNumber>
<eventName>
:string
- name of the event in camelCase format.<eventVersionNumber>
:integer
- the version number of the event to allow for future upgradeability
Several options were considered when discussing what information to include
in the accounts
section of the initial pairing response.
However, the following reasons forced us to only include the public keys (prefixed with Kadena's WalletConnect Chain ID):
- Kadena fungible contracts (specifically the
coin
contract) have a maximum account name length of 256, but the CAIP-10 standard limits WalletConnect account names to a maximum of 128 characters. - We considered only supporting
k:
accounts, as they're built fromk
:publicKey
, but we want this response to be generic for all accounts that could exist on the Kadena blockchain.
Therefore, we strongly advise builders to integrate the kadena_getAccounts_v1
method into the pairing process with the wallet.
This will allow them to support multi-sig accounts (e.g. w:
-accounts) and
other means of signing transactions.
We do NOT recommend extracting the publicKey
from the WalletConnect account
and just adding a k:
in front of it.
While not required in the namespace proposal process, a network's SLIP-0044 value is used throughout the WalletConnect demo code.
Kadena's coin type is 626 as documented in (SLIP-0044)[https://github.com/satoshilabs/slips/blob/master/slip-0044.md].
- The
localhost:9467
web-server will be phased out. - The
/sign
and/quicksign
endpoints will have their counterparts in the WalletConnect Methodskadena_sign_v1
andkadena_quicksign_v1
. - For wallets that have the local web-server integrated, we suggest they keep this available behind a toggle while they transition to WalletConnect.