githubEdit

CBTC Quick Start

⚠️ API Disclaimer. CBTC APIs have no formal versioning policy today. All endpoints and library interfaces described in this guide are subject to change. Breaking changes are communicated via #cbtc-ecosystem and the changelog. This disclaimer will be updated once a formal versioning and stability policy is established.

This step-by-step guide walks you through minting your first CBTC (wrapped Bitcoin) on the Canton Network. You will authenticate with Keycloak, create a deposit account, send BTC to a Taproot address, and receive 1:1 backed CBTC on your Canton participant node. The full process takes about 15 minutes of active work plus ~60 minutes of Bitcoin confirmation time.

🎯 What you will accomplish

  • Authenticate to the Canton Network via Keycloak

  • Create a CBTC deposit account

  • Obtain a Bitcoin deposit address

  • Send BTC and wait for confirmation

  • Verify your CBTC balance

  • Send CBTC to another party (two-phase transfer)


Prerequisites for Minting CBTC

Before you begin minting wrapped Bitcoin on Canton, make sure you have the following:

Requirement
Description

Canton participant node

A running Canton participant node connected to the network. See Canton documentationarrow-up-right for setup.

DA Registry Utility

Installed and configured. See Digital Asset Utilities docsarrow-up-right.

Keycloak credentials

A valid Keycloak host, realm, client ID, username, and password for your environment.

Party ID

Your Canton Party ID, obtained during onboarding.

Rust toolchain

If using cbtc-lib (Rust). Install via rustup.rsarrow-up-right.

BTC to deposit

Real BTC (mainnet) or testnet BTC (testnet). For testnet, you can use the CBTC Testnet Faucetarrow-up-right to get test CBTC directly. For mainnet, you mint CBTC by depositing real BTC.


Choose Your CBTC Environment: Testnet or Mainnet

CBTC is available on three environments. Start with testnet for experimentation, then move to mainnet for production. CBTC also exists on Devnet, but minting and withdrawals are not available to external users on Devnet. You can use the faucet to obtain test CBTC for development.

🧪 Testnet vs. Mainnet: what is identical and what differs

  • Identical: DAR file, API surface, mint/burn flows, governance model, two-phase transfer mechanics

  • Differs: Attestor set (smaller on testnet), confirmation times (may be faster), Instrument IDs (different from mainnet), faucet-only BTC on testnet (no real value)

  • Mocked or unavailable on testnet: Real BTC settlement, production Attestor SLAs, mainnet fee structure

  • Operational note: Testnet may be reset without notice. Testnet CBTC balances and transaction history may not persist across resets. Do not rely on testnet state for production planning. Exact reset schedule and data persistence details to be confirmed with Engineering.

Environment Configuration

Variable
Devnet
Testnet
Mainnet

Set these as environment variables before running any commands:


Step 1: Authenticate with Keycloak

All CBTC operations require a valid Keycloak access token. The canton-lib crate provides a helper for this.

Using cbtc-lib (Rust)

Using the Keycloak API directly

Save the access_token from the response. You will pass it as a Bearer token in all subsequent API calls.


Step 2: Create a Deposit Account

A deposit account maps your Canton Party ID to a unique Bitcoin deposit address. You only need to create this once; the address can be reused for future deposits.

Using cbtc-lib

Using the Canton API directly

Submit a CreateDepositAccount command to the Canton Ledger API v2 endpoint. You can fetch the CBTCDepositAccountRules contract from an Attestor's /app/get-account-contract-rules endpoint.


Step 3: Get Your Bitcoin Deposit Address

Once the deposit account is created, retrieve the Bitcoin address associated with it. This address is derived from the Deposit Account's id field (or the contract_id if the Deposit Account is new).

Using cbtc-lib

Important: This address can be reused indefinitely for future deposits. You can also request additional deposit addresses if needed.


Step 4: Send BTC

Send Bitcoin to the deposit address using any standard Bitcoin wallet or tooling. There is no minimum deposit enforced at the protocol level, but check with BitSafe for any operational minimums.

After sending, you need to wait for 6 Bitcoin block confirmations before the Attestor network will process the deposit.


Step 5: Wait for Confirmations and Auto-Minting

Once your BTC transaction reaches 6 confirmations:

  1. The Attestor network detects the confirmed deposit

  2. Each Attestor independently verifies the transaction

  3. When a threshold of Attestors confirm (via ConfirmDepositAction on the CBTC Governance module), CBTC is automatically minted to your Canton Party

  4. No further action is required from you This process typically takes 60 to 90 minutes, depending on Bitcoin block times.


Step 6: Check Your CBTC Balance

Using cbtc-lib

Using the Canton API directly

Query active contracts filtered by the token holding interface:

💡 Filtering required. This query returns all token holdings, including Canton Coin (CC). To isolate your CBTC balance, you must filter the results client-side by the CBTC instrumentId. The cbtc-lib library handles this automatically via active_contracts::get. There is no single curl that can query and filter for CBTC holdings in one step. The activeAtOffset must be set to the actual latest offset from your ledger.

💡 UTXO model. CBTC uses a UTXO model similar to Bitcoin. Your balance may be spread across multiple holding contracts (soft limit of 10 UTXOs per party per token type). Use the cbtc::consolidate module to merge UTXOs, or cbtc::split to divide them.


Step 7: Transfer CBTC Between Canton Parties

CBTC transfers use a two-phase model: the sender creates an offer, and the receiver accepts it. This ensures both parties explicitly consent to the transfer.

Phase 1: Create a transfer offer (sender)

Phase 2: Accept the transfer (receiver)

ℹ️ No curl example for transfers. The raw API transfer flow requires 5-6 sequential API calls with contract disclosures and is too complex to represent as a single curl example. Use cbtc-lib for transfers, or refer to the Canton Utility docsarrow-up-right for the full API sequence.


Redeem CBTC: Convert Wrapped Bitcoin Back to BTC

To convert CBTC back to BTC:

  1. Create a withdraw account specifying your Bitcoin destination address using the cbtc::mint_redeem::redeem module

  2. Submit the withdrawal which burns CBTC on Canton

  3. The Attestor network detects the burn and constructs a Bitcoin transaction

  4. Attestors sign the transaction via threshold signing (FROST)

  5. The BTC transaction is broadcast to the Bitcoin network

Using cbtc-lib

Using the Canton API directly

Submit a CBTCWithdrawAccount_Withdraw command. You can get the correct extraArgs and contract disclosures from an Attestor's /app/get-token-standard-contracts endpoint. The contractIds, templateIds, and blobs in this example are for illustration only:


Additional Operations

The cbtc-lib library provides several utility modules for managing your CBTC holdings:

Module
Purpose

cbtc::batch

Batch operations for sending CBTC from a CSV file

cbtc::distribute

Distribute CBTC across multiple parties

cbtc::consolidate

Merge multiple UTXO holdings into fewer contracts

cbtc::split

Split a single holding into multiple UTXOs

cbtc::active_contracts

Query your current CBTC holdings


Troubleshooting

chevron-rightMy deposit has not been minted after 90 minuteshashtag
  • Verify the BTC transaction has at least 6 confirmations on a block explorer

  • Confirm you sent to the correct deposit address (from Step 3)

  • Check that your Canton participant node is connected and syncing

  • Escalation: contact [email protected]envelope or post in #cbtc-ecosystem on Slack

chevron-rightTransfer offer is not appearing for the receiverhashtag
  • The receiver must be registered in the DA Registry with a valid credential

  • Confirm the receiver's Party ID is correct

  • Check that both parties are connected to the same Canton sync domain

chevron-right"Insufficient holdings" error when sendinghashtag
  • CBTC uses a UTXO model. You may need to consolidate holdings first using cbtc::consolidate

  • Check your balance with cbtc::active_contracts to verify available amounts

chevron-rightAuthentication token expiredhashtag
  • Keycloak tokens have a limited lifetime. Re-authenticate using Step 1 before retrying the operation


Next Steps

  • API Reference: Full documentation of Canton Ledger API endpoints for CBTC operations (coming soon)

  • SDK Reference: Complete cbtc-lib and canton-lib module documentation (coming soon)

  • Authentication Guide: Detailed Keycloak setup and Auth0 community example (coming soon)

  • Integration Examples: Real-world code showing CBTC in DeFi protocols, wallets, and trading systems (coming soon)


📧 Need help? Reach out to [email protected]envelope or post in #cbtc-ecosystem on Slack. For urgent technical issues, tag the engineering team directly in the Slack channel.

⚠️ Code updated per PR #22. All Rust code examples have been updated to match the actual cbtc v0.3.0 and canton-lib v0.3.0 APIs (correct module paths, struct params, function signatures). Curl examples updated to use ${LEDGER_HOST} without port. Final engineering sign-off by Jesse or Ferenc is still required before external publication.

Last updated