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.