Subscription-based app: need architectural advice

Hi all,

Here’s what I’m planning to do for my subscription-based app.

  • User A wants to subscribe to the app
  • User A clicks on “Subscribe”
  • This calls the icrc2_approve method, giving approval to canister C to transfer on behalf of user A
  • Monthly, canister C transfers the subscription amount from A to the app vault (user B?)

Does this sound ok?

Here’s where I’m a bit puzzled:

1/ Giving approval to a canister feels weird because: can’t the canister principal change ? I’m guessing the principal doesn’t change upon being upgraded, but what if for instance at some point I want to split my canister into 2 for technical reasons. That would require me to destroy my canister and recreate new ones. I would then lose all the approvals !

2/ Also, what’s the best way to get a canister’s principal? Can this be done from the canister id ?

Any help appreciated :slight_smile:



Your plan for the subscription-based app seems solid. Here are a couple of suggestions based on your questions:

  1. You can create a Ledger Canister to handle all approval and transfer operations. This way, your other canisters can verify transaction correctness and provide services based on the user principal interacting with your application.

  2. To get a canister’s principal, you can use on rust ic_cdk::id() inside your canister logic, and for Motoko follow this post.

1 Like

‘canister id’ and ‘canister principal’ are synonyms. The ID is the principal

1 Like

Noted :+1:

What about this:

Any workaround?
If I build an app for the next 10 years, how can I know I won’t have to change its canister id…?

You can’t be sure. But if you use @b3hr4d’s suggestion and create a minimal canister that is only responsible for proxying ledger calls it can always be done with that canister’s principal. The other option is if you have to split your canisters to split in such a way that the canister that does ledger calls will stay in the same ID

1 Like

Thanks @b3hr4d and @Severin. As you guys suggested, I split my backend canister into 2, with 1 canister specifically for handling approvals and transfers. It feels much cleaner and it lowers the chances of having to split even further.