Wallet Integrations

The Connext client assumes that it runs in a trusted environment because it needs to control the ability to automatically sign messages and transactions on behalf of a user. To ensure that user funds remain secure, it is recommended that implementers carefully read through all of the following sections:

Client Options

Instantiating the client requires providing the following:

Name Type Description
rpcProviderUrl String the Web3 provider URL used by the client
nodeUrl String url of the node
mnemonic String (optional) Mnemonic of the signing wallet
store object Maps to set/get from CF
logLevel? number Depth of logging
natsUrl? String Initially hardcoded
natsClusterId? String Initially hardcoded
natsToken? String Initially hardcoded

Compatibility and React Native

At the moment, the Connext client - including the core protocol execution engine - is implemented only in Typescript. Other implementations are on the roadmap (we would love your help in building them!). The remainder of these docs will assume that the client is either being implemented in a TS/JS server-side environment or in React Native.

TODO Coming soon: React Native tips and setup guide.

Managing Mnemonics and the KeyGen Function

Connext is opinionated in that all channels are associated with a BIP32 mnemonic, xpriv, or HDWallet rather than a simple private key. This is done as part of the core protocols in order to protect against replay attacks on the channel’s state. When making updates to the state, the protocol generates a new ephemeral key for each interaction, where the generated key is the nth key along a custom state-channel-specific path.

const CF_PATH = "m/44'/60'/0'/25446";

This has a couple of consequences:

First, wallets will need to create and safely store a mnemonic, xpriv, or HDWallet for the user - even if they are building on contract wallet infrastructure that uses randomized keys. The mnemonic itself can be completely channel-specific and, because channels can be disputed if the mnemonic is lost, should still be able to conform to existing contract wallet recovery patterns.

Second, wallets should consider how they wish to expose the client to the mnemonic. For simplicity, it is possible to pass in the mnemonic directly into the client. However, this is an unsafe pattern and should not be used in production, particularly if the user’s funds are also tied to the same mnemonic.

Ideally, the master key is hosted outside of the client. The wallet can then derive the xpub associated with the mnemonic,

const hdWallet = fromExtendedKey(fromMnemonic(mnemonic).extendedKey).derivePath(CF_PATH);
const xpub = hdNode.neuter().extendedKey;

And then pass it in along with a wrapper function to derive ephemeral keys as needed:

  keyGen: function(index) => {
    return Promise.resolve(hdNode.derivePath(index).privateKey);
  }

Creating a Store

Channels move state storage completely offchain to the end user’s device. This means that the security of a user’s state is tied to a user’s funds.

To implement the client, wallets will need to create a secure persistent storage and then pass in a wrapper that maps to it. The storage wrapper interface looks like the following:

store = {
  get(path: string): Promise<any>;
  set(
    pairs: { path: string; value: any }[],
    allowDelete?: Boolean
  ): Promise<void>;
  reset?(): Promise<void>;
}

In addition to device local storage, it is recommended that wallets back up user state data to remote stores. This can be done simply as an additional step as part of the set() function. You can follow the same method to make backups to Watchtower/dispute resolution services such as Pisa, or to web3 storage systems like 3Box.

reset(), while optional can be used to trigger a manual reset of the user’s local store from a cloud backup in the unlikely case that their channel reaches a broken state. For lost devices or deleted state, wallets can go through their normal key recovery process, copy their cloud store backup to the user’s (new) device, and then pass in the store as normal.

We strongly recommend that wallets do not try to manually edit channel stores. Even small changes in stores can lead to broken channels and unrecoverable funds.