ARC-25: Algorand WalletConnect v1 API Source

API for communication between Dapps and wallets using WalletConnect

AuthorJasonPaulos
Discussions-Tohttps://github.com/algorandfoundation/ARCs/issues/104
StatusFinal
TypeStandards Track
CategoryInterface
Created2022-05-12

Algorand WalletConnect v1 API

This document specifies a standard API for communication between Algorand decentralized applications and wallets using the WalletConnect v1 protocol.

Abstract

WalletConnect https://walletconnect.com/ is an open protocol to communicate securely between mobile wallets and decentralized applications (dApps) using QR code scanning (desktop) or deep linking (mobile). It’s main use case allows users to sign transactions on web apps using a mobile wallet.

This document aims to establish a standard API for using the WalletConnect v1 protocol on Algorand, leveraging the existing transaction signing APIs defined in ARC-1.

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.

Comments like this are non-normative.

It is strongly recommended to read and understand the entirety of ARC-1 before reading this ARC.

Overview

This overview section is non-normative. It offers a brief overview of the WalletConnect v1 lifecycle. A more in-depth description can be found in the WalletConnect v1 documentation https://docs.walletconnect.com/tech-spec .

In order for a dApp and wallet to communicate using WalletConnect, a WalletConnect session must be established between them. The dApp is responsible for initiating this session and producing a session URI, which it will communicate to the wallet, typically in the form of a QR code or a deep link. This processed is described in the Session Creation section.

Once a session is established between a dApp and a wallet, the dApp is able to send requests to the wallet. The wallet is responsible for listening for requests, performing the appropriate actions to fulfill requests, and sending responses back to the dApp with the results of requests. This process is described in the Message Schema section.

Session Creation

The dApp is responsible for initializing a WalletConnect session and producing a WalletConnect URI that communicates the necessary session information to the wallet. This process is as described in the WalletConnect documentation https://docs.walletconnect.com/tech-spec#requesting-connection, with one addition. In order for wallets to be able to easily and immediately recognize an Algorand WalletConnect session, dApps SHOULD add an additional URI query parameter to the WalletConnect URI. If present, the name of this parameter MUST be algorand and its value MUST be true. This query parameter can appear in any order relative to the other query parameters in the URI.

For example, here is a standard WalletConnect URI:

wc:4015f93f-b88d-48fc-8bfe-8b063cc325b6@1?bridge=https%3A%2F%2F9.bridge.walletconnect.org&key=b0576e0880e17f8400bfff92d4caaf2158cccc0f493dcf455ba76d448c9b5655

And here is that same URI with the Algorand-specific query parameter:

wc:4015f93f-b88d-48fc-8bfe-8b063cc325b6@1?bridge=https%3A%2F%2F9.bridge.walletconnect.org&key=b0576e0880e17f8400bfff92d4caaf2158cccc0f493dcf455ba76d448c9b5655&algorand=true

It is RECOMMENDED that dApps include this query parameter, but it is not REQUIRED. Wallets MAY reject sessions if the session URI does not contain this query parameter.

Chain IDs

WalletConnect v1 sessions are associated with a numeric chain ID. Since Algorand chains do not have numeric identifiers (instead, the genesis hash or ID is used for this purpose), this document defines the following chain IDs for the Algorand ecosystem:

  • MainNet (genesis hash wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=): 416001
  • TestNet (genesis hash SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=): 416002
  • BetaNet (genesis hash mFgazF+2uRS1tMiL9dsj01hJGySEmPN28B/TjjvpVW0=): 416003

At the time of writing, these chain IDs do not conflict with any known chain that also uses WalletConnect. In the unfortunate event that this were to happen, the algorand query parameter discussed above would be used to differentiate Algorand chains from others.

Future Algorand chains, if introduced, MUST be assigned new chain IDs.

Wallets and dApps MAY support all of the above chain IDs or only a subset of them. If a chain ID is presented to a wallet or dApp that does not support that chain ID, they MUST terminate the session.

For compatibility with WalletConnect usage prior to this ARC, the following catch-all chain ID is also defined:

  • All Algorand Chains (legacy value): 4160

Wallets and dApps SHOULD support this chain ID as well for backwards compatibility. Unfortunately this ID alone is not enough to identify which Algorand chain is being used, so extra fields in message requests (i.e. the genesis hash field in a transaction to sign) SHOULD be consulted as well to determine this.

Message Schema

Note: interfaces are defined in TypeScript. These interfaces are designed to be serializable to and from valid JSON objects.

The WalletConnect message schema is a set of JSON-RPC 2.0 https://www.jsonrpc.org/specification requests and responses. Decentralized applications will send requests to the wallets and will receive responses as JSON-RPC messages. All requests MUST adhere to the following structure:

interface JsonRpcRequest {
  /**
   * An identifier established by the Client. Numbers SHOULD NOT contain fractional parts.
   */
  id: number;
  /**
   * A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
   */
  jsonrpc: "2.0";
  /**
   * A String containing the name of the RPC method to be invoked.
   */
  method: string;
  /**
   * A Structured value that holds the parameter values to be used during the invocation of the method.
   */
  params: any[];
}

The Algorand WalletConnect schema consists of a single RPC method, algo_signTxn, as described in the following section.

All responses, whether successful or unsuccessful, MUST adhere to the following structure:

interface JsonRpcResponse {
  /**
   * This member is REQUIRED.
   * It MUST be the same as the value of the id member in the Request Object.
   * If there was an error in detecting the id in the Request object (e.g. Parse error/Invalid Request), it MUST be Null.
   */
  id: number;
  /**
   * A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
   */
  jsonrpc: "2.0";
  /**
   * This member is REQUIRED on success.
   * This member MUST NOT exist if there was an error invoking the method.
   * The value of this member is determined by the method invoked on the Server.
   */
  result?: any;
  /**
   * This member is REQUIRED on error.
   * This member MUST NOT exist if the requested method was invoked successfully.
   */
  error?: JsonRpcError;
}

interface JsonRpcError {
  /**
   * A Number that indicates the error type that occurred.
   * This MUST be an integer.
   */
  code: number;
  /**
   * A String providing a short description of the error.
   * The message SHOULD be limited to a concise single sentence.
   */
  message: string;
  /**
   * A Primitive or Structured value that contains additional information about the error.
   * This may be omitted.
   * The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
   */
  data?: any;
}

algo_signTxn

This request is used to ask a wallet to sign one or more transactions in one or more atomic groups.

Request

This request MUST adhere to the following structure:

interface AlgoSignTxnRequest {
  /**
   * As described in JsonRpcRequest.
   */
  id: number;
  /**
   * As described in JsonRpcRequest.
   */
  jsonrpc: "2.0";
  /**
   * The method to invoke, MUST be "algo_signTxn".
   */
  method: "algo_signTxn";
  /**
   * Parameters for the transaction signing request.
   */
  params: SignTxnParams;
}

/**
 * The first element is an array of `WalletTransaction` objects which contain the transaction(s) to be signed.
 * If transactions from an atomic transaction group are being signed, then all transactions in the group (even the ones not being signed by the wallet) MUST appear in this array.
 * 
 * The second element, if present, contains addition options specified with the `SignTxnOpts` structure.
 */
type SignTxnParams = [WalletTransaction[], SignTxnOpts?];

SignTxnParams is a tuple with an optional element https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#optional-elements-in-tuple-types, meaning its length can be 1 or 2.

The WalletTransaction and SignTxnOpts types are defined in ARC-1.

All specifications, restrictions, and guidelines declared in ARC-1 for these types apply to their usage here as well. Additionally, all security requirements and restrictions for processing transaction signing requests from ARC-1 apply to this request as well.

For more information, see ARC-1 - Syntax and Interfaces and ARC-1 - Semantic and Security Requirements.

Response

To respond to a request, the wallet MUST send back the following response object:

interface AlgoSignTxnResponse {
  /**
   * As described in JsonRpcResponse.
   */
  id: number;
  /**
   * As described in JsonRpcResponse.
   */
  jsonrpc: "2.0";
  /**
   * An array containing signed transactions at specific indexes.
   */
  result?: Array<SignedTxnStr | null>;
  /**
   * As described in JsonRpcResponse.
   */
  error?: JsonRpcError;
}

SignedTxnStr type is defined in ARC-1.

In this response, result MUST be an array with the same length as the number of WalletTransactions in the request (i.e. <AlgoSignTxnRequest instance>.params[0].length). For every integer i such that 0 <= i < result.length:

  • If the transaction at index i in the group should be signed by the wallet (i.e. <AlgoSignTxnRequest instance>.params[0][i].signers is not an empty array): result[i] MUST be a base64-encoded string containing the msgpack-encoded signed transaction params[0][i].txn.
  • Otherwise: result[i] MUST be null, since the wallet was not requested to sign this transaction.

If the wallet does not approve signing every transaction whose signature is being requested, the request MUST fail.

All request failures MUST use the error codes defined in ARC-1 - Error Standards.

Rationale

Security Considerations

None.

Copyright and related rights waived via CCO.

Citation

Please cite this document as:

JasonPaulos, "ARC-25: Algorand WalletConnect v1 API," Algorand Requests for Comments, no. 25, May 2022. [Online serial]. Available: https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0025.md.