# /docs/sdk

import RunExample from '@/components/RunExample'

# SDK

`keepkey-vault-sdk` is a typed TypeScript client for the KeepKey REST API. Zero dependencies, native `fetch`, works in browser, Node, Bun, and edge runtimes.

- **npm:** [`keepkey-vault-sdk`](https://www.npmjs.com/package/keepkey-vault-sdk)
- **Full API reference:** [/docs/reference/api](/docs/reference/api) (auto-generated from the source)

## API surface

Every method is grouped by domain on the `KeepKeySdk` instance:

| Namespace       | What it does                                                        |
|-----------------|---------------------------------------------------------------------|
| `sdk.system`    | Device info, health, PIN management, initialization, firmware      |
| `sdk.address`   | Derive addresses (BTC, ETH, Cosmos, Osmosis, Solana, XRP, TRON, …) |
| `sdk.eth`       | Ethereum signing — tx, message, EIP-712 typed data                 |
| `sdk.btc`       | Bitcoin / UTXO transaction signing                                  |
| `sdk.cosmos`    | Cosmos Hub amino signing — transfer, staking, IBC                  |
| `sdk.osmosis`   | Osmosis amino signing — transfer, staking, IBC, LP, swap           |
| `sdk.thorchain` | THORChain transfer and deposit                                      |
| `sdk.mayachain` | MAYAChain transfer and deposit                                      |
| `sdk.ripple`    | XRP transaction signing                                             |
| `sdk.binance`   | BNB Beacon Chain signing                                            |
| `sdk.solana`    | Solana transaction signing (incl. SPL tokens)                      |
| `sdk.tron`      | TRON signing (incl. TRC-20)                                         |
| `sdk.ton`       | TON signing (incl. Jettons)                                         |
| `sdk.xpub`      | Extended public key derivation — single and batch                  |
| `sdk.chain`     | Portfolio balances, market info, UTXOs, tx history, swap quotes    |
| `sdk.sweep`     | Recover BTC from non-standard derivation paths                      |

## Creating an instance

```ts
import { KeepKeySdk } from 'keepkey-vault-sdk'

const sdk = await KeepKeySdk.create({
  apiKey: process.env.KEEPKEY_API_KEY, // optional — if omitted, triggers pairing
  serviceName: 'My App',
  serviceImageUrl: 'https://example.com/icon.png',
  baseUrl: 'http://localhost:1646', // default — override if running on a custom port
})
```

`create()` verifies the REST API is reachable, validates the supplied `apiKey` (or initiates pairing), and returns a connected instance. It throws `SdkError` if the desktop application isn't running.

## Deriving addresses

Every chain has a `get{Chain}Address` method that takes a BIP32 path. Pass `show_display: true` to make the device show the address on-screen so the user can verify it before use.

<RunExample id="get-btc-address" />

<RunExample id="get-cosmos-address" />

## Batch public key derivation

When deriving many addresses at once (e.g. for a portfolio view), use the batch endpoint. The server caches results, so repeated calls for the same path are fast.

```ts
const { pubkeys } = await sdk.xpub.getPublicKeys([
  { address_n: [0x80000054, 0x80000000, 0x80000000], coin: 'Bitcoin', script_type: 'p2wpkh' },
  { address_n: [0x8000002C, 0x8000003C, 0x80000000], coin: 'Ethereum', type: 'address' },
  { address_n: [0x8000002C, 0x80000076, 0x80000000], coin: 'Cosmos' },
])
```

## Signing a transaction

Every signing call blocks until the user approves on the device. The default timeout is 10 minutes.

### Ethereum (EIP-1559)

```ts
const signed = await sdk.eth.ethSignTransaction({
  addressNList: [0x8000002C, 0x8000003C, 0x80000000, 0, 0],
  to: '0x...',
  value: '0x2386f26fc10000', // 0.01 ETH in wei
  data: '0x',
  chainId: 1,
  nonce: '0x0',
  gasLimit: '0x5208',
  maxFeePerGas: '0x2540be400',
  maxPriorityFeePerGas: '0x3b9aca00',
})

// Broadcast signed.serializedTx via your own RPC provider
```

### Bitcoin

Bitcoin (and other UTXO chains) require you to supply the full set of inputs and outputs. Each input needs the previous transaction it spends from — you fetch that from a block explorer or indexer.

#### Get a Bitcoin address

BIP44 derivation paths are encoded as `address_n` — an array of 32-bit integers with the hardened bit set on the first three levels.

```ts
// BIP44 path: m/44'/0'/0'/0/0 — first legacy Bitcoin address
const { address } = await sdk.address.utxoGetAddress({
  address_n: [
    0x80000000 + 44,  // BIP44 purpose (legacy)
    0x80000000 + 0,   // Coin type: Bitcoin
    0x80000000 + 0,   // Account 0
    0,                // External chain
    0,                // Address index 0
  ],
  coin: 'Bitcoin',
  script_type: 'p2pkh',  // legacy
  show_display: true,    // verify on device before using
})
```

#### Script types

Script type maps to address format:

| `script_type` | Format | Example path |
|---------------|--------|--------------|
| `p2pkh`       | Legacy (1…)        | `m/44'/0'/0'/0/0` |
| `p2sh`        | Nested SegWit (3…) | `m/49'/0'/0'/0/0` |
| `p2wpkh`      | Native SegWit (bc1…) | `m/84'/0'/0'/0/0` |

Default to `p2wpkh` unless you have a reason not to. Taproot (`m/86'`) is supported by the
firmware but is not exposed by default — see [Bitcoin Address Types](/docs/learn/address-types)
for the compatibility reasoning, and [Supported Chains](/docs/firmware/supported-chains) for
firmware-level support.

#### Sign a Bitcoin transaction

```ts
// Inputs describe what you're spending. Each input references a previous tx
// by txid + vout index, and must include the full previous transaction so
// the device can verify the input amount.
const inputs = [
  {
    addressNList: [0x80000000 + 44, 0x80000000 + 0, 0x80000000 + 0, 0, 0],
    scriptType: 'p2pkh',
    amount: '390000',  // amount of this input, in satoshis
    vout: 0,
    txid: 'd5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882',
    tx: prevTx,  // the full previous transaction object, fetched from an indexer
  },
]

// Outputs describe where the funds are going.
const outputs = [
  {
    address: '1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1',
    addressType: 'spend',
    amount: '380000',  // 390_000 input - 10_000 fee
    isChange: false,
  },
]

const signed = await sdk.btc.btcSignTransaction({
  coin: 'Bitcoin',
  inputs,
  outputs,
  version: 1,
  locktime: 0,
})

// signed.serializedTx is the hex-encoded transaction, ready to broadcast
```

The same flow works for other UTXO chains — set `coin` to `'Litecoin'`, `'Dogecoin'`, `'BitcoinCash'`, etc., and use the matching coin type and script type.

## Error handling

The SDK throws `SdkError` with an HTTP status code for REST errors:

```ts
import { KeepKeySdk, SdkError } from 'keepkey-vault-sdk'

try {
  const sdk = await KeepKeySdk.create({ serviceName: 'My App' })
} catch (e) {
  if (e instanceof SdkError) {
    if (e.status === 503) {
      console.error('Desktop application is not running')
    } else if (e.status === 401) {
      console.error('Pairing was rejected')
    }
  }
  throw e
}
```

Common status codes:

| Status | Meaning |
|--------|---------|
| `200`  | Success |
| `401`  | Missing, invalid, or revoked API key |
| `403`  | User rejected the signing request on the device |
| `408`  | Signing request timed out (device didn't respond within 10 min) |
| `503`  | Desktop application not reachable |
