Skip to main content

Using ckBTC in dapps

Advanced
Bitcoin
Chain-key tokens

ckBTC can be integrated into dapps in several ways. Integration may target the dapp developer’s own canisters or the end users of the application. The main options are:

  • allowing clients to interact with the ckBTC ledger directly,
  • enabling a canister to interact with the ckBTC ledger (for its own use or to manage user funds), and
  • supporting Bitcoin ↔ ckBTC conversion for deposits and withdrawals.

Ledger interaction

The ckBTC ledger implements the ICRC-1 and ICRC-2 token standards. This means that integration with the ledger involves calling the standard endpoints for actions such as:

  • icrc1_balance_of to fetch balances,
  • icrc1_transfer to transfer tokens, and
  • icrc2_approve / icrc2_transfer_from for delegated transfers.

There are two primary ways to interact with the ckBTC ledger:

Client calls (via agent)

A client application (e.g. web application) can use an agent to interact directly with the ckBTC ledger canister.

An agent is the API client layer used to call ICP canisters. For example, the ICP JavaScript agent can create an actor from the ledger’s Candid interface to invoke its endpoints.

The following libraries simplify creating actors for the ckBTC ledger:

In this model, all transactions are signed by the user’s account.

Inter-canister calls

A canister can also interact with the ckBTC ledger.

  • In some cases, the canister may use ckBTC for its own purposes, such as making payments to other canisters, managing a treasury, or executing automated transfers.
  • In other cases, the canister may act on behalf of users, which requires managing user funds. This can be achieved by creating subaccounts per user or by pooling all funds in a single account and maintaining an internal balance table.

Libraries are available to simplify inter-canister calls:

  • Rust:
    • icrc-ledger-types Package that defines types for interfacing with ICRC-1/2 ledgers.
    • icrc-ledger-client Package that uses icrc-ledger-types and defines functions for interfacing with ICRC-1/2 ledgers.
    • icrc-ledger-client-cdk Package that defines runtime meant to be used together with the icrc-ledger-client library.
  • Motoko:
    • icrc2-types Package that defines types for interfacing with ICRC-1/2 ledgers.

Example code:

Considerations

  • The ICRC-1/2 ledgers in many cases implement more interfaces than those defined in ICRC-1 and ICRC-2. For example the Rust libraries provided by DFINITY include additional types and functions for (proposed) standards such as ICRC-3, ICRC-21, ICRC-103 and ICRC-106.
  • The libraries mentioned above might not always cover all types and interfaces defined in a ledger's Candid interface.

Bitcoin ↔ ckBTC conversion

Beyond ledger interactions, a dapp may also support minting and burning ckBTC by calling the ckBTC minter canister.

This can be done in two ways:

  • Client calls (via agent)

    • Any client can call the ckBTC minter canister directly.
    • TypeScript library: @dfinity/ckbtc
  • Inter-canister calls

    • A backend canister can call the ckBTC minter canister as part of its logic, either for its own use or on behalf of users.

Check out the ckBTC API and learn more about implementing this conversion flow in the ckBTC best practices.

Why integrate conversion into a dapp

  • Enables deposits from Bitcoin → ckBTC and withdrawals from ckBTC → Bitcoin without leaving the application.
  • Reduces friction and improves overall user experience.

Note: Applications that integrate with OISY may rely on OISY to handle Bitcoin ↔ ckBTC conversion on behalf of their users, instead of implementing the conversion themselves.

Example applications for ckBTC

  • ic-pos An experimental app to demonstrate a real-world use case for ckBTC on the Internet Computer. It is a simple Point of Sale app that allows users to accept ckBTC payments.

Some applications that integrated ckBTC