Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions docs/guides/chain-fusion/bitcoin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ICP provides a protocol-level integration with the Bitcoin network. Canisters ca
There are two approaches to working with Bitcoin on ICP:

- **ckBTC (chain-key Bitcoin)**: a 1:1 BTC-backed token native to ICP. Transfers settle in 1-2 seconds with a 10 satoshi fee. Best for most applications that need to accept, hold, or transfer Bitcoin value.
- **Direct Bitcoin API**: call the management canister to read UTXOs, get balances, and submit raw Bitcoin transactions. Best for advanced use cases that need full control over Bitcoin transactions (custom scripts, Ordinals, Runes, BRC-20).
- **Direct Bitcoin API**: call the Bitcoin canister to read UTXOs, get balances, and submit raw Bitcoin transactions. Best for advanced use cases that need full control over Bitcoin transactions (custom scripts, Ordinals, Runes, BRC-20).

This guide covers both approaches.

Expand All @@ -34,19 +34,25 @@ ckBTC is the recommended path for most developers. The ckBTC minter canister hol
```plantuml
actor User
participant "ckBTC Minter" as Minter
participant "Bitcoin Checker" as KYT
participant "ckBTC Ledger" as Ledger
participant "Bitcoin Network" as BTC

User -> Minter: get_btc_address(account)
User -> Minter: get_btc_address(owner, subaccount)
Minter --> User: btc_address
User -> BTC: send BTC to btc_address
User -> Minter: update_balance(account)
Minter --> User: ckBTC minted to ICRC-1 account
note right of BTC: 4 confirmations required
User -> Minter: update_balance(owner, subaccount)
Minter -> KYT: check UTXO
KYT --> Minter: ok
Minter -> Ledger: mint ckBTC (amount - kyt_fee)
Minter --> User: MintedUtxos
```

1. Call `get_btc_address` on the minter with the user's principal and subaccount. This returns a unique Bitcoin address controlled by the minter.
2. The user sends BTC to that address using any Bitcoin wallet.
3. Wait for Bitcoin confirmations (the minter requires confirmations before minting).
4. Call `update_balance` on the minter with the same principal and subaccount. The minter checks for new UTXOs and mints equivalent ckBTC to the user's ICRC-1 account.
1. Call `get_btc_address` on the minter with the user's principal and subaccount. This returns a unique Bitcoin address controlled by the minter via threshold ECDSA.
2. Send BTC to that address from any Bitcoin wallet.
3. Wait for 4 Bitcoin confirmations (mainnet). The minter will not process UTXOs until the required number of confirmations is reached.
4. Call `update_balance` on the minter. The minter checks for new UTXOs, runs a KYT (Know-Your-Transaction) compliance check via the Bitcoin Checker canister, and mints ckBTC to the user's ICRC-1 account. A KYT fee of 100 satoshis is deducted per UTXO. UTXOs that fail the KYT check are quarantined and not minted.

<Tabs syncKey="lang">
<TabItem label="Motoko">
Expand Down Expand Up @@ -243,15 +249,20 @@ async fn transfer(to: Principal, amount: Nat) -> Result<Nat, TransferError> {
actor User
participant "ckBTC Ledger" as Ledger
participant "ckBTC Minter" as Minter
participant "Bitcoin Checker" as KYT
participant "Bitcoin Network" as BTC

User -> Ledger: icrc2_approve(spender=minter, amount)
User -> Minter: retrieve_btc_with_approval(btc_address, amount)
Minter -> KYT: check destination address
KYT --> Minter: ok
Minter -> Ledger: icrc2_transfer_from(user, minter, amount)
Minter -> BTC: send BTC to btc_address
Minter --> User: block_index
note right of Minter: processed asynchronously
Minter -> BTC: submit signed transaction
```

Withdrawal is a two-step process: approve the minter to spend your ckBTC, then call `retrieve_btc_with_approval`. The minimum withdrawal is 50,000 satoshis (0.0005 BTC).
Withdrawal is a two-step process: approve the minter to spend your ckBTC, then call `retrieve_btc_with_approval`. Before burning ckBTC, the minter runs a KYT check on the destination Bitcoin address. The Bitcoin transaction is submitted asynchronously — the minter batches pending requests to optimize miner fees. Track status with `retrieve_btc_status_v2(block_index)`. The minimum withdrawal is 50,000 satoshis (0.0005 BTC).

<Tabs syncKey="lang">
<TabItem label="Motoko">
Expand Down Expand Up @@ -493,7 +504,7 @@ For a complete working example with all type definitions and error handling, see

## Direct Bitcoin API

For use cases that require full control over Bitcoin transactions (custom scripts, Ordinals, Runes, BRC-20), you can call the Bitcoin API directly through the management canister. This involves generating addresses with threshold ECDSA or Schnorr signatures, building raw transactions, and submitting them to the Bitcoin network.
For use cases that require full control over Bitcoin transactions (custom scripts, Ordinals, Runes, BRC-20), you can call the Bitcoin canister directly. This involves generating addresses with threshold ECDSA or Schnorr signatures, building raw transactions, and submitting them to the Bitcoin network.

### Bitcoin API canister IDs

Expand Down Expand Up @@ -1165,7 +1176,7 @@ docker stop bitcoind && docker rm bitcoind
- [Chain-key cryptography](../../concepts/chain-key-cryptography.md): learn how threshold ECDSA and Schnorr signatures work
- [Chain-key tokens](../digital-assets/chain-key-tokens.md): explore ckBTC, ckETH, and other chain-key tokens
- [Ethereum integration](ethereum.md): apply similar patterns for Ethereum
- [Management canister reference](../../reference/management-canister.md): full API reference for `bitcoin_get_utxos`, `sign_with_ecdsa`, and other management canister methods
- [Management canister reference](../../reference/management-canister.md): full API reference for `sign_with_ecdsa`, `sign_with_schnorr`, and other management canister methods (note: the `bitcoin_*` methods in the management canister are deprecated; use the Bitcoin canister directly)
- [Bitcoin canister API specification](https://github.com/dfinity/bitcoin-canister/blob/master/INTERFACE_SPECIFICATION.md): detailed API documentation
- [Bitcoin integration (Learn Hub)](https://learn.internetcomputer.org/hc/en-us/articles/34211154520084): protocol-level details of how ICP connects to Bitcoin

Expand Down
8 changes: 4 additions & 4 deletions docs/guides/chain-fusion/dogecoin.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ ICP canisters can interact directly with the Dogecoin network without bridges or
- **Dogecoin canister**: a system canister controlled by the NNS that exposes an API for querying Dogecoin network state (UTXOs, balances, block information) and submitting signed transactions.
- **Threshold ECDSA**: canisters request threshold ECDSA signatures from the management canister to sign Dogecoin transactions. The private key is never reconstructed; it exists only as secret shares distributed across subnet nodes.

This is the same model as the [Bitcoin integration](bitcoin.md), using a UTXO-based transaction model and secp256k1 ECDSA signatures. The main difference is that Dogecoin transactions are submitted through the Dogecoin canister rather than the Bitcoin management canister API.
This is the same model as the [Bitcoin integration](bitcoin.md), using a UTXO-based transaction model and secp256k1 ECDSA signatures. The main difference is that Dogecoin transactions are submitted through the Dogecoin canister rather than the Bitcoin canister.

## How it works

Expand Down Expand Up @@ -118,7 +118,7 @@ For a complete, working implementation covering all steps (including deriving a

The [Bitcoin integration guide](bitcoin.md) covers the same conceptual steps with complete inline code. Because Dogecoin is a fork of Bitcoin and shares the same UTXO model and secp256k1 ECDSA signatures, the patterns translate directly with these differences:

- Use the Dogecoin canister for UTXO queries and transaction submission (not the management canister's `bitcoin_*` API)
- Use the Dogecoin canister for UTXO queries and transaction submission (not the Bitcoin canister's `bitcoin_*` API)
- Use Dogecoin's P2PKH address format (mainnet addresses start with `D`)
- Dogecoin uses koinus instead of satoshis (1 DOGE = 100,000,000 koinus)
- Dogecoin uses a different fee rate: use `dogecoin_get_current_fee_percentiles` to get current rates
Expand All @@ -131,13 +131,13 @@ The key differences in implementation:

| | Bitcoin | Dogecoin |
|---|---|---|
| API | Management canister (`bitcoin_*` methods) | Dogecoin canister |
| API | Bitcoin canister (`bitcoin_*` methods) | Dogecoin canister |
| Chain-key token | ckBTC | ckDOGE |
| Address prefix | `1`, `3`, `bc1` (mainnet) | `D` (mainnet) |
| Unit | satoshi | koinu |
| Status | Stable | Beta |

Developers familiar with the Bitcoin integration will find the Dogecoin integration conceptually identical. The primary practical difference is calling the Dogecoin canister rather than the management canister's Bitcoin API.
Developers familiar with the Bitcoin integration will find the Dogecoin integration conceptually identical. The primary practical difference is calling the Dogecoin canister rather than the Bitcoin canister.

## NNS governance

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/digital-assets/chain-key-tokens.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The deposit flow has two steps:
1. **Get a deposit address**: call `get_btc_address` on the ckBTC minter with the owner principal and an optional subaccount. The minter returns a unique Bitcoin address.
2. **Mint ckBTC**: after BTC is sent to that address, call `update_balance` on the minter. The minter checks for new UTXOs and mints ckBTC to the corresponding ICRC-1 account.

The minter requires a minimum number of Bitcoin confirmations before minting (currently 6 on mainnet). `update_balance` returns `NoNewUtxos` if confirmations have not yet been reached: your app should poll or prompt the user to wait.
The minter requires a minimum number of Bitcoin confirmations before minting (currently 4 on mainnet). `update_balance` returns `NoNewUtxos` if confirmations have not yet been reached: your app should poll or prompt the user to wait.

<Tabs syncKey="lang">
<TabItem label="Motoko">
Expand Down
10 changes: 5 additions & 5 deletions plugins/remark-plantuml.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ skinparam defaultFontSize 13
skinparam defaultFontColor #1a1714
skinparam sequenceArrowThickness 1.5
skinparam sequenceArrowColor #cc5a2b
skinparam SequenceLifeLineBorderColor #e5ddcf
skinparam SequenceLifeLineBorderColor #6b6660
skinparam ParticipantBackgroundColor #fdfaf3
skinparam ParticipantBorderColor #e5ddcf
skinparam ParticipantBorderColor #6b6660
skinparam ParticipantFontColor #1a1714
skinparam ActorBackgroundColor #fdfaf3
skinparam ActorBorderColor #e5ddcf
skinparam ActorBorderColor #6b6660
skinparam ActorFontColor #1a1714
skinparam NoteBackgroundColor #f2d7c7
skinparam NoteBorderColor #e5ddcf
skinparam NoteBorderColor #6b6660
skinparam NoteFontColor #1a1714
`;

Expand All @@ -53,7 +53,7 @@ export default function remarkPlantUML() {
const url = toUrl(node.value);
parent.children[index] = {
type: "html",
value: `<img src="${url}" alt="PlantUML diagram" />`,
value: `<figure class="plantuml-diagram"><img src="${url}" alt="PlantUML diagram" /></figure>`,
};
});
};
Expand Down
22 changes: 22 additions & 0 deletions src/styles/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,28 @@ h1, h2, h3, h4, h5, h6 {
color: var(--sl-color-white);
}

/* ── PlantUML diagrams ────────────────────────────────────── */

.plantuml-diagram {
display: block;
margin: 1.5rem 0;
background: var(--icp-bg-elev);
border-radius: 6px;
padding: 1.5rem;
text-align: center;
}

.plantuml-diagram img {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}

[data-theme='dark'] .plantuml-diagram img {
filter: invert(1) hue-rotate(180deg);
}

/* ── Agent signaling ──────────────────────────────────────── */

/* Visually hidden but present in DOM for HTML-to-markdown converters.
Expand Down
Loading