Skip to content
CCPEDIAby Unity Nodes
App Development

Per-user deposit destination on a single party without a memo field — is there a pattern?

8 posts132 views1 likesLast activity 2d ago

  1. joao_trakxOP

    Is there any way on Canton to give each end user a unique deposit destination string that routes to a single party we control, without the user having to fill in a memo/reason field?

    Context: we operate a single receiving party on our own validator and need to attribute incoming CIP-0056 transfers to the end user who sent them. Today the options we know of are:

    1. Sender attribution — the user pre-registers the parties they will send from, and we attribute by sender. Works with any wallet, but requires registration first.
    2. Memo/reason metadata (“splice.lfdecentralizedtrust.org/reason”) — the exchange-integration pattern. Works when our app composes the transaction (CIP-0103), but on a manual transfer from a wallet UI the user has to type the memo into a separate field. We tried a BitGo-style “party?memoId=…” string and wallets do not parse it.
    3. One party per user — not viable for us given party limits and custody constraints.

    What we are looking for is closer to a virtual IBAN: one string per user that the user pastes as the recipient, that resolves on the sending side to “receiver = our party” plus an identifier we can read on receipt. Something like an alias/proxy party that forwards to a fixed destination while preserving who it was addressed to.

    Related questions:

    • CIP-0112 Accounts (“owner + provider + id”) seem to be the standard’s answer, but the account “id” is a separate input field, and V1 senders cannot set it at all. Is anyone working on a serialised “party + account” address format that wallets would parse from a single paste?
    • Is there any known “magic party” / alias-party pattern for this (someone mentioned building one a while ago)? Registry-side resolution of the receiver account (the V1→V2 partial-compatibility case in CIP-0112 §5.4) would also do it, if any registry implements it.
    • Wallet providers (Loop, Walley, Fireblocks, BitGo): is a recipient string with an embedded account id / memo on your roadmap?

    Any pointers appreciated.

  2. vinh

    Since you’re custody the coin anyway you can indeed do this in a very simple way using external party but share the same key. So you don’t need to manage a lot of key. And you use a party-hint to identify account such as a::fingerprint a2::fingerprint All of these can come out of a single private key. It’s external party, so you won’t hit the limit and at the same time only a key to manage from your custodian perspective.

    Another apporach you can consider is to using random deposit amount to distingush them in a short window.

  3. kevmuko

    Creator of Walley here. I think you’ve probably exhausted most of the options given the party limit onboarding network-wide. For magic addresses, it boils down to either memo or sender attribution. If you want the UX convenience of party id, then it would require party allocation per user. I know DA is actively trying to increase the upper bound on network wide party allocations, but it’s still going to be fixed (on the order of a couple million parties) for a long period of time even into next year.

    You could do something clever where you allocate a fixed N number of deposit addresses and you can rotate through them with time allocation per user (each user holds a lock on the address for a fixed amount of time where you can attribute the deposits). This is just better resource management given the network allocation constraint.

    Otherwise, I think virtual addresses would need to be supported at the protocol level by DA. Generally, party id’s represent custody on the network and hence why we don’t have anything like smart contract addresses like on Ethereum.

    From the wallet angle, it could be that there’s a better way to process metadata through a singular field and move away from like filling in a memo, and instead just do like a generic tx field that encodes the party id, account, metadata, etc. for better UX. This would probably require a new CIP and adoption from all the wallets on the network. Nothing on the roadmap currently on this, and if work is done it would require a new wallet standard to be proposed, reviewed, and implemented.

  4. joao_trakx

    Thanks, appreciated. One nuance: we don’t custody end users’ coins on Canton (they hold their own parties), and units only reach our party when they redeem. That said, the shared-namespace idea is neat, and we’ll keep it in mind if we ever need per-user receiving parties. Out of curiosity: do external parties hosted on a participant count towards its hosted-party limit?

    On random amounts, we already use a unique amount as the key for proving control of a party at registration, but for the transfer itself the amount is the request size, so it can’t carry the identifier.

  5. joao_trakx

    Thanks, that’s the confirmation we were looking for. For now we’ll go with sender attribution: users register and prove control of the parties they send from, and the same registered party receives their minted units, so it fits our flow well.

    Where it breaks is the exchange/custodian case: an investor whose tokens sit on an exchange sends from an omnibus party that identifies nobody and can change at any time. A memo solves that on paper, but in practice users forget to fill it in, and every miss becomes a support case to recover funds.

    So +1 on the single-field idea. A recipient string that carries party + account/memo, which every wallet parses by default on a plain copy/paste, would cover it. Some wallets already accept a party?memo=… style string, but it isn’t standard, so it breaks on others (e.g. the Splice wallet UI). If a CIP gets drafted for this, we’d be happy to contribute the use case and help review it.

  6. jadonamite 1

    Hi joao_trakx, I read your post in t/9207 about matching deposits from exchanges, especially the line “users forget to fill it in, and every miss becomes a support case to recover funds.”
    I built something for exactly that during HackCanton Season 3. It’s called Naust. Every customer gets their own deposit address under your key, so a deposit is matched to the customer by where it lands. No memo and no sender registration, and the exchange doesn’t change anything. It accepts the transfer, sweeps it to your treasury and writes a receipt on the ledger. It runs on DevNet today: 10 deposits in a row matched in under 5 seconds each.
    Could I ask you five quick questions, on a 20-minute call or by message, whichever is easier?

    Jadon

  7. joao_trakx

    Coming back to this after digging into the Naust thread and the Canton 3.6 release notes, because two things changed the picture since September.

    @vinh — I dismissed the shared-key idea too quickly. For the redemption leg we are the receiver anyway, so a receiving party per customer under one key is not custody of the customer’s assets; it is the Canton equivalent of the per-customer deposit address we already run on the EVM side. Combined with PV36 decoupling validator memory from the hosted-party count, this looks viable. A few questions before we commit:

    1. Shared key across external parties: is this documented anywhere? I’d like to confirm that several external parties with different hints can be allocated under the same signing key (same namespace fingerprint) and that nothing in the topology or in the Splice/Utilities registries treats them as one identity.
    2. Hosted-party limits post-PV36: is there still a configured cap per participant, or only the network-wide allocation limit? And is the 3.6 ACS-commitment redesign already live on MainNet?
    3. Cost per party: what does allocating an external party cost in CC/traffic today (topology transactions), and does a receiving-only party need any CC balance of its own — e.g. to create a transfer pre-approval for an instrument whose admin we are?
    4. The wallets-and-exchanges docs still advise against using parties as deposit addresses. Is that guidance pre-PV36 and aimed at exchanges with millions of occasional depositors, or does DA still recommend memo tags even at a few thousand parties?

    @jadonamite — thanks for the pointer; your thread is a useful reference for the accept-and-sweep sequence. Our case is simpler since we are the instrument admin and hold the receiving keys, so we can pre-approve each party at creation and skip the accept step.

  8. noahevans

    On the shared-key point: as I understand it, multiple external parties can be allocated under the same namespace/signing key; the party hint makes the IDs distinct, and they remain separate parties for authorization/topology. I’m not aware of a Splice/Utilities doc that explicitly promises registries won’t correlate them, so I’d get that confirmed rather than assume. For a receive-only party I would not expect it to need its own CC balance; traffic is normally a participant/validator concern, though creating a transfer pre-approval is still a ledger action with traffic cost. I can’t verify the post-PV36 cap or 3.6 MainNet status from here.