Skip to main content

Keys module

The keys module of Joystream SDK facilitates the management of keys and integrations with external signers.

Key features

  • simplifies WalletConnect integration,
  • uses @polkadot/keyring internally to manage the set of available keys,
  • provides a unified interface to access all available keys, regardless of their source (whether they are directly added to the Keyring, provided by WalletConnect or via other extensions)
  • environment agnositc, works both in the browser and Node.js environments.

KeyManager class

KeyManager is main class provided by the keys module. Creating a new instance of KeyManager is extemely simple:

import { KeyManager } from '@joystream/sdk-core/keys'

const keyManager = new KeyManager()
// Optionally, if you didn't call cryptoWaitReady() before:
await keyManager.ready()

You can also override the default Keyring configuration if you need:

const keyManager = new KeyManager({
keyringOptions: {
isDev: true, // Will import all dev accounts like //Alice, //Bob etc.
type: 'sr25519', // The default key type will be 'sr25519'
// ...
},
})

Adding keys directly

You can add new keys directly to KeyManager, similarly to how you would add them to a Keyring instance:

// Add from mnemonic
keyManager.addKey({
mnemonic:
'bottom drive obey lake curtain smoke basket hold race lonely fit walk',
type: 'sr25519', // Would use the default type if not provided
meta: { name: 'Dev' }, // You can optionally add some metadata
})

// Add from SURI
keyManager.addKey({
suri: '//Alice',
// ...optionally other options can be provided as above
})

// Add from seed:
keyManager.addKey({
seed: '0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a',
// ...optionally other options can be provided as above
})

Using external providers

KeyManager allow you to add external key provides as long as they match the following interface:

interface KeyProvider {
signer?: Signer
getAccounts(): Promise<{ address: string }[]>
subscribeAccounts(cb: (keys: KeyInfo[] | undefined) => void): unknown
}

interface KeyInfo {
address: string
type?: KeyType
name?: string
}

This interface is compatible with some of the most popular packages for connecting wallets, such as:

It's also combatible with the WalletConnect class that you can import from @joystream/sdk-core/keys/integrations/wallet-connect (see WalletConnect integration).

To add a key provider which matches this interface to a KeyManager you can simply call:

keyManager.addKeysProvider(PROVIDER_NAME, PROVIDER)

See WalletConnect integration for a more concrete example.

Retrieving keys

To retrieve all available keys from the KeyManager you can use one of the following methods:

// Retrieve keys once:
const keys = keyManager.keys

// Subscribe keys:
const unsubscribe = keyManager.subscribeKeys((keys) => {
/* Do something with the keys */
})

The returned keys will match the following interface:

interface Key {
// Name of the provider specified during `.addKeysProvider`
// or 'internal' if the key was added directly to the Keyring
provider: string

// SS58 address of the key (uses the Joystream network prefix by default)
address: string

// Type of the key (if specified)
type?: 'ed25519' | 'sr25519'

// meta.name if specified
name?: string
}

WalletConnect integration

@joystream/sdk-core/keys provides a WalletConnect class to allow very easy integration with Wallet Connect. See the minimal example below:

import { KeyManager } from '@joystream/sdk-core/keys'
import { UxHandler } from '@joystream/sdk-core/keys/integrations/wallet-connect/ux'
import { WalletConnect } from '@joystream/sdk-core/keys/integrations/wallet-connect'

const keyManager = new KeyManager()
await keyManager.ready()

// Specify the actions to take on connection request
// and (optionally) when the connection process is finalized.
const wxUxHandler: UxHandler = {
requestConnect: async (uri: string) => {
/* Show a QR code or allow the user to copy the WalletConnect uri manually */
},
onFinalized: async (uri: string) => {
/* For example: close the WalletConnect modal */
},
}

const walletConnect = new WalletConnect(
{
projectId: process.env.PROJECT_ID, // You must provide a valid PROJECT_ID here!
relayUrl: 'wss://relay.walletconnect.com',
},
wxUxHandler
)

await walletConnect.connect()
await keyManager.addKeysProvider('WalletConnect', walletConnect)

console.log(keyManager.keys)

For more concrete examples, see Example apps below.

Example apps

React

The example React app which uses @joystream/sdk-core/keys module can be found in /examples/keys-react.

To run the example locally you can execute the following steps:

git clone https://github.com/Joystream/sdk.git joystream-sdk cd joystream-sdk git checkout dev yarn cd examples/keys-react yarn start

You should see a simple UI like this:

React example UI

The example React app allows you to add keys using 3 different ways:

  • using Talisman Connect, which supports most popular browser extensions / injected wallets, such as:
    • Talisman
    • SubWallet
    • Nova Wallet
    • Polkadot.js
    • etc. (see full list here)
  • using WalletConnect, which supports:
    • Mobile / Desktop wallets such as:
      • Subwallet
      • Nova Wallet
    • Tangem hardware wallet
    • etc. (see full list here)
  • direcly to Keyring from:
    • mnemonic
    • seed
    • SURI

You can verify the signing process by signing an example message using the Sign button:

React example signing

CLI

The example CLI app which uses @joystream/sdk-core/keys module can be found in /examples/keys-cli.

To run the example locally you can execute the following steps:

git clone https://github.com/Joystream/sdk.git joystream-sdk cd joystream-sdk git checkout dev yarn yarn run-example keys-cli