Common Wallet Interface

This document describes the format you can expect the Wallet instance object to look like.

WalletInstance {
  /*
   * Props
   */
  address: String,
  chainId: Number,
  keystore: Promise<String>,
  mnemonic: String,
  derivationPath?: Promise<String>,
  otherAddresses: Array<String>,
  privateKey: String,
  publicKey: Promise<String>,
  type: String,
  subtype: String,
  /*
   * Methods
   */
  setDefaulAddress(addressIndex: Number): Promise<Boolean>,
  sign(transactionObject: Object): Promise<String>
  signMessage(messageObject: Object): Promise<String>
  verifyMessage(verificationObject: Object): Promise<Boolean>
}

Values in the wallet object will be set if possible upon instantiation, but may be left undefined in certain contexts. For example, when instantiating a software wallet using an existing privateKey, the mnemonic value cannot be derived from a private key and so it will remain undefined. However, when instantiating with a mnemonic the privateKey will be set (with the first address as the default derivationPath).

Props

Methods

Props

address

WalletInstance.address: String

Contains the wallet's public address in the form of String.

Tip: Across all wallet types and formats this is the only value that will certainly be present in the object.

Note: For the Metamask Wallet this will always reflect the address selected from the UI, so you can always count on it to be accurate.

Usage:

import { open } from '@colony/purser-software';

const wallet = await open({ privateKey: `0x9274...f447` });

console.log(wallet.address); // 0x3953...a4CC

chainId

WalletInstance.chainId: Number

Contains the id of the network the wallet is intended to work on (eg: homestead, ropsten, etc).

This is used on the hardware wallets to determine the derivationPath and on all wallet types as a default if one isn't provided to the object of transaction you wish to sign.

Note: For the Metamask Wallet this is not available as it handles it internally, but can be changed using the UI.

Usage:

import { open } from '@colony/purser-ledger';

const wallet = await open({ chainId: 3 });

console.log(wallet.chainId); // 3

keystore

WalletInstance.keystore: Promise<String>

This is prop has both a getter and a setter attached to it. The getter is async and returns a Promise, while the setter is synchronous and gives you the ability to set the encryption password.

The getter Promise will not resolve if an encryption password wasn't set, either via the password argument when instantiating the wallet or via the aforementioned setter.

Upon resolving, the Promise will return a JSON-formatted String. (Which you can transform into an object using JSON.parse()).

This getter is also memoized, so the next time you read its value, it will be served from memory instead of being re-calculated.

If the wallet was instantiated using an encrypted keystore, than this value is already set and memoized, so calling this will return the value instantly,

If you need more information about the encrypted keystore, you can check out the Web3 Secret Storage Definition.

Usage:

import { open } from '@colony/purser-software';

const wallet = await open({ privateKey: `0x9274...f447` });

let keystore = await wallet.keystore; // Promise rejects: You did not provide a password for encryption...

console.log(keystore); // undefined

wallet.keystore = '0fbfd56c94dc9d2578a6';

let keystore = await wallet.keystore;

console.log(keystore); // {"address":"3953...06a4","version":"0.1"}}

mnemonic

WalletInstance.mnemonic: String

If a new wallet was instantiated, or a new instance was created via a mnemonic phrase, this prop will contain that (or a new) phrase in the form of a String.

Usage:

import { create } from '@colony/purser-software';

const wallet = await create();

console.log(wallet.mnemonic); // load blush spray dirt random cash pear illness pulse sketch sheriff surge

derivationPath

WalletInstance.derivationPath: Promise<String>

This is a getter that returns a Promise. Upon resolving, the promise returns a BIP32 derivation path in the form of a String.

When instantiating a software wallet using a mnemonic phrase, this is used to re-create the privateKey. This defaults to m/44'/60'/0'/0/0, but can be manually set when creating the wallet instance.

On a hardware wallet, this is read-only, and is used to derive all the address indexes.

Usage:

import { open } from '@colony/purser-software';

const wallet = await open({ mnemonic: 'load blush ... sheriff surge' });

console.log(await wallet.derivationPath); // m/44'/60'/0'/0/0
import { open } from '@colony/purser-trezor';

const wallet = await open();

console.log(await wallet.derivationPath); // m/44'/60'/0'/0/0

await wallet.setDefaultAddress(1);

console.log(await wallet.derivationPath); // m/44'/60'/0'/0/1

otherAddresses

WalletInstance.otherAddresses: Array<String>

Note: This prop is only available on Hardware Wallet types (Eg: Trezor).

It contains an Array of all the addresses that were derived initially when opening the wallet, by specifying a number to the addressCount prop. (The addresses in the Array are in String format).

This is useful to see all the addresses that you have access to.

Note, that if only one address was derived when you opened the wallet (Eg: { addressCount : 1 }), this prop will be undefined. This is because it will only contain one entry, which is also the default selected address (See: setDefaultAddress).

Usage:

import { open } from '@colony/purser-trezor';

const multipleAddresesWallet = await open();

console.log(wallet.otherAddress); // [0x56B4...8173, 0x0F91...d9A8, 0x26eB...bAD1, 0xb883...49F6, 0x9d4E...7dbc, 0x4a59...8526, 0x9E8b...5C28, 0x6F29...A682, 0x4BAB...5aFb, 0x9677...9647]

console.log(wallet.otherAddress.length); // 10
import { open } from '@colony/purser-trezor';

const multipleAddresesWallet = await open({ addressCount: 1 });

console.log(wallet.otherAddress); // undefined

privateKey

WalletInstance.privateKey: String

Contains the privateKey for the wallet in String form. This will be available in all cases: if you created a new wallet instance, if you opened a wallet instance using either a mnemonic or a private key.

Warning: As the name suggests, this is private. So treat it with caution and if possible don't expose it to other parts of your app.

Usage:

import { open } from '@colony/purser-software';

const wallet = await open({ mnemonic: 'load blush ... sheriff surge' });

console.log(wallet.privateKey); // 0x9274...f447

publicKey

WalletInstance.publicKey: Promise<String>

This is a getter that returns a Promise. Upon resolving, the promise returns the public key for the current address, in String form.

This is useful for cases where you want to prove the wallet's identity without exposing any private and dangerous information (Eg: privateKey, mnemonic...).

Note: The Metamask Wallet does not provide native access to the public key, but it can be recovered from a signed message. in order to access it, you will first have to sign a message with Metamask to obtain the public key. It will then be saved locally for future reference (current selected address only), so that if you have to use it again, you won't have re-sign the message.

Usage:

import { open } from '@colony/purser-trezor';

const wallet = await open();

console.log(await wallet.publicKey); // 0x93f7 ... a9dd

type

WalletInstance.type: String

This is just a simple string value that represents the main type for the instantiated wallet object.

Usage:

import { create } from '@colony/purser-software';

const wallet = await create();

console.log(wallet.type); // software

subtype

WalletInstance.subtype: String

This is just a simple string value that represents the sub type for (wallet type engine) the instantiated wallet object.

Usage:

import { create } from '@colony/purser-software';

const wallet = await create();

console.log(wallet.subtype); // ethers

Methods

setDefaultAddress()

WalletInstance.setDefaultAddress(addressIndex: Number): Promise<Boolean>

Note: This prop is only available on Hardware Wallet types (Eg: Trezor).

This method returns the address defined in the address, publicKey and derivationPath props, and which will be used when calling the sign(), signMessage() and verifyMessage() methods, as it can only use one at a time for these operations.

This method takes in an address index argument as a Number (this corresponds to the otherAddresses Array) and sets that address's value internally.

If setting the address value is successful, it will return true, otherwise it will throw. The only case this will fail is if you provide an unavailable address index. (Eg: if you opened the wallet with { addressCount: 1 }, there's no other addressIndex that will work, except 0)

Usage:

import { open } from '@colony/purser-trezor';

const multipleAddresesWallet = await open();

console.log(wallet.address); // 0x56B4...8173

await wallet.setDefaultAddress(2);

console.log(wallet.address); // 0x0F91...d9A8

sign()

WalletInstance.sign(transactionObject: Object): Promise<String>

Sign an Ethereum transaction using the current default address.

This method takes in an transactionObject Object (See below), and returns the hex String signature wrapped inside a Promise (This method is async).

The transactionObject props will each be individually validated, and will throw if there is something wrong with any of them.

Note: On hardware wallets this method will require some form of confirmation from the user.

Note: Metamask is designed to handle its own nonce count. You can manually set it, but it's advisable to leave it out of the transaction object. One case where you would want to override the nonce would be to over-write a previously sent pending transaction (with different values or a higher gas price).

transactionObject format:

transactionObject {
  gasPrice: bigNumber // The gas price you're willing to pay for this transaction, in WEI, as an instance of bigNumber. Defaults to 9000000000 WEI (9 GWEI)
  gasLimit: bigNumber // The gas limit you want for this transaction, as an instance of bigNumber. Defaults to 21000
  chainId: Number // The chain id where the transaction is going to be sent. Defaults to 1.
  nonce: Number // The nonce of the transaction. Defaults to 0.
  to: String // The destination address to send the transaction to, as a hex String. This is the only REQUIRED prop by this library
  value: bigNumber // The value you want to send to the destination address, in WEI, as an instance of bigNumber. Defaults to 1 WEI
  inputData: String // The additional input data to send in the transaction, as a hex String. Defaults to `0x00`
}

Usage:

import { open } from '@colony/purser-trezor';

const trezorWallet = await open();

const transactionSignature = await trezorWallet.sign({ to: '0x3953...a4C1' }); // 0xF990...8d91
import { open } from '@colony/purser-trezor';
import { bigNumber } from '@colony/purser-core/utils';

const trezorWallet = await open();

const transaction = {
  gasPrice: bigNumber('0.00000001').toWei(),
  gasLimit: bigNumber(30000),
  chainId: 4,
  nonce: 15987,
  to: '0x3953...a4C1',
  value: bigNumber(1).toWei(),
  inputData: '0x00',
};

const transactionSignature = await trezorWallet.sign(transaction); // 0xf849...5681

signMessage()

WalletInstance.signMessage(messageObject: Object): Promise<String>

Sign a message with your public key to prove your identity and ownership of the address.

This method takes in an messageObject Object (See below), and returns the hex String signature wrapped inside a Promise (This method is async).

The messageObject only has one prop, message, but to keep consistency with the rest of the library, it is passed in as an Object.

Note: On hardware wallets this method will require some form of confirmation from the user.

messageObject format:

messageObject {
  message: String // The message you want to sign, as a String. Defaults to the '' empty String
}

Usage:

import { open } from '@colony/purser-trezor';

const trezorWallet = await open();

const messageSignature = await trezorWallet.signMessage({ message: 'Yes, this is me!' }); // '0xa1f7...0b1c'

verifyMessage()

WalletInstance.verifyMessage(verificationObject: Object): Promise<Boolean>

Verify a previously signed message to validate your identity and prove it was indeed signed by your current account.

This method takes in an verificationObject Object (See below), and returns a Boolean wrapped inside a Promise (This method is async).

If the (internally signed) message matches the provided signature, it will return true, otherwise it will return false (And if you're in a development environment, also a warning).

Note: On hardware wallets this method may require some form of confirmation from the user (depending on the hardware wallet type).

verificationObject format:

messageObject {
  message: String // The message you want to verify, as a String. Defaults to the '' empty String
  signature: String // The signature you want to verify the message against, as a `hex` String.
}

Usage:

import { open } from '@colony/purser-trezor';

const trezorWallet = await open();

const messageSignature = await trezorWallet.verifyMessage({
  message: 'Yes, this is me!',
  signature: '0xa1f7...0b1c'
});