Skip to content

Latest commit

 

History

History
215 lines (169 loc) · 9.4 KB

sep-0043.md

File metadata and controls

215 lines (169 loc) · 9.4 KB

Preamble

SEP: 0043
Title: Standard Web Wallet API Interface
Authors: Piyal Basu <[email protected]>, Leigh McCulloch <@leighmcculloch>, George Kudrayvtsev <[email protected]>, Enrique Arrieta <@earrietadev>, Orbit Lens <@orbitlens>
Track: Standard
Status: Draft
Created: 2024-04-11
Version: 1.2.1
Discussion: https://github.com/stellar/stellar-protocol/discussions/1467

Abstract

This standard aims to enhance developer experiences by standardizing an interface for web wallets to use when interacting with other codebases.

Motivation

There are numerous Stellar wallets in the ecosystem with this number expected to grow as the ecosystem does. Wallets expose an API to allow dapps to call methods that perform such common tasks as transmitting a wallet's address. An issue is that wallets all use slightly different API's to perform similar functions, with different method names and call signatures as well as different return values. Developers have a motivation to integrate with as many as possible, but currently, they must create abstractions to handle every wallet they wish to connect to. This proposal presents a standard API interface for all wallets to implement. If all wallets have the same interface, it removes the need for developers to create abstractions for every individual wallet they want to integrate with. Developers can safely assume a wallet uses this agreed-upon interface, creating simpler code paths that easily connect to current wallets while also simplifying the onboarding of new wallets.

Specification

The standard web wallet interface provides a structure for common methods that wallets are expected to offer. In addition, the interface defines common error message shapes to ensure wallets adhere to informative and usable error messaging. Messages are designed to be surfaced directly to the user, so they should provide a readable description of what went wrong.

Wallet Interface Format

Wallets will employ an API using the following format:

interface Error {
  message: string,    // general description message returned to the client app
  code: number,       // unique error code
  ext?: Array<string>  // optional extended details
}

{
  getAddress: () =>
    Promise<{
      address: string;
    } & error?: Error>,

  signTransaction: (
    xdr: string,
    opts?: {
      networkPassphrase?: string,
      address?: string;
      submit?: boolean;
      submitUrl?: string;
    }) =>
    Promise<{
      signedTxXdr: string;
      signerAddress: string;
    } & error?: Error>,

  signAuthEntry: (
    authEntry: string,
    opts?: {
      networkPassphrase?: string,
      address?: string
    }) =>
    Promise<{
      signedAuthEntry: string;
      signerAddress: string;
    } & error?: Error>,

  signMessage: (
    message: string,
    opts?: {
      networkPassphrase?: string,
      address?: string
    }) =>
    Promise<{
      signedMessage: string;
      signerAddress: string;
    } & error?: Error>,

  getNetwork: () =>
    Promise<{
      network: string,
      networkPassphrase: string
    } & error?: Error>
}

In addition, this proposal has a standard for error interfaces.

The errors will return a specific code depending on the type of error that the wallet is encountering. Codes map as follows:

-1: internal wallet error, likely caused by the wallet logic itself
-2: external service (Horizon, RPC, etc.) returned an error
-3: client app request is invalid (wrong parameters, invalid transaction XDR, etc.)
-4: user rejected the request, client app should not try to retry the request

Alongside these error codes, the wallet will include a message key that maps to a custom error string that the wallet can define. This string will be a human readable message that informs the user of what went wrong.

Wallets may also include an optional ext field which is an array of strings that may provide some specific information about the error.

Below are examples of different kinds of errors a wallet may surface:

  // an internal error occurred in the wallet. For example, a JS runtime error

  {
    message: 'The wallet encountered an internal error. Please try again or contact the wallet if the problem persists.',
    code: -1
  },

  // an error occurred with an external service. For example, Horizon returned an error

  {
    message: 'An error occurred with Horizon. Please try again.',
    code: -2,
    ext: ['Operation 2: Invalid "amount" value.', "Operation 5: Asset issuer is required."] // malformed tx error example
  },

  // Either the dapp or the user passed a malformed request to the wallet. For example, a user didn't pass a valid XDR to `signTransaction`

  {
    message: 'Request is invalid. Please check the details and try again.',
    code: -3,
    ext: ['Invalid transaction XDR'] // example error
  },

  // The wallet received the request from the client, but the user decided to decline.

  rejected: {
    message: 'The user rejected this request.',
    code: -4
  }

Methods

getAddress

getAddress will provide the public key (G...) the wallet is signing for. This may be the account loaded in the wallet, or it may be a different account that the wallet is the signer for.

signTransaction

signTransaction will take an XDR provided by the requester and apply a signature to it before returning a base64-encoded string XDR-encoded Transaction Envelope with Decorated Signatures and the signer address back to the requester. The first parameter is the XDR string while the second parameter is a set of options. Options allow a user to specify what network they intend the transaction to be signed on. They can do so by passing the network's passphrase as networkPassphrase. Options also allow a wallet to specify which account they're seeking a signature for as address. If a wallet holds numerous addresses, it can use this param to ensure it is signing with the intended address. Options also allow a user to set a submit flag, which will allow a user to sign a transaction and immediately submit it to a network. If a user would like to configure the URL of the network to which they would like to submit, they can do so by setting submitUrl.

signAuthEntry

Similar to its transaction counterpart, signAuthEntry will take an authorization entry preimage provided by the requester and apply a signature to it before returning a signed hash of the same authorization entry and the signer address back to the requester. The first parameter is the XDR string while the second parameter is a set of options. Options allow a user to specify what network they intend the transaction to be signed on. They can do so by passing the network's passphrase as networkPassphrase. Options also allow a wallet to specify which account they're seeking a signature for as address. If a wallet holds numerous addresses, it can use this param to ensure it is signing with the intended address.

signMessage

signMessage is similar to its transaction and auth entry counterparts in that it will take a payload provided by the requester and apply a signature to it before returning the HEX-encoded message derived from the public key and original message as well as the signer address back to the requester. This method is different in that signMessage accepts an arbitrary string rather than a transaction or auth entry. This can be used to implement identity/ownership verification. The first parameter is the XDR string while the second parameter is a set of options. Options allow a user to specify what network they intend the transaction to be signed on. They can do so by passing the network's passphrase as networkPassphrase. Options also allow a wallet to specify which account they're seeking a signature for as address. If a wallet holds numerous addresses, it can use this param to ensure it is signing with the intended address.

getNetwork

getNetwork provides details about the network that the wallet is currently configured to. This allows a dapp to confirm that they are building a transaction for the correct network.

Errors

Error messaging provides clear errors to the requester. The message field provides an informative, human readable string that a UI could surface to the end user. This message should include actions a user can take to remedy the situation. The 4 types of code key delineate between possible errors: those caused by an internal wallet error, an error caused by external service (for ex: Horizon or Soroban RPC), invalid user input (for ex: a malformed XDR), and an error caused by the user rejecting the action requested. Finally, the ext field is an optional value that can provide more context for the error, if needed. The wallet is responsible for localizing the message and ext fields to be useful for their users.

Changelog