SDK Implementation Guide

Table of Contents


Installation & Setup

Install the Package

Platform Requirements

  • Node.js: Version 20 or higher

  • Browser: Modern browsers with WebAssembly support (Chrome, Firefox, Safari, Edge)

  • Electron: Version 20 or higher (for desktop applications)

  • TypeScript: Optional but recommended

Browser Setup: WASM Files

For browser environments, you need to serve the WASM files from your public directory:

  1. Copy WASM files to your public directory:

  2. The SDK will automatically load these files from the root path (/)

Basic Initialization

The SDK automatically uses the appropriate storage for your platform:

  • Node.js: FileStorage (stores in ~/.vultisig by default)

  • Browser: BrowserStorage (uses IndexedDB with localStorage fallback)

  • Electron: FileStorage (same as Node.js, shared with CLI)

Custom Storage (optional):


Quick Start Tutorial

Here's a complete example showing vault creation, address derivation, and balance checking with password management:


Core Concepts

Vault Types

The SDK supports two types of vaults:

  • FastVault: 2-of-2 MPC with VultiServer assistance. Always encrypted with password. Best for quick setup and individual use.

  • SecureVault: Multi-device N-of-M MPC with configurable thresholds. Optionally encrypted. Best for maximum security, teams, and multi-device scenarios.

Feature
FastVault
SecureVault

Threshold

2-of-2 (fixed)

N-of-M (configurable)

Setup

Server-assisted, instant

Multi-device, requires QR pairing

Signing

Instant via VultiServer

Requires device coordination

Password

Required

Optional

Use Cases

Personal wallets, development

Team wallets, high security, custody

Supported Chains

The SDK supports 36 blockchains across multiple ecosystems:

  • EVM (13): Ethereum, Polygon, BSC, Arbitrum, Optimism, Base, Avalanche, Blast, Cronos, ZkSync, Hyperliquid, Mantle, Sei

  • UTXO (6): Bitcoin, Litecoin, Dogecoin, Bitcoin Cash, Dash, Zcash

  • Cosmos (10): Cosmos Hub, THORChain, MayaChain, Osmosis, Dydx, Kujira, Terra, Terra Classic, Noble, Akash

  • Other (7): Solana, Polkadot, Sui, TON, Ripple, Tron, Cardano

See the Quick Reference section for the complete list.

Storage Layer

The SDK uses platform-appropriate storage by default:

  • Node.js: FileStorage - Stores vaults in ~/.vultisig directory

  • Browser: BrowserStorage - Uses IndexedDB with localStorage fallback

  • Electron: FileStorage - Same as Node.js (vaults shared with CLI)

  • Fallback: MemoryStorage - In-memory only (data lost on restart)

For custom persistence, implement the Storage interface:

Stateless Usage

For scenarios where you don't need persistent storage—such as one-off operations, testing, or serverless functions—use MemoryStorage to create ephemeral vault instances:

Use cases for stateless usage:

  • One-off signing: Sign a transaction without persisting vault state

  • Address derivation: Generate addresses without storing vault data

  • Testing: Unit and integration tests without filesystem side effects

  • Serverless functions: Lambda/Cloud Functions that load vault per-request

  • CLI tools: Command-line utilities that operate on vault files

What works in stateless mode:

  • ✅ Address derivation

  • ✅ Balance checking

  • ✅ Transaction signing (FastVault)

  • ✅ Gas estimation

  • ✅ Swap quotes and execution

  • ✅ Token/chain management (in-memory only)

What doesn't persist:

  • ❌ Vault preferences (chains, tokens, currency)

  • ❌ Cached balances/addresses (recreated each session)

  • ❌ Password cache (must provide password each time)

Note: The vault file (.vult) itself is never modified by the SDK—it's read-only. Persistence is about SDK metadata and cached data, not the vault file contents.


Password Management

Password management is a critical aspect of the SDK. FastVaults are always encrypted, and proper password handling ensures both security and good user experience.

When Passwords Are Required

  • FastVault: Always encrypted, password required for all operations

  • SecureVault: Optional encryption, password only required if encrypted

  • Import: Password required if the vault file is encrypted

  • Export: Password optional, encrypts the backup file

Setting Up Password Callback

Configure a password callback when creating your SDK instance to automatically prompt users when needed:

Browser Example (with Modal)

Node.js Example (Command Line)

Retrieve from Secure Storage

Password Caching

Cache passwords to avoid repeated prompts during a session:

Common TTL configurations:

Manual Lock/Unlock

Control password cache manually for sensitive operations:

Example: Auto-lock on Inactivity

Checking Encryption Status

Before importing a vault, check if it requires a password:

Export with Password

Create encrypted backups with a password (can be different from vault password):

Password Security Best Practices

  1. Never store passwords in plain text

  2. Use password caching with reasonable TTLs (5-15 minutes recommended)

  3. Lock vaults after sensitive operations

  4. Use different passwords for backups

  5. Implement auto-lock on inactivity

  6. Clear password cache on logout

  7. Use secure password input (type="password" in forms)


Vault Management

Creating Fast Vaults

Create a new vault with server assistance:

Important: Verification Flow

Fast vaults require email verification. The vault is only returned after successful verification:

  1. createFastVault() generates keys and returns the vaultId

  2. The vault exists in memory but is not returned or persisted

  3. User calls verifyVault(vaultId, code) with the email verification code

  4. On success, the vault is saved to storage, set as active, and returned

If the process is killed before verification completes, the vault is lost. This is intentional - unverified vaults cannot be used for signing anyway. The user simply needs to call createFastVault() again to restart the process.

Creating Secure Vaults

Secure vaults use multi-device MPC with configurable N-of-M thresholds. Creation requires coordination with other devices running the Vultisig mobile app.

Creation Flow:

  1. createSecureVault() generates session parameters and a QR payload

  2. onQRCodeReady callback receives the QR data - display this for other devices

  3. Other participants scan the QR with the Vultisig mobile app (iOS/Android)

  4. onDeviceJoined fires as each device joins the session

  5. Once all devices join, MPC keygen runs automatically (DKLS for ECDSA, Schnorr for EdDSA)

  6. The vault is created and saved, then returned

Threshold Configuration:

The threshold determines how many devices must participate in signing:

Devices
Default Threshold
Can Sign With

2

2

Both devices

3

2

Any 2 of 3

4

3

Any 3 of 4

5

4

Any 4 of 5

Formula: threshold = Math.ceil((devices * 2) / 3)

Cancellation Support:

Signing with Secure Vault

Signing with a secure vault requires coordination with other devices. The threshold number of devices must participate.

Signing Flow:

  1. Call vault.sign() with transaction payload and callbacks

  2. onQRCodeReady fires with QR data - display for other participants

  3. Other devices scan QR and approve the transaction in the Vultisig app

  4. onDeviceJoined fires as devices join the signing session

  5. Once threshold is reached, MPC signing runs automatically

  6. Signature is returned and can be broadcast

Signing Arbitrary Bytes with Secure Vault:

Timeout Behavior:

Device coordination has a 5-minute timeout by default. If threshold devices don't join within this window, the signing operation fails.

Importing Vaults

Import an existing vault from a .vult backup file:

Exporting Vaults

Create a backup of your vault:

Listing Vaults

Get all stored vaults:

Switching Vaults

Set the active vault:

Deleting Vaults

Remove a vault from storage:

Renaming Vaults


Creating Vaults from Seedphrase

Import existing wallets from BIP39 mnemonic phrases (12 or 24 words). This allows migrating wallets from other applications into Vultisig.

Validating a Seedphrase

Always validate the mnemonic before attempting import. The SDK supports all 10 BIP39 languages with automatic language detection:

  • English, Japanese, Korean, Spanish, Chinese (Simplified/Traditional), French, Italian, Czech, Portuguese

You can also specify a language explicitly for stricter validation:

Discovering Chains with Balances

Before importing, you can scan chains to find existing balances:

Progress Phases:

  • validating - Validating the mnemonic

  • deriving - Deriving addresses for each chain

  • fetching - Fetching balances from blockchain

  • complete - Discovery finished

Creating a FastVault from Seedphrase

Import a seedphrase with VultiServer assistance (2-of-2 threshold):

Creating a SecureVault from Seedphrase

Import a seedphrase with multi-device MPC (N-of-M threshold):

Joining a SecureVault Session (Programmatic Multi-Device)

Use joinSecureVault() to programmatically join an existing vault creation session from another SDK instance. This enables multi-device coordination without QR code scanning.

Example 1: Joining a fresh keygen session

Example 2: Joining a seedphrase-based session

Auto-detection: The joinSecureVault() method automatically detects whether the session is a fresh keygen or seedphrase-based from the QR payload's libType field. For seedphrase sessions, the mnemonic option is required and must match the initiator's mnemonic.

Creation Flow Comparison

Feature
FastVault from Seedphrase
SecureVault from Seedphrase

Method

createFastVaultFromSeedphrase()

createSecureVaultFromSeedphrase()

Threshold

2-of-2 (with VultiServer)

N-of-M (configurable)

Verification

Email code required

Device pairing via QR or joinSecureVault()

Password

Required

Optional

Signing

Instant

Requires device coordination

Joiner Method

N/A (server auto-joins)

joinSecureVault()

Security Considerations

  1. Memory Safety: The SDK clears mnemonic from memory after derivation

  2. No Logging: Mnemonics are never logged or persisted

  3. HTTPS Only: All server communication is encrypted

  4. Input Validation: Always validate before import to catch typos


Essential Operations

Address Derivation

Get addresses for different blockchains:

Addresses are cached automatically for performance.

Balance Checking

Check balances for your assets:

Preparing & Sending Transactions

Send transactions on any supported chain:

Gas Estimation

Get gas information for transactions:

Signing Arbitrary Bytes

The signBytes() method allows you to sign pre-hashed data directly, giving you full control over transaction construction. This is useful when you need to:

  • Sign transactions built with external libraries (ethers.js, viem, bitcoinjs-lib, etc.)

  • Implement custom signing flows not covered by prepareSendTx()

  • Sign arbitrary messages for authentication or verification

Input Formats:

Chain Parameter:

The chain parameter determines the signing algorithm and derivation path:

  • ECDSA chains (Ethereum, Bitcoin, Polygon, etc.): Uses secp256k1, returns { signature, recovery }

  • EdDSA chains (Solana, Sui): Uses Ed25519, returns { signature }

Complete Example: Custom EVM Transaction

Complete Example: Bitcoin Transaction with bitcoinjs-lib

Return Type:

Note: signBytes() is available for both FastVault and SecureVault. For SecureVault, provide signing options with callbacks for device coordination.

Broadcasting Raw Transactions

The broadcastRawTx() method broadcasts pre-signed raw transactions to the blockchain network. Use this with signBytes() for custom transaction workflows.

Supported Input Formats:

Chain Family
Input Format

EVM (Ethereum, Polygon, BSC, etc.)

Hex-encoded signed tx (with/without 0x)

UTXO (Bitcoin, Litecoin, etc.)

Hex-encoded raw tx

Solana

Base58 or Base64 encoded tx bytes

Cosmos (Cosmos, Osmosis, THORChain, etc.)

JSON {tx_bytes} or raw base64 protobuf

TON

BOC (Bag of Cells) as base64 string

Polkadot

Hex-encoded extrinsic

Ripple

Hex-encoded tx blob

Sui

JSON {unsignedTx, signature}

Tron

JSON tx object

Error Handling:

The method throws VaultError with these codes:

  • BroadcastFailed - Transaction failed to broadcast (may include "already submitted" errors)

  • UnsupportedChain - Chain not yet supported for raw broadcast

Cosmos Signing (SignAmino & SignDirect)

For Cosmos SDK chains (Cosmos, Osmosis, THORChain, MayaChain, Dydx, Kujira, etc.), the SDK provides two signing methods that give you full control over transaction construction:

  • SignAmino: Legacy JSON/Amino format, widely supported

  • SignDirect: Modern Protobuf format, more efficient

SignAmino Example (Governance Vote)

SignAmino with Multiple Messages

SignDirect Example (Pre-encoded Transaction)

Use SignDirect when you have pre-encoded Protobuf transaction bytes:

Supported Cosmos Chains

Chain
Chain ID
Native Denom

Cosmos

cosmoshub-4

uatom

Osmosis

osmosis-1

uosmo

THORChain

thorchain-1

rune

MayaChain

mayachain-1

cacao

Dydx

dydx-mainnet-1

adydx

Kujira

kaiyo-1

ukuji

Terra

phoenix-1

uluna

TerraClassic

columbus-5

uluna

Noble

noble-1

uusdc

Akash

akashnet-2

uakt

Common Message Types


Token Management

Add and manage custom tokens:

Chain Management

Manage which chains are active for the vault:

Portfolio Value

Get total portfolio value in fiat:


Token Swaps

The SDK supports token swaps across multiple chains and protocols, including cross-chain swaps via THORChain and same-chain DEX aggregation via 1inch.

Supported Swap Routes

Route Type
Provider
Example

Cross-chain (BTC, ETH, Cosmos)

THORChain

BTC → ETH, ETH → ATOM

Same-chain EVM

1inch

ETH → USDC on Ethereum

Cross-chain EVM

LiFi

Polygon → Arbitrum

Checking Swap Support

Getting a Swap Quote

Get a quote before executing a swap:

Swapping with ERC-20 Tokens

For ERC-20 tokens, specify the token contract address:

Executing a Swap

Complete swap flow with signing and broadcasting:

Checking Token Allowance

Check if ERC-20 approval is needed before swapping:

Swap Events

Subscribe to swap-related events:

Error Handling

Handle common swap errors gracefully:


Configuration

SDK Instance Configuration

All configuration is passed to the Vultisig constructor. The SDK uses instance-scoped configuration (no global state):

Multiple SDK Instances

You can create multiple isolated SDK instances, each with its own storage and configuration:

Custom Storage Implementation

Implement the Storage interface for custom persistence:


Caching System

The SDK uses a multi-level caching system for optimal performance:

Address Caching

Addresses are cached indefinitely by default (they never change):

Addresses are cached permanently (they never change for a vault) and persisted to storage.

Balance Caching

Balances are cached to avoid excessive API calls:

Configure cache TTLs:

Password Caching

Passwords are cached to avoid repeated prompts (see Password Management):

Portfolio Value

Total portfolio value is calculated from cached balances and prices:

Cache Invalidation

Caches are automatically invalidated when:

  • Balance updated from transaction

  • Token added/removed

  • Chain added/removed

  • Currency changed

Manual cache clearing:


Event System

Subscribe to vault events for reactive UIs:

Available Events

Event Patterns

React Example:

Unsubscribe from Events:


Quick Reference

Vultisig Class Methods

VaultBase Methods

Vault Creation Methods

Fast vaults and secure vaults are created through the Vultisig class:

Supported Chains

Common Configuration Options

Cosmos Signing Types

Seedphrase & Vault Creation Types


Platform Notes

Browser

WASM Files: Must be served from the root path:

IndexedDB Storage: For persistent storage, use IndexedDB (see examples/browserarrow-up-right for implementation).

Import:

Security Considerations:

  • Use type="password" for password inputs

  • Consider using Web Crypto API for sensitive data

  • Implement Content Security Policy (CSP)

Node.js

Import:

Custom Storage: For custom persistence needs, implement the Storage interface (see Custom Storage Implementation for a full example).

Password Input: Use libraries like inquirer or prompts for CLI password input.

React Native

Status: Coming soon

Electron

The SDK supports Electron desktop applications. The SDK runs in the main process and uses FileStorage (~/.vultisig), which means vaults are shared with the CLI tool.

Architecture:

Main Process Setup:

Preload Script:

Renderer (UI):

Shared Vaults with CLI:

Because both Electron and CLI use FileStorage with ~/.vultisig:

WASM Files:

Include WASM files in your Electron build:

Security Best Practices:

  • Always use contextIsolation: true (Electron default)

  • Never use nodeIntegration: true in renderer

  • Keep all vault operations in main process

  • Only expose necessary operations via IPC


Additional Resources


Questions or feedback? Open an issue on GitHub or check the example projects for more detailed implementations.

Last updated

Was this helpful?