RecipesWallets
Wallet setup prerequisites
Before creating a wallet, ensure you have:
- An authenticated user (API or regular user)
- The
@blockstream/ecs-js-sdkpackage configured - Appropriate permissions to create signers and wallets
Signer Creation
All wallet types require a signer. The signer holds the cryptographic keys used for transaction signing.
Signer Locations
| Location | Description |
|---|---|
hosted | Keys managed by the Custody Engine server |
external | Keys managed externally (hardware wallets, etc.) - WIP |
Note: External signers are currently a work in progress. Use
hostedfor production deployments.
Creating a Signer
import { v4 as uuidv4 } from 'uuid'
const signerResult = await broadcastRequest({
action: 'add',
resource: '/signers',
details: {
sid: uuidv4(),
name: 'my_signer',
location: 'hosted',
},
})
const signerId = signerResult.details.sidSigner Creation Parameters
| Field | Type | Required | Description |
|---|---|---|---|
sid | UUID | Yes | Unique identifier for the signer |
name | String | Yes | Human-readable name |
location | String | Yes | Where keys are stored (hosted or external) |
XPUB Derivation
After creating a signer, derive an extended public key (XPUB) for address generation.
What is an XPUB?
An Extended Public Key (XPUB) is a cryptographic construct that allows generating an unlimited number of public keys (and thus addresses) from a single master key, without exposing the private key.
Why XPUBs matter:
- Privacy: Generate a new address for each transaction without key management overhead
- Security: Share the XPUB with watch-only systems that can't spend funds
- Audit: Accountants/auditors can verify all addresses belong to the same wallet
- HD Wallets: Follows BIP-32/BIP-44/BIP-87 hierarchical deterministic standards
Derivation
m / purpose' / coin_type' / account' / change / address_index
87 0 (BTC) 0 0/1 0+
1 (testnet)
1776 (Liquid)const xpubResult = await broadcastRequest({
action: 'add',
resource: `/signers/${signerId}/xpubs`,
details: {
id: uuidv4(),
change: 'receive', // 'receive' or 'change'
},
})
const keyoriginXpub = xpubResult.details.keyorigin_xpubXPUB Derivation Parameters
| Field | Type | Required | Description |
|---|---|---|---|
id | UUID | Yes | Unique identifier for the XPUB |
change | String | Yes | Address type (receive or change) |
Wallet creation
Address Generation
Each wallet type has its own creation flow, but after creating a wallet, generate addresses to receive funds:
const addressResult = await broadcastRequest({
action: 'add',
resource: `/wallets/${walletId}/addresses`,
details: {
type: 'receive', // 'receive' or 'change'
index: 1, // Address index (increment for new addresses)
},
})
const address = addressResult.details.addressAddress Parameters
| Field | Type | Required | Description |
|---|---|---|---|
type | String | Yes | Address type (receive or change) |
index | Number | Yes | Derivation index (use sequential numbers) |