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
26 changes: 25 additions & 1 deletion docs/guides/chain-fusion/bitcoin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ ckBTC is the recommended path for most developers. The ckBTC minter canister hol

### Deposit flow (BTC to ckBTC)

```plantuml
actor User
participant "ckBTC Minter" as Minter
participant "Bitcoin Network" as BTC

User -> Minter: get_btc_address(account)
Minter --> User: btc_address
User -> BTC: send BTC to btc_address
User -> Minter: update_balance(account)
Minter --> User: ckBTC minted to 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.
2. The user sends BTC to that address using any Bitcoin wallet.
3. Wait for Bitcoin confirmations (the minter requires confirmations before minting).
Expand Down Expand Up @@ -227,6 +239,18 @@ async fn transfer(to: Principal, amount: Nat) -> Result<Nat, TransferError> {

### Withdraw (ckBTC to BTC)

```plantuml
actor User
participant "ckBTC Ledger" as Ledger
participant "ckBTC Minter" as Minter
participant "Bitcoin Network" as BTC

User -> Ledger: icrc2_approve(spender=minter, amount)
User -> Minter: retrieve_btc_with_approval(btc_address, amount)
Minter -> Ledger: icrc2_transfer_from(user, minter, amount)
Minter -> BTC: send BTC to btc_address
```

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).

<Tabs syncKey="lang">
Expand Down Expand Up @@ -1020,7 +1044,7 @@ All Bitcoin API calls require cycles attached to the call. In Rust, the `ic-cdk-

## Development setup

### Quick start with the bitcoin-starter template
### Quickstart with the bitcoin-starter template

The fastest way to get started is with the bitcoin-starter template:

Expand Down
34 changes: 33 additions & 1 deletion docs/guides/chain-fusion/dogecoin.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ The key differences in implementation:
| | Bitcoin | Dogecoin |
|---|---|---|
| API | Management canister (`bitcoin_*` methods) | Dogecoin canister |
| Chain-key token | ckBTC (live) | ckDOGE (upcoming) |
| Chain-key token | ckBTC | ckDOGE |
| Address prefix | `1`, `3`, `bc1` (mainnet) | `D` (mainnet) |
| Unit | satoshi | koinu |
| Status | Stable | Beta |
Expand All @@ -143,6 +143,38 @@ Developers familiar with the Bitcoin integration will find the Dogecoin integrat

The Dogecoin canister is controlled by the [Network Nervous System](../../concepts/governance.md). Any changes to the canister require an NNS proposal that the community must review and approve before taking effect. This means your canister can call the Dogecoin canister without additional trust assumptions beyond the NNS governance process itself.

## ckDOGE

ckDOGE is a 1:1 DOGE-backed token on ICP. The ckDOGE minter holds real DOGE and mints or burns ckDOGE using the same ICRC-1/ICRC-2 interface as ckBTC. For canister IDs and CLI-based deposit and withdrawal flows, see [Chain-key tokens](../digital-assets/chain-key-tokens.md).

### Deposit (DOGE to ckDOGE)

```plantuml
actor User
participant "ckDOGE Minter" as Minter
participant "Dogecoin Network" as DOGE

User -> Minter: get_doge_address(account)
Minter --> User: doge_address
User -> DOGE: send DOGE to doge_address
User -> Minter: update_balance(account)
Minter --> User: ckDOGE minted to ICRC-1 account
```

### Withdrawal (ckDOGE to DOGE)

```plantuml
actor User
participant "ckDOGE Ledger" as Ledger
participant "ckDOGE Minter" as Minter
participant "Dogecoin Network" as DOGE

User -> Ledger: icrc2_approve(spender=minter, amount)
User -> Minter: retrieve_doge_with_approval(doge_address, amount)
Minter -> Ledger: icrc2_transfer_from(user, minter, amount)
Minter -> DOGE: send DOGE to doge_address
```

## Next steps

- [Chain fusion overview](../../concepts/chain-fusion.md): understand how ICP integrates with external blockchains
Expand Down
18 changes: 18 additions & 0 deletions docs/guides/chain-fusion/ethereum.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ For a conceptual overview of how ICP connects to other blockchains, see [Chain F

The EVM RPC canister (`7hfb6-caaaa-aaaar-qadga-cai`) is a system canister deployed on ICP's 34-node fiduciary subnet. When your canister calls it:

```plantuml
participant "Your Canister" as Canister
participant "EVM RPC Canister" as EVM
participant "Provider 1" as P1
participant "Provider 2" as P2
participant "Provider N" as PN

Canister -> EVM: eth_getBlockByNumber(chain, args) + cycles
EVM -> P1: JSON-RPC (HTTPS outcall)
EVM -> P2: JSON-RPC (HTTPS outcall)
EVM -> PN: JSON-RPC (HTTPS outcall)
P1 --> EVM: response
P2 --> EVM: response
PN --> EVM: response
note right of EVM: consensus check (≥2/3 nodes agree)
EVM --> Canister: Consistent(result) + refund excess cycles
```

1. Your canister sends a request to the EVM RPC canister with cycles attached.
2. The EVM RPC canister fans the request out to multiple RPC providers via [HTTPS outcalls](../backends/https-outcalls.md).
3. Each provider's response goes through ICP subnet consensus (at least 2/3 of nodes must agree).
Expand Down
53 changes: 52 additions & 1 deletion docs/guides/chain-fusion/solana.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ Two ICP features enable Solana integration:

The SOL RPC canister (`2xib7-jqaaa-aaaar-qai6q-cai`) is deployed on ICP mainnet and handles Solana JSON-RPC calls on your behalf. When your canister calls it:

```plantuml
participant "Your Canister" as Canister
participant "SOL RPC Canister" as SolRpc
participant "Solana Providers" as Providers
participant "Solana" as SOL

Canister -> SolRpc: request(json_rpc, max_response_bytes) + cycles
SolRpc -> Providers: HTTPS outcalls to multiple providers
Providers --> SolRpc: aggregated responses
SolRpc --> Canister: result + refund excess cycles
```

1. Your canister sends a JSON-RPC request with cycles attached.
2. The SOL RPC canister fans the request out to multiple Solana RPC providers via HTTPS outcalls.
3. Responses are aggregated. The canister returns the result once providers agree.
Expand Down Expand Up @@ -328,14 +340,53 @@ Every SOL RPC call requires cycles to cover HTTPS outcall costs. The `sign_with_

Send 10B cycles per RPC call as a starting budget: unused cycles are refunded. Set `max_response_bytes` to the minimum needed; smaller values reduce costs.

## ckSOL

ckSOL is a 1:1 SOL-backed token on ICP. The ckSOL minter holds real SOL via chain-key Ed25519 addresses and mints or burns ckSOL using the ICRC-1/ICRC-2 interface. For canister IDs and CLI-based deposit and withdrawal flows, see [Chain-key tokens](../digital-assets/chain-key-tokens.md).

### Deposit (SOL to ckSOL)

```plantuml
actor User
participant "ckSOL Minter" as Minter
participant "ckSOL Ledger" as Ledger
participant "SOL RPC Canister" as SolRpc
participant "Solana" as SOL

User -> Minter: get_deposit_address(owner, subaccount)
Minter --> User: deposit_address
User -> SOL: transfer SOL to deposit_address
User -> Minter: process_deposit(owner, subaccount, tx_signature)
Minter -> SolRpc: fetch & verify transaction
Minter -> Ledger: mint ckSOL (amount - deposit_fee)
Minter --> User: Minted { block_index, minted_amount }
```

### Withdrawal (ckSOL to SOL)

```plantuml
actor User
participant "ckSOL Minter" as Minter
participant "ckSOL Ledger" as Ledger
participant "Solana" as SOL

User -> Ledger: icrc2_approve(spender=minter, amount)
User -> Minter: withdraw(sol_address, amount)
Minter -> Ledger: burn via icrc2_transfer_from(user, amount)
Minter --> User: burn_block_index
note right of Minter: processed asynchronously
Minter -> SOL: submit SOL transfer (chain-key Ed25519)
User -> Minter: withdrawal_status(burn_block_index)
Minter --> User: TxFinalized
```

## Current status and limitations

The Solana integration is newer than the Bitcoin and Ethereum integrations:

- **SOL RPC canister is live on mainnet**: deployed and functional, with the API surface still evolving.
- **Threshold Ed25519 is available**: both test (`test_key_1`) and production (`key_1`) keys are live on ICP mainnet.
- **No SPL token helpers**: SPL token operations (reading token accounts, transferring tokens) require constructing JSON-RPC calls and transaction instructions manually.
- **No ckSOL token**: unlike Bitcoin (ckBTC) and Ethereum (ckETH), there is no chain-key SOL token yet.
- **Transaction construction is manual**: there is no official ICP library for building Solana transactions. See the [basic_solana example](https://github.com/dfinity/sol-rpc-canister/tree/main/examples/basic_solana) for a reference implementation.

Follow the [SOL RPC canister repository](https://github.com/dfinity/sol-rpc-canister/blob/main/README.md) for the latest updates.
Expand Down
25 changes: 22 additions & 3 deletions plugins/remark-plantuml.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,30 @@ function encode(data) {
return r;
}

const SKIN = `
skinparam backgroundColor transparent
skinparam defaultFontName sans-serif
skinparam defaultFontSize 13
skinparam defaultFontColor #1a1714
skinparam sequenceArrowThickness 1.5
skinparam sequenceArrowColor #cc5a2b
skinparam SequenceLifeLineBorderColor #e5ddcf
skinparam ParticipantBackgroundColor #fdfaf3
skinparam ParticipantBorderColor #e5ddcf
skinparam ParticipantFontColor #1a1714
skinparam ActorBackgroundColor #fdfaf3
skinparam ActorBorderColor #e5ddcf
skinparam ActorFontColor #1a1714
skinparam NoteBackgroundColor #f2d7c7
skinparam NoteBorderColor #e5ddcf
skinparam NoteFontColor #1a1714
`;

function toUrl(source) {
const src = source.trimStart().startsWith("@startuml")
const body = source.trimStart().startsWith("@startuml")
? source
: `@startuml\n${source}\n@enduml`;
const compressed = deflateRawSync(Buffer.from(src, "utf-8"), { level: 9 });
: `@startuml\n${SKIN}\n${source}\n@enduml`;
const compressed = deflateRawSync(Buffer.from(body, "utf-8"), { level: 9 });
return `${SERVER}/${encode(compressed)}`;
}

Expand Down
Loading