Generate unique ICRC-1 address for each user (subaccount)


I am trying to generate a unique address (principal) for each user so I can display it in the front end and the user can send ckBTC token to this address.

I tried to search for solutions and couldn’t find any. The closest I got was with this code that I found in this thread:

  public type Account = { owner : Principal; subaccount : ?Blob };

  public shared (msg) func getDepositAddress() : async Text {
    let acc : Account = {
      owner = Principal.fromActor(this);
      subaccount = ?Principal.toBlob(msg.caller);
    return Account.toText(acc);

However, it is trapping when I call the function because of this assertion in the module.

assert (subaccount.size() == 32);

Please, do you have a working example somewhere? I feel like this should be really straightforward but I spent a couple of hours on it and couldn’t find a solution for this use case.

1 Like

The principal is up to 29 bytes, that’s why the assertion failed
You can try: toSubAccount


Thanks a lot @zohaib29, this works for me. I put together a small working example that generates subaccount for each caller and then verifies balance of it in case this can be helpful for anyone:

1 Like

Hey @lukevoz , nice solution. Once your customers know where to send their BTCs, do you let them choose their preferred on-ramp provider, or do you forward them to a provider you’ve partnered with?

1 Like

Hey @Mercury, thanks for your message. Yeah the way it currently works is we display the address to the user (and a QR code) and the user can pay it from any wallet he/she wants and once the payment is done user can click the button to verify it through the backend. You can see the current design in the picture attached.

Nice. Any plans to integrate a (web3/web2) KYC / KYB provider ? Yes, IC 's current partner handles KYT for IC, but it’s IC 's users who’re liable for KYC/KYB, meaning us, the BUIDLers :slight_smile: