Interesting dApp idea! I’m just think out loud here. In your step 3, you can design your own rules for generating a BTC address.
The ckBTC minter provides a method called get_btc_address
that generates a Bitcoin deposit address that a user can send Bitcoin to:
get_btc_address : (record { owner: opt principal; subaccount : opt blob }) -> (text);
Since it’ll be your dApp canister that receives the converted ckBTC, the owner
here can be your dApp’s canister id. You may also supply a 32-byte subaccount
of your own choosing, which can help encode additional logic you need.
Now, your dApp can store the staking terms indexed by subaccount
. It can generate a fresh subaccount
for each new deposit to receive, store (subaccount, staking terms) in this table, and then generate the deposit address by calling get_btc_address
with this subaccount.
Note that this owner
and subaccount
pair is exactly the Account
being used by ICRC tokens, such as ckBTC.
Later your canister (or anyone else) may call the update_balance
method of ckBTC minter to confirm if any balance has been received. This method also takes an Account
(owner
and subaccount
) as argument. If new UTXOs have been received on this address, it means new ckBTC has been minted to the corresponding Account
. Your dApp can then lookup the above table for the staking terms.
In fact, your dApp can use the same table to keep track of ongoing deposits. Iterate through this table and call ckBTC minter’s update_balance
with each subaccount
. On a successful deposit, it may move ckBTC tokens to a central account and remove the corresponding entry in this table.
There are a few things to note though:
- If a user sends more BTC to the generated address, new ckBTC will not be minted unless
get_balance
is called again. So you may want to keep checking until all expected funds are received.
- Calling
get_balance
is actually expensive. You can call get_known_utxos
method first, compare with a previous result of get_known_utxos
to check if there is any new UTXO on this address, and only call update_balance
when there is.
Subaccounts need to be unique, and you probably should also think of how users may retrieve their staking in the future, which btw can be part of the staking terms.
If your users are authenticated, the subaccount can be their principal id + nonce, where nonce can be just a counter that increases when the user creates a new stake. If your users are not authenticated, the subaccount can be just a plain counter. Either way, you probably need some way to prevent spamming.