Keyper Agency Remote Procedure Call Specification

Simple Summary

This document defines a standard set of RPC methods that a Keyper Agency should implement.

Abstract

There’re kinds of wallets for Nervos CKB but few of them are able to sign transactions with user-specified signer since the logic of signature is too flexible to bundle them all in one wallet. Keyper Agency is such a kind of wallet conforming to Keyper Protocol which allows users to set custom signers for various transactions. However, it only constrains the workflow between users’ lock scripts and Keyper Agency, and doesn’t cover the communication between Keyper Agency and DApps. As a complement, this document standardizes such a specification to define the RPC methods between DApps and Keyper Agency.

Table of Contents

  1. Introduction
  2. Specification

    2.1. RFC 2119

    2.2. JSON RPC

    2.3. Error Code

    2.4. Keyper Agency Methods
  3. References

Introduction

Keyper Agency is a kind of wallet which follows Keyper Protocol, a protocol defining the behaviours between wallets and user’s lock scripts. But as a wallet, Keyper Agency also needs rules to handle requests from DApps, which will be elaborated in this document.

In the workflow of all DApps, the actions related to private key, e.g. signing transactions and messages, should be done in the wallet, so sign_transaction and sign_message are mandatory; A wallet is a user’s identity on blockchain, makes query_addresses inevitable; All these three methods are privacy sensitive and auth method is necessary. Besides, sending transactions is a basic function of a wallet, thus send_transaction and sign_and_send_transaction should be provided by Keyper Agency. These are the six RPC methods defined in this document.

Specification

RFC-2119

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.

JSON-RPC

Communication with Keyper Agency is accomplished using JSON-RPC, a stateless, lightweight remote procedure call protocol that uses JSON as its data format. Keyper Agency RPC methods MUST be called using JSON-RPC request objects and MUST respond with JSON-RPC response objects.

Error-Code

Code Message Meaning Category
1001 Rejected Request is rejected standard
1002 Invalid Token Authentication failed standard
1003 Remote Error Error from indexer server connected via Keyper Agency standard
1004 Unknown Error Other error standard

Example error response:

id: 1
jsonrpc: '2.0'
error:
  code: 1001
  message: Rejected

Keyper_Agency_Methods

  1. auth
  2. query_addresses
  3. sign_transaction
  4. send_transaction
  5. sign_and_send_transaction
  6. sign_message

Auth

Description

The auth method is used for authentication and authorization. With the request, DApp requires a token for the next requests. A token MUST be returned from Keyper Agency which MUST be set in headers[Authorization] in the following requests.

Along with the token, a flag named networkId MUST be returned to identify the type of the chain connected to Keyper Agency. The flag MUST be congruent with ChainInfo.chain from CKB Node.

Request
id: 1
jsonrpc: '2.0'
method: auth
params:
  description: message with the authorization request
Response
id: 1
jsonrpc: 2.0
result:
  token: token generated by keyper agency # should be set in headers[Authorization] in next requests
  networkId: ckb # network type of indexer connected via Keyper Agency, same as `ChainInfo.chain` in CKB Node RPC

Query_Addresses

Description

The query_addresses method is used to get addresses related information, such as it’s public key, lock hash, lock script, lock script meta.

Addresses are derived from lock scripts abiding by 0021-ckb-address-format, so each lock script imported in Keyper Agency can be located by an address and MUST be returned along it.

Since a user can have multiple addresses when multiple lock scripts are imported in Keyper Agency, the user id MUST be returned for DApp to manage addresses.

Request
id: 1
jsonrpc: 2.0
method: query_addresses
Response
id: 1
jsonrpc: '2.0'
result:
  userId: user_id # user id, the uuid of keystore
  addresses:
    - address: ckb address # address
      publicKey: public key # public key to generate the address
      lockHash: lock script hash # lock script hash
      lockScript: # lock script of the address
        codeHash: code hash
        hashType: type of code hash
        args: args appended in the lock script
      lockScriptMeta: # meta of lock script
        name: lock script name # lock script name defined by user
        headerDeps: [] # data used with the lock script
        cellDeps: # data used with the lock script
          - outPoint:
              txHash: tx hash of lock script
              index: tx index of lock script
            depType: dep type

Sign_Transaction

The sign_transaction method is used to sign a transaction generated by DApps.

There are four top-level fields in the params. Among them,

  1. The tx is the transaction object to sign, it has the same structure as Transaction listed in 0019-data-structures except that it has all fields camelcased. The cellDeps field MUST be left blank because it will be filled by data from user specified lock script;
  2. The lockHash is used to find out which lock script is used in the signing process;
  3. The inputSignConfig is used to indicate which witnesses will be signed by the lock script, it specifies the witness list by index and length of an array. All witnesses are covered if inputSignConfig is null, and the rest of witnesses are covered if length is -1;
  4. The description is an optional field for user interface.

A transaction with signed witnesses MUST be returned.

Request
id: 1
jsonrpc: '2.0'
params:
  tx: # transaction to sign
    version: '0x0'
    cellDeps: [] # leave this empty since Keyper Agency should fill them in.
    inputs:
      - previousOutput:
          txHash: tx hash
          index: previous output index
        since: since
    outputs:
      - capacity: capacity
        lock:
          codeHash: code hash
          hashType: hash type
          args: args
        type:
          codeHash: code hash
          hashType: hash type
          args: args
    outputsData:
      - 0x
    headerDeps: []
    witnesses:
      - lock: lock
        inputType: input type
        outputType: output type
  lockHash: lock hash used to locate signer provided by Keyper Agency
  description: friendly message with the signing request
  inputSignConfig: # optional, `null` to sign them all
    index: starting index of witnesses to sign
    length: count of witnesses to sign # -1 to sign the rest
Response
id: 1
jsonrpc: '2.0'
result:
  tx:
    version: '0x0'
    cellDeps: # filled by Keyper Agency
      - outPoint:
          txHash: tx hash
          index: index
        depType: dep type
    inputs:
      - previousOutput:
          txHash: tx hash
          index: index
        since: since
    outputs:
      - capacity: capacity
        lock:
          codeHash: code hash
          hashType: hash type
          args: args
    outputsData:
      - 0x
    headerDeps: []
    witnesses:
      - signed message # signed message by Keyper Agency
    hash: tx hash

Send_Transaction

Description

The send_transaction method is used to send a signed transaction via Keyper Agency.

The tx is the transaction object to send, it has the same structure as Transaction listed in 0019-data-structures except that it has all fields camelcased.

Requset
id: 1
jsonrpc: '2.0'
method: send_transaction
params:
  tx:
    version: '0x0'
    cellDeps:
      - outPoint:
          txHash: tx hash
          index: index
        depType: dep type
    inputs:
      - previousOutput:
          txHash: tx hash
          index: index
        since: since
    outputs:
      - capacity: cell capacity
        lock:
          codeHash: code hash
          hashType: hash type
          args: args
        type:
          codeHash: code hash
          hashType: hash type
          args: args
    outputsData:
      - 0x
    headerDeps: []
    witnesses:
      - signed message
    hash: tx hash
Response
id: 1
jsonrpc: '2.0'
result:
  txHash: hash of sent tx

Sign_and_Send_Transaction

Description

The sign_and_send_transaction is a combination of sign_transaction and send_transaction, which accepts four top-level fields as params:

  1. The tx is the transaction object to sign and send, it has the same structure as Transaction listed in 0019-data-structures except that it has all fields camelcased. The cellDeps field MUST be left blank because it will be filled by data from user specified lock script;
  2. The lockHash is used to find out which lock script is used in the signing process;
  3. The inputSignConfig is used to indicate which witnesses will be signed by the lock script, it specifies the witness list by index and length of an array. All witnesses are covered if inputSignConfig is null, and the rest of witnesses are covered if length is -1;
  4. The description is an optional field for user interface.

But the response has an additional transaction with signed witnesses instead of solely a transaction hash.

Request
id: 1
jsonrpc: '2.0'
params:
  tx: # transaction to sign
    version: '0x0'
    cellDeps: [] # leave this empty since Keyper Agency should fill them in.
    inputs:
      - previousOutput:
          txHash: tx hash
          index: previous output index
        since: since
    outputs:
      - capacity: capacity
        lock:
          codeHash: code hash
          hashType: hash type
          args: args
        type:
          codeHash: code hash
          hashType: hash type
          args: args
    outputsData:
      - 0x
    headerDeps: []
    witnesses:
      - lock: lock
        inputType: input type
        outputType: output type
  lockHash: lock hash used to locate signer provided by Keyper Agency
  description: friendly message with the signing request
  inputSignConfig: # optional, `null` to sign them all
    index: starting index of witnesses to sign
    length: count of witnesses to sign # -1 to sign the all left
Response
id: 1
jsonrpc: '2.0'
result:
  txHash: hash of sent tx
  tx:
    version: '0x0'
    cellDeps:
      - outPoint:
          txHash: tx hash
          index: index
        depType: dep type
    inputs:
      - previousOutput:
          txHash: tx hash
          index: index
        since: since
    outputs:
      - capacity: capacity
        lock:
          codeHash: code hash
          hashType: hash type
          args: args
        type:
          codeHash: code hash
          hashType: hash type
          args: args
    outputsData:
      - 0x
    headerDeps: []
    witnesses:
      - signed message
    hash: tx hash

Sign_Message

Description

The sign_message method is used to calculate the signature of a provided message

  • Request
id: 1
jsonrpc: '2.0'
method: sign_message
params:
  message: message to sign
  address: ckb address to locate private key for the signature
  • Response
id: 1
jsonrpc: '2.0'
result:
  sig: signed message

Rationale

There’s only a protocol called Keyper defines the interface of users’ lock scripts and Keyper Agency, whereas the communication between Keyper Agency and DApps is missing. Due to that each DApp should add a bundle of work for various API sets. This document defines a standard set of RPC methods so the entire cycle is complete and developer experience is uniformed.

References

Normative

Implements


Author: Keith

This is part of the work for Synapse’s grant roadmap, more details about Synapse’s grant, please refer to Synapse - Browser Wallet and Keyper Agency

2 Likes