Client Reference

Best Practices

Like web3.js, the Connext client is a collection of libraries that allow you to interact with a local or remote Connext hub over HTTP.

Payment Types

By default, clients make all payments using the PT_OPTIMISTIC payment type. We recommend that you understand the trust assumptions of optimistic payments before implementing the client. Optimistic payments will be phased out completely by the time the network is decentralized.

Payments will automatically be of the type PT_LINK if you provide a secret in the payment metadata but do not provide a payment recipient. Link payments are redeemable “referral” payments which can be unlocked by having the receiver call the redeem() function and supply the secret set by the sender.

For advanced users, you can set payment type directly. For instance, you can make all payments only custodially with PT_CUSTODIAL. Check out the buy() reference

Runtime Flags

Onchain functions such as deposit() and withdraw() use a “two-phase commit” process. First, the user sends the transaction onchain to the contract. Then, upon detecting the transaction, the hub returns a confirmation offchain which reflects the user’s new balances.

It is recommended that implementers use the RuntimeState flags to show the lifecycle of onchain functions to users. This helps users understand where their funds are in the process. The flags also expose transaction hashes which can be shown on etherscan

Documentation

Methods:

State:

getConnextClient

getConnextClient(options: ConnextClientOptions): <ConnextClient>

Retrieve a new instance of the connext client initialized with the provided parameters.

Implementers can provide:

  1. connextProvider, and web3Provider; OR

  2. safeSignHook, web3Provider, and hubUrl; OR

  3. privateKey, and hubUrl; OR

  4. mnemonic, and hubUrl

Parameters:

Name Type Description
options ConnextClientOptions the options to initialize the client with

Returns: ConnextClient

Example:

import { getConnextClient } from `connext`;

const connext = getConnextClient({...})
await connext.start() // start polling

buy

buy(purchase: PurchaseRequest): Promise<object>

Make a purchase (group of related payments) within the channel. Purchases can have meta objects associated with them. These objects are stored as JSONs by the hub.

There are 5 primary types of payments:

  • [PT_CHANNEL] - A payment between channel participants (to or from hub directly)

  • [PT_THREAD] - Noncustodial payments to others who have channels open with the hub. Users must be online to receive these payments. Threads can be thought of as unidirectional, short-lived channels.

  • [PT_CUSTODIAL] - Purely custodial payments through the hub.

  • [PT_LINK] - A payment generated by a secret created by the sender. This payment is only redeemable of the receiver can provide the secret, and is redeemable by anyone. This is a custodial payment.

By default, all payments are made with the PT_OPTIMISTIC type, which utilizes the following flow:

  1. Attempts a PT_CHANNEL payment;

  2. If the above fails, attempts to recollateralize the receiver channel and waits;

  3. Attempts a PT_CHANNEL payment again after 30 seconds;

  4. If the above fails, uses PT_CUSTODIAL instead.

All non-custodial payment types are subject to availablility and collateral requirements.

Parameters:

Name Type Description
purchase PurchaseRequest the PurchaseRequest sent to the hub.

Returns: Promise<{ purchaseId: string }>

Example:

// any information stored in the meta is stored
// by the hub and linked to the purchase made
const meta: MetadataType = {
  sku: "somePurchaseInfo"
}
const amount: Payment = { // in wei units
  wei: "1000",
  tokens: "0",
}
// a group of related payments, e.g. a tip and a fee
// this is the basic structure for each outlined type of payment
const payments: PurchasePaymentRequest[] = [
  {
    recipient: connext.opts.hubAddress,
    amount,
    type: "PT_CHANNEL"
  },
  {
    recipient: "0xsa3g...", // a user that has a channel with the hub
    amount,
    type: "PT_THREAD"
  },
  {
    recipient: "0xgf5s...", // a user who may be offline frequently
    amount,
    type: "PT_CUSTODIAL"
  },
  {
    recipient: emptyAddress, // use "0x000..."
    amount,
    type: "PT_LINK",
    meta: {
      secret: connext.generateSecret()
    }
  },
]

const { purchaseId } = await connext.buy({
  meta,
  payments,
})

It is important to note that while the metadata can be unstructured JSONs for any payments, if using PT_LINK type payments, you MUST include a generated secret in the meta on the payment, not the higher level purchase.


deposit

deposit(payment: Payment): Promise<void>

This method allows users to deposit into their channels.

It generates a ProposePendingDeposit state update, which is cosigned by the hub, and sent to chain by the user.

If there is a problem with the onchain transaction, the client will automatically send an Invalidation update to the hub and revert any pending deposits into their channel.

While users have an onchain transaction in flight, they are not able to make further updates to their state until the transaction is either confirmed onchain, or it is invalidated.

Parameters:

Name Type Description
payment Payment the deposit amount as a Payment(types.html#payment) type

Returns: Promise<void>

Example:

// send a token and eth deposit to the channel
await connext.deposit({
  amountWei: "10000",
  amountToken: "1000",
})
// the connext class is an event emitter. Implementers can
// subscribe to channel state changes via registered listeners

Note: since the user is sending the onchain transaction, there must be enough eth in the signing wallet to afford the gas of the deposit transaction * connext.opts.gasMultiple.


exchange

exchange(toSell: string, currency: “wei” | “token”): Promise<void>

Allows a user to initiate an in-channel exchange with the hub by requesting an exchange and proposing an Exchange update type.

Exchange rates used are supplied by the hub, and verified to be within a reasonable range of the exchange rate in the client’s store before moving forward with the exchange.

If the hub does not have sufficient collateral in the channel for the exchange, the exchange will fail. Unlike failed payments, a failing exchange will not trigger autocollateralization of the channel. By default, the hub should deposit enough to facilitate any in channel exchanges up to the exchange limit set by your hub operator. See the hub configuration section for more details, and contact your hub operator to determine how the exchange limits may affect your application

Parameters:

Name Type Description
toSell string the amount of eth/tokens to sell, in wei units
currency "wei" | "token" can either be "wei" or "token" to specify which type of currency you are selling

Returns: Promise<void>

Example:

// propose a token exchange with the hub
await connext.exchange({
  toSell: "100",
  currency: "token",
})
// propose a wei exchange with the hub
await connext.exchange({
  toSell: "10",
  currency: "wei",
})

Note: Due to rounding errors, you may notice that the amount that is actually exchanged within the channel may not be exactly the requested amount.


recipientNeedsCollateral

recipientNeedsCollateral(recipient: Address, amount: Payment): Promise<string | null>

Returns null if the hub has enough collateral in the recipient’s channel to facilitate a payment, and a descriptive string if it cannot.

Insufficiently collateralized payments will fail, but they will trigger the hub’s autocollateralization mechanism. See more about this in the core concepts section of this documentation.

Implementers can use this function to check the status of a recipient’s collateral, and intentionally send a failing payment to start the autocollateralization, then use this function to monitor the status of that collateralization.

Parameters:

Name Type Description
recipient Address the signing wallet address of the payment recipient
amount Payment the amount of the payment, as a Payment type.

Returns: Promise<string | null>

Example:

// establish payment details
const payment: PurchasePaymentRequest = {
  recipient: "0x87djb...",
  amount: {
    wei: "100",
    token: "0"
  },
  type: "PT_CHANNEL"
}
// check if a payee's channel has sufficient collateral before sending payment
const needsCollateral: string | null = await connext.recipientNeedsCollateral({
  recipient: payment.recipient,
  amount: payment.amount,
})

// if needsCollateral exists, trigger autocollateralization
if (needsCollateral) {
  // is a descriptive string, e.g "Channel does not exist yet"
  console.log(needsCollateral)
  try {
    await connext.buy({
      meta: { msg: "Triggering autocollateral of recipient"},
      payments: [payment]
    })
  } catch (e) {
    console.log("Autocollateral triggered by failing payment for recipient!")
  }
}

// `needsCollateral == null` so recipient does not need collateral in channel
// payment should go through instantly

redeem

redeem(secret: string): Promise<{ purchaseId: string }>

Allows a payee to input a secret (previously generated by the payor) to unlock funds.

Upon submission of the secret, the hub unlocks the funds indicated by the secret and sends them to the user redeeming the secret.

Parameters:

Name Type Description
secret string Hex string generated by connext.generateSecret() created by the payor

Returns: Promise<{ purchaseId: string }>

Example:

// first create a secret as payor and add to payment level metadata
const secret = connext.generateSecret()
const payment = {
  meta: { secret },
  recipient: "0x0000...", // linked payments always use empty addr recipients
  amount: {
    wei: "100",
    token: "0",
  }
}
// make the payment
const payorRes = await connext.buy({
  meta: { msg: "linked payment demo" },
  payments: [ payment ]
})
console.log("payor purchaseId", payorRes.purchaseId)

// redeem a linked payment
const payeeRes = await connext.redeem(secret)
console.log("payee purchaseId", payeeRes.purchaseId)

It is important to note that PT_LINK type payments have no specified recipient and can be redeemed by anyone with the secret. Additionally, for the payee, these are custodial payments and not subject to availability or collateral requirements.


requestCollateral

requestCollateral(): Promise<void>

Request that the hub collateralize a user’s channel.

Hub will deposit tokens and/or ETH to the user’s account in accordance with their configured autodeposit parameters. In order to conserve collateral, some hub operators may impose restrictions on who is allowed to request collateral into their channel to avoid griefing.

Contact your hub operator to find out how their configuration may affect your use case, and learn more about hub configuration parameters here and autocollateralization.

Returns: Promise<void>

Example:

await connext.requestCollateral()
// hub will generate a `ProposePendingDeposit` update, where it deposits into the
// users channel from the contract reserves

// unlike user submitted onchain transactions, or onchain transactions with exchanges
// (as with client withdrawals), hub collateral deposits
// are non-blocking operations, and the state may still be updated.

start

start(): Promise<void>

Starts the stateful portions of the Connext client, including internal pollers.

It is important to note that the client is an EventEmitter, so implementers can subscribe to changes in the client state by registering listeners before starting the connext client.

Returns: Promise<void>

Example:

const connext: ConnextClient = getConnextClient({...})
// register listener
// the only event the client emits is `onStateChange`, which is triggered
// each time the connexts internal store is updated.

connext.on('onStateChange', state => {
  console.log('Connext state changed:', state);
})
await connext.start() // start polling

stop

stop(): Promise<void>

Stops the stateful portions of the Connext client.

Returns: Promise<void>

Example:

await connext.stop() // stops all internal polling
// should be used when cleaning up resources

withdraw

withdraw(withdrawal: WithdrawalParameters): Promise<void>

Withdraw funds from a channel.

Partial withdrawals, full withdrawals, and withdrawals with an onchain exchange (i.e. the hub uses contract reserves instead of channel balance to fund an exchange at withdrawal) are supported by the hub.

Currently, token withdrawals are not supported as the hub is trying to maintain its token collateral.

Parameters:

Name Type Description
withdrawal WithdrawalParameters the WithdrawalParameters sent to the hub.

Returns: Promise<void>

Example:

// first generate the withdrawal parameters
const withdrawal: WithdrawalParameters = {
  withdrawalWeiUser: "0", // wei to withdraw from channel balance
  tokensToSell: "0", // tokens to sell and withdraw as wei
  withdrawalTokenUser: "0", // tokens to withdraw from channel balance
  weiToSell: "0", // wei to sell and withdraw as tokens
  recipient: "0xad33f..." // an outside address to receive funds to. does not need a channel
}

// NOTE: at this time, the hub does NOT support token withdrawals
// this is done to conserve collateral complexity by forcing token
// payments and conserving tokens within the channel system.

// this will be enabled very soon!

await connext.stop() // stops all internal polling
// should be used when cleaning up resources

PersistentState

The client’s persistent state includes things that should persist through independent sessions. It is stored as a redux state with the following properties:

channel: ChannelState the latest double signed channel state

channelUpdate: UpdateRequest the latest channel update

latestValidState: ChannelState the latest channel update without pending operations, used for Invalidation updates

activeThreads: ThreadState[] all open threads in the latest channel state

activeInitialThreadStates: ThreadState[] the initial states of all open threads

threadHistory: ThreadHistoryItem[] an array of objects used to track and generate appropriate threadIDs, keyed by the receiver address

lastThreadUpdateId: number the id of the latest thread update to keep hub in sync

syncControllerState: SyncControllerState includes any updates to sync with the hub


RuntimeState

The client’s runtime state includes things that should not persist through sessions. The flags set here can be used by implementers to restrict user actions at a UI level. The can* flags in the runtime state are set by the middleware.

It is stored as a redux state with the following properties:

awaitingOnchainTransaction: boolean true if either channel member has submitted an onchain transaction

canDeposit: boolean true if user can initiate a deposit

canExchange: boolean true if user can initiate an exchange

canWithdraw: boolean true if user can withdraw from channel

canBuy: boolean true if user can make a purchase

canCollateralize: boolean true if hub is able to collateralize users channel

exchangeRate: ExchangeRateState| null the client’s exchange rates

syncResultsFromHub: SyncResult[] all open threads in the latest channel state

updateRequestTimeout: number default amount of time to wait before invalidating update

channelStatus: ChannelStatus the current status of the channel. Can only advance channel state if the channel status is CS_OPEN. Otherwise, clients can contact hub admins offline to solve the dispute gaslessly, or use the ChannelManager functions with the channelState from the client (latest double signed state).