Best Practice - Backend Service Wallets

Good morning All,

Can anyone help me with the Best Practice approach for backend server management of user payments. I’m just building a prototype app that requires the user to send ADA for service use. I’ve been looking through and testing the Cardano-Wallet API with a bespoke server wrapper enabling my client facing app. I’d like to know which of these is the best approach:

  1. Create a new wallet per client; although that entails the need management of all the keys generated, so that the wallets can be recoverable later (i.e. to avoid losing funds)
  2. Use a single wallet and provide the client a send address; however, I need to uniquely identify them. I can do that, by allocating the next unused payment address. However, given the standard, only 20 are preallocated, with more are only allocated when funds arrive; if the client doesn’t send money, I’ve got no way of generating more send addresses.Thoughts? Am I expected to dust them, although that could then be used as an attack mechanism to cost me money with skeleton accounts?
  3. Another way?

Any help/advice would be really appreciated.

Kind regards

Carl

Use a HD wallet and generate a unique address for each client. That way you don’t need to manage many keys, just their derivation paths.

Many thanks @waldmops, I’d not come across the HD Wallets; that completely clears up my expectation but couldn’t find what… :wink:

@waldmops actually, I’m just an idiot! I just googled and now understand that I’m already using HD Wallets (I just didn’t understand the terminology).

Can you explain how I deal with this use case: 21 clients want to send me ADA. The HD Wallet maintains 20 unused addresses, which I can get a list of and allocate them to the first 20. I assume the 21st (and any others) are now blocked until one of the first 20 send ADA and hence use the address? Worst still is that all 20 might decide NOT to send immediately, that that blocks any future clients. In the Cardao-Wallet API I can’t see a practical way of either marking the address in use (without sending some dust; costing me ADA) or any way of allocating more send addresses?

I hope this makes sense and that there is a good solution/approach? At the moment, I’m toying with the idea of allocating the full wallet and actually giving the wallet back to the client (so they can recover and control it). However, if they populate that wallet, my server would see the funds and allow them to use my service. This forms a nice elegant compromise as the client is left in complete control. Thoughts?

You can use the 21st address first or any other. There is no order in which addresses need to be used.

Do I understand your use case correctly in that the client funds a wallet to which both they and you hold the key and you deduct funds for service use?

If that’s really the way you want to do it consider what happens if a client has their key stolen and the wallet drained. Wouldn’t the client accuse you of cheating? You would have no way to prove that you could not have taken the money.

If you want pay-per-use micropayments the way I would go is with payment channels.

Thanks, you’re right about the key being stolen etc, I had given that a thought but I still can’t get my head around the problem of the 20 addresses, i.e.

The first person is given the first unused address to send to (I know it’s that person by the address given to them to pay to)
Then the second person is given the second (I record that address against them for their transaction)
…through to the 20th person

Now on the 21st, IF none of those have paid yet, the 20 allocated addresses are still unused; i.e. no one has paid so when I do a list of addresses, I get the same 20 unused addresses that I’m expecting those 20 different people to use.

How do I get around that problem? It’s this issue that I’m finding hard to conceptualise. It’s clearly a problem in my head (i.e. not understanding something fundamental; but for the life of me, I can’t see how to get around it).

So I simply need a service that quotes the cost of the transaction + my fee and then ask for the person (through the client app) to make a transfer. When that transfer is complete, I can tick off their payment (i.e. I know when send they were and then I action the transaction on chain via Metadata).

Looking into payment channels now. To see if they help/are what I need. Had our poxy cat sit on my lap for the last few hours!! Taking my dev time away… Doh.

Such a dependency does not exist. You can generate address #21 first or #4223, it doesn’t matter. They also don’t need to be generated in batches. Every customer can have their own address. You can have any number of them.

It would depend on your use case, the 20 address you mention is your default address gap in BIP44 - if it’s a wallet that you wont be reusing across different clients and is for your own use, you can change it to as high as 10,000 or 100,000 if you wish. Note that higher you go with address gap, slower the performance of the wallet would be to search the addresses. This is commonly done by some of the exchanges.

Also, another aid for you would be upcoming multi account support which will allow you to have different accounts available associated with a single key, which could each have custom address gap. This could essentially help you divide the address gap into smaller divisions.

We have a similar problem.

We want to generate addresses that customers can send ADA to, but we don’t know if or when they actually will. The address will be “reserved” for them, and only them. It can’t be used by anyone else.

We might generate 100 adrresses and allocate them to 100 customers, but only 40 customers use the address to send us ADA.

When the 101th customer asks for an address, we will want to give them an address that hasnt been allocated (or used) before.

Am I right to understand that the best/recommended way to do this is to use a large ADDRESS_POOL_GAP (maybe 10000), and when all the unused addresses have allocated we just create another wallet? Is this what the (some of) the exchanges do?

When is the multi-account support planned to arrive?

The larger the ADDRESS_POOL_GAP value, the slower the performance, so the optimal value is as large as we can get away with from a performance perspective.

Thank you John for asking I honestly don’t know the answer. I’m told above that we can just allocate more addresses, but the Cardano-Wallet doesn’t allow it; i.e. it just provides another x addresses. It assumes all will get used, but if our customer doesn’t send, then that address is wasted, thus needs to be recycled and the customer warned do not use. It’s worrying the heck out of me when we hit 10k and we run out of space. As you say, generating another wallet is the only option. I can’t believe there isn’t a function that just says, give me another please.

I’d like to know more about the construct address section of the API. I think it might be relevant but I’m not sure. Does anyone know if there is an example or some more documentation?

@johnmathews @CrazyCareer
This thread is 3 months old, please check the options (especially second one) presented on this thread.

Thanks @rdlrt . cardano-addresses is the way to go. problem solved as far as i can tell.

Thanks @rdirt. This demonstrates why it’s worth continuing on these discussions, whether 1 minute, 1 day or 1 month after. Thank you @johnmathews. I’d NOT picked up on the construct address! I simply missed it in the communication and API. That, I agree, will solve our use case (finally). Many thanks.

@CrazyCareer a lot of what we’re trying to do is similar to other exchanges and service providers. The Rosetta project covers this use case perfectly as far as I can tell. cardano have developed an implementation of the spec. GitHub - input-output-hk/cardano-rosetta: An implementation of Rosetta for Cardano

Are you familiar with it? I’d suggest you take a look if not. It’s an extra layer of abstraction but could be worth the effort.

If you want to combine efforts to understand and build using it, I’d be happy to talk!

I’m joining to this usefull thread! How you guys would create transactions using cardano-wallet with derived addresses created with cardano-addresses?

I mean can I create transactions with cardano-wallet using exact UTXOs from derived child addresses far beyond the gap-limit set to keep it under BIP-44 ? I don’t want to use cli for this in my backend.

Does rosetta really helps or that extra layer of abstraction over-complicates things for small-medium sized projects?

Does creating a mnemonic wallet for each user with less than 20 as gap limit would destroy cardano-node performance with tons of wallet syncs running in paralell?