I’m doing a project in which the users of my platform pay a certain amount of ADA to use a service. For this, my server machine provides them with an address to send the payment in order to use a specific service. I do not care to know which user sent the payment. But I do care to know that that payment was completed. To do this, in the wallet of my server machine, I review the transactions received and check the addresses of those transactions to verify that the payment was made. Since my platform will have multiple services that you can pay for, I will need multiple addresses that my wallet generates.
To do this, I am using the Cardano wallet API:
github: input-output-hk/cardano-wallet
For the generation of keys and addresses I use the Cardano official documentation library “Cardano Serialization Lib”:
Here comes the complicated part and you have to have knowledge of address generation in Cardano.
The cardano-wallet API provides a GET query to get a list of 20 unused addresses. To these addresses are added the addresses already used but the library has the obligation to always show 20 unused. This parameter is configured when creating a wallet with the name “address_pool_gap”, described in the following documentation:
An example of this GET query would be:
localhost:8090/v2/wallets/{addressId}/addresses
[{"state":"unused","id":"addr_test1qq6c8gvykc5aeq3hetxnrw6kzn3zpq6lw8m4t7p7yyc93swqd42kad2psa767zynpd2ut4mx54xh4ccu7ztc7d2wttcqg67nrk","derivation_path":["1852H","1815H","0H","0","0"]},
{"state":"unused","id":"addr_test1qq5qxxsr3ffjmx7mkjt6m40kepg3uprz0ueu9hnlv6gxnxwqd42kad2psa767zynpd2ut4mx54xh4ccu7ztc7d2wttcqm67z5t","derivation_path":["1852H","1815H","0H","0","1"]},
... (2, 3, ..., 18,)
{"state":"unused","id":"addr_test1qrfhrwljs07sy6jrgf9087pryeaq7rrmm0zvrh5pv0uk3ywqd42kad2psa767zynpd2ut4mx54xh4ccu7ztc7d2wttcqmge5rr","derivation_path":["1852H","1815H","0H","0","19"]},
{"state":"unused","id":"addr_test1qzgf2lhcq98zu82vu2vgrptxzu7q8asudwwncg5988a2thxqd42kad2psa767zynpd2ut4mx54xh4ccu7ztc7d2wttcqe0qufc","derivation_path":["1852H","1815H","0H","0","20"]}]
Since I’m going to need multiple addresses from where I’m going to receive payments, I cannot be satisfied with the 20 default addresses nor with 10000 setting the parameter “address_pool_gap” to the maximum (Although changing this parameter from “address_pool_gap” could slow down operations, as it says in the documentation. Which I don’t understand why).
So I decided to use Cardano Serialization Lib. I decided to create one by one addresses as they are needed. Using the following code described in the Cardano developer documentation. Serialization-Lib.
// base address with staking key
const baseAddr = CardanoWasm.BaseAddress.new( CardanoWasm.NetworkInfo.testenet().network_id(), CardanoWasm.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()), CardanoWasm.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()));
Since all addresses start from the same root key for their generation. Following the BIP-44 standard → “1852H”, “1815H”, “0H”, “0”, “0” You get the same addresses as those provided by the cardano-wallet API. I mean, those of the GET query discussed above. You only have to increase the final derivation value that generates a new address, in this way:
“1852H”, “1815H”, “0H”, “0”, “1”,
“1852H”, “1815H”, “0H”, “0”, “2”,
“1852H”, “1815H”, “0H”, “0”, “n”,
etc.
The problem comes when I’m going to generate the address number 21. By having the parameter in “address_pool_gap” set to 20 in the wallet, the address 21 does not receive payments sent from a Daedalus wallet. It only works if you increment the value of “address_pool_gap” or if you use one of the unused addresses at least. For example, for address 22 you would need to previously use 2 of the 20 unused and so on. Due to this, the following two addresses would automatically be created, that is, 21 and 22. In this way they would already be available to use (payments are received). I don’t understand why this is so.
So I finally decided to create enterprise addresses as follows:
// enterprise address without staking ability, for use by exchanges/etc
const enterpriseAddr = CardanoWasm.EnterpriseAddress.new( CardanoWasm.NetworkInfo.mainnet().network_id(), CardanoWasm.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()));
These addresses are shorter (they have fewer characters) but I can create as many as I want and at any time they are available to receive payments. Here are my doubts:
-
What is the difference between enterprise addresses and base addresses?
-
Why does a payment to a “base address” with a derivation index higher than “address_pool_gap” not receive the ADAs when I show the wallet balance?
-
How can I make address 21 receive payments without having to use an address from 0 to 20 and without modifying the “address_pool_gap” parameter?
-
Why does modifying the “address_pool_gap” parameter cause performance degradation as stated in the documentation?
-
What security problems can the distribution of “enterprise address” have? I mean, could a malicious person discover the recovery phrases and access the wallet?
-
This approach of generating several addresses from the same public key so that they can make payments and in this way find out that the transaction was completed, is it the most correct?
All my respects to those who know how to resolve these doubts as they don’t seem simple. Consider yourself an expert in using Cardano if you know how to solve them