Skip to main content

Using the SDK

Just show me the code, Schneebly

  • The sdk-minimal-demo has examples of the minimal setup required to use the SDK.
  • The sdk-playground is a simple single-process web app where you can play with the SDK right in your browser.

And actually, it's Schnay-blay.

Single vs Multi-process

@exodus/headless, a.k.a. "The SDK", is designed to work in both types of environments. There are two main logical pieces: the API side and the UI side. In single-process apps, e.g. a vanilla React Native app, both will live together in one process. In multi-process environments, e.g. a browser extension, a website with web-workers, an Electron app, Node.js, etc., you may choose to separate the two for performance or even just for architectural clarity. Of course, when you separate them, you'll need a transport and RPC layer.

sdk-minimal-demo has both single-process and multi-process examples. Zoom into some of the pieces below.

Setup: the API side

We're not there yet but we want to get to very lightweight initialization code, e.g.:

import createExodus from '@exodus/headless'
import adapters from '@exodus/adapters-web' // doesn't exist yet

const exodus = createExodus({ adapters })

In the meantime, you'll have to do a bit more wiring:

Choose your platform

The SDK is designed to be platform-agnostic and thus must accept a number of platform-specific adapters for storage, network, build metadata, a port for connecting to the UI side, etc. The runtime environment dependent ones will soon be prepackaged as @exodus/adapters-web, @exodus/adapters-mobile, etc. for convenience, but the app-specific ones you'll always have to inject yourself, e.g. the asset plugins (@exodus/bitcoin-plugin, @exodus/ethereum-plugin, etc).

See the sdk-playground for (roughly) what will soon be packaged as @exodus/adapters-web

Choose your features

@exodus/headless ships with core features built in. You can plug in additional features similarly to how you'd add middleware to express:

import createExodus from '@exodus/headless'

const sdkBuilder = createExodus({ adapters, config })
sdkBuilder.use(myFeature())
// locks down the feature set and resolves the dependency graph. You can't call `use()` after this
const exodus = sdkBuilder.resolve()

Further reading: see the core features bundled into headless, and the features available for you to plug into it.

Configure your features

Many features in the SDK are configurable. Most will soon ship with sensible defaults, towards a zero-conf-by-default experience.

In the meantime, you'll need to supply a config object to headless:

import createExodus from '@exodus/headless'

const config = {
// ...
[featureId]: featureConfig,
}

const exodus = createExodus({ adapters, config }).resolve()

Connect the UI

The exodus instance of @exodus/headless you constructed on the the API does two things: provides an API to feature-specific functionality and emits events for state changes.

In single-process apps, you will use that instance directly from the UI. In multi-process apps, you'll need a transport layer.

API

These are all the APIs provided by 'api' nodes in the SDK. See a usage example below and many others in https://github.com/ExodusOSS/hydra/tree/master/sdks/headless/:

await exodus.application.start()
await exodus.application.create({ passphrase })
await exodus.wallet.exists() // true
await exodus.addressProvider.getAddress({
purpose: 44,
assetName: 'bitcoin',
walletAccount: WalletAccount.DEFAULT_NAME,
chainIndex: 0,
addressIndex: 0,
})

See the full APIs for the above features:

Events

The SDK emits events you can subscribe to. These come from various domain-specific plugins, e.g. walletAccounts, apyRates, etc.

exodus.subscribe(console.log) // e.g. { type: 'activeWalletAccount', payload: 'exodus_0' }

On the UI side, Exodus provides helpers to copy events into redux state, namespaced per feature. In addition, most features ship with a number of selectors. With @exodus/headless/redux the setup is reduced to a few lines of code.

Once you have that selectors export, you can connect it to any component:

import { selectors } from '~/ui/flux'

const MyComponent = () => {
// selector definition https://github.com/ExodusOSS/hydra/tree/master/features/fiat-balances/redux/selectors/by-wallet-account.js
const balances = useSelector(selectors.fiatBalances.byWalletAccount)
// ...
}