Skip to main content

Multichain Support

Keystone is now integrated with OKX for the mulit chain support.

Connect with Keystone

For supporting multichain, Keystone defines the new UR type crypto-multi-accounts to expose the public keys. Software can utilize these data to generate the desired addresses for different blockchains. Developers can use the SDK to retrieve and parse this data from the QR Code displayed on the Keystone device.

Here is a sample code snippet to scan the animated QR code and parse the data:

import KeystoneSDK, {UR, URType} from "@keystonehq/keystone-sdk"
import {AnimatedQRScanner} from "@keystonehq/animated-qr"

/**
* Represents a component that handles the scanning of an animated QR code to retrieve
* the crypto hdkey information from a Keystone hardware wallet.
*
* The component uses the `AnimatedQRScanner` from `@keystonehq/animated-qr` to scan the QR code,
* and the `KeystoneSDK` to parse the scanned data into a human-readable account information format.
*/

const Account = () => {

/**
* Callback function to handle successful QR code scans.
*
* @param {Object} data - The data object containing the type and cbor encoded string.
* @param {string} data.type - The type of the scanned data.
* @param {string} data.cbor - The cbor encoded string representing the account information.
*/
const onSucceed = ({type, cbor}) => {
// Parses the crypto multi accounts from the scanned QR code data.
const account = KeystoneSDK.parseMultiAccounts(new UR(Buffer.from(cbor, "hex"), type))
console.log("multiAccounts: ", multiAccounts);
}

/**
* Callback function to handle errors during QR code scanning.
*
* @param {string} errorMessage - The error message describing what went wrong during scanning.
*/
const onError = (errorMessage) => {
console.log("error: ", errorMessage);
}

// Renders the AnimatedQRScanner component with the specified handlers for success and error events.
return <AnimatedQRScanner handleScan={onSucceed} handleError={onError} urTypes={[URType.CryptoMultiAccounts]} />
}

Example of the resulting data:

{
"masterFingerprint": "f23f9fd2",
"keys": [
{
"chain": "BTC",
"path": "m/44'/0'/0'",
"publicKey": "b6...",
"name": "BTC-0",
"chainCode": "",
"extendedPublicKey": "xpub..."
},
{
"chain": "BTC",
"path": "m/49'/0'/0'",
"publicKey": "b6...",
"name": "BTC-01",
"chainCode": "",
"extendedPublicKey": "xpub..."
},
{
"chain": "BTC",
"path": "m/84'/0'/0'",
"publicKey": "b6...",
"name": "BTC-2",
"chainCode": "",
"extendedPublicKey": "xpub..."
},
{
"chain": "ETH",
"path": "m/44'/60'/0'",
"publicKey": "b6...",
"name": "ETH-0",
"chainCode": "",
"extendedPublicKey": "xpub..."
},
{
"chain": "SOL",
"path": "m/44'/501'/0'",
"publicKey": "b6...",
"name": "SOL-0",
"chainCode": "",
"extendedPublicKey": ""
},
{
"chain": "LTC",
"path": "m/49'/2'/0'",
"publicKey": "02629d...",
"name": "LTC-0",
"chainCode": "4d58...",
"extendedPublicKey": "xpub6CAS..."
},
...
],
"device": "Keystone"
}

Here is the type defination of the CryptoMutliAccounts:

interface MultiAccounts {
masterFingerprint: string // A 4 bytes hex string indicates the current mnemonic, e.g. 'f23f9fd2'
keys: Account[] // An array of public keys
device?: string // The device name, e.g. 'Keystone'
deviceId?: string // The device id, e.g. '28475c8d80f6c06bafbe46a7d1750f3fcf2565f7'
deviceVersion?: String // The device firmware version, e.g. '1.0.2'
}

interface Account {
chain: string // The symbol of the coin this key belongs to, e.g. 'SOL'
path: string // The full derivation path of current key
publicKey: string // Public key in hex string
name?: string // The address name in hardware wallet
chainCode: string // The chain code if exist
extendedPublicKey?: string // The bip32 extended public key, e.g. xpub...
note?: string // The note for current account
}

Keystone will provide the master fingerprint and the public keys for different chains, allowing software wallets to select the necessary data to generate the desired addresses.

After connecting with Keystone, software can generate unsigned data and use different UR types by chain to encode the data into QR codes. For detailed information on specific chains, please refer to the documentation for each chain.