4

I want to use blockchain API for my store but the wallet only monitoring last 20 generated address.

Quote from https://blockchain.info/api/api_receive:

As defined in BIP 44, wallet software will not scan past 20 unused addresses. Given enough requests from this API that don't have a matching payment, you could generate addresses past this horizon, which would make spending funds paid to those addresses quite difficult. For this reason, this API will return an error and refuse to generate new addresses if it detects it would create a gap of over 20 unused addresses. If you encounter this error, you will either need to switch to a new xPub (within the same wallet is fine), or receive a payment to one of the previous 20 created addresses

I googled about this problem and found some solutions such as:

Solutions that I found

  1. Check gap with blockchain checkgap API and don't generate new address until they have been paid.
  2. Increase gap limit on the receive api.
  3. Send money to the last unused address.

Problems with these Solutions

  1. If I have 20 unpaid address and they never been paid, solution #1 can not solve the problem. it just say I have 20 unpaid address.
  2. Solution #2 can not solve the main problem. Even I set the gap limit to the 100, How about the time that 101 curious users only want to see the checkout page and close it. I will get 100 unused address again.
  3. Solution #3 is not a nice solution to me. It seems like a bad practice to me and this is a solution that solved by spending money.

My Solution

If I get it right, when Blockchain generating the address, It will be there until it's getting paid. Correct me if I'm wrong, Blockchain will not callback until the user pay the amount. so I do this to solve the problem:

  1. Check the gap by API. If gap>19 goto #3 else #2.
  2. Generate the address and store it inside unpaid_address table based on the "index number" that blockchain returns with address. set expiration time for 30 minutes and go to the #4.
  3. Get the first expired unpaid address from unpaid_address table. If there isn't anything, show sorry server is busy, else goto #4.
  4. show the address to the user and say you have 15 minutes to pay to this address. (15 minutes less than expire time to avoid problems).
  5. If blockchain callback my URL and It has been paid before the expire time, I remove the address from unpaid_address else the address has been there for the next request by other user. I will give that address to the next user for paying.

Question

This solution give me the ability to never exceed gap limit. But I don't know if it's safe to give the address to a user and if he didn't pay on 30 minutes, give it to another user.

What do you think? Is it safe? or is there better solution?

About giving the address to multiple users

  1. First user see the checkout page in 8:20AM and send the amount to the address. but there is no confirmation in 15 minutes. the confirmation come in 11:00AM.
  2. Second user see the checkout page in 9:00AM and send the amount to the same address. there is confirmation in 9:10AM so I will return callback result as paid.

What about the first user confirmation on 11:00AM?

6
  • Related: bitcoin.stackexchange.com/questions/48090/… I like your #4 suggestion and is used in practice, time limits on paying an address is pretty common in online bitcoin retail solutions. If you don't put a time limit and use an HD wallet in a retail setting you will have users who don't follow the directions and you could possibly get multiple people paying the same address, or two people trying to claim a single payment.
    – m1xolyd1an
    Commented Apr 27, 2018 at 1:49
  • @m1xolyd1an I saw your answer on that question before. I mentioned that on solution #1 and my solution #1. so, If I expire the invoice after 15 minutes for the current user and give the same address to the next user, is it a safe practice?
    – ICE
    Commented Apr 27, 2018 at 2:15
  • 30 minutes is not very long, what happens if a user submits a transaction to the network, but it isn't mined within that time? Maybe the network is congested, or it takes longer than average to find a new block? If the system gives the same address to another and they also submits a payment it could get messy.
    – chytrik
    Commented Apr 27, 2018 at 10:32
  • 1
    @chytrik Is there any solution for the gap limit? The only thing that I can think of, is the time limit, expire the invoice and give the address to other user.
    – ICE
    Commented Apr 27, 2018 at 10:58
  • 1
    What if you suddenly have a lot of users (like 50) in a very short period of time, I don't see how your solution would be effective, you would still run out of unpaid addresses.
    – ethmz
    Commented May 29, 2018 at 10:45

5 Answers 5

5
+50

Blockchian.info is not really qualified to provide Bitcoin API's for business, 20 empty addresses are really cool and enough as a personal wallet but for business, it's not.

I suggest you find an alternative or use some payment gateways, or you can do the following but it's not really recommended.

  • Increase 20 address limit by getting more than blockchain wallet, When some user create an address check gap if it's over 18 change the xPub to the next xpub and go on.

  • 15 min time limit, if the user didn't pay within 15 min, give it to another user. Note: You don't have to wait for confirmations. Once you receive a transaction mark those addresses so you don't give them to another user.

  • Before you reach address number 20, pay a small amount automatically to that address so you get another 20 address.

UPDATE:

You can't create an xpub Programmatically (using blockchain.info api), but a new wallet

https://blockchain.info/api/create_wallet

You don't really want to do that, you can create like 5 xpub's keys and store them in your database, and just sweep between them.

blockchain.info

Settings --> Addresses --> + ADD. Click To create a new xpub key.

Manage --> Show xPub. To get your extended public key (xpub).

gif

2
  • Is there any way that I can generate new xPub on my code? I mean is it provided on blockchain API?
    – ICE
    Commented May 3, 2018 at 17:21
  • 1
    I've made an edit for the answer.
    – Tailer
    Commented May 3, 2018 at 23:34
1

IMHO it is not safe to give the address to a user immediately but, from my position, your proposed solution seems feasible with adjustment.

I would recommend ammending as follows:

  1. Check the gap by API. If **gap>x* goto #3 else #2.

  2. Generate the address and store it inside unpaid_address table based on the "index number" that blockchain returns with address. set expiration time for 60 minutes, store also the amount requested and go to the #4.

  3. Get the first expired unpaid address from unpaid_address table. Duplicate it if it is still marked as pending and store the amount also. If there isn't anything, show sorry server is busy, else goto #4.

  4. Show the address to the user and say you have 15 minutes to pay to this address. (15 minutes is less than expire time to avoid problems).

  5. I note that you seem to be using blockchin wallet but, you can do this in addition: If using Bitcoin Core (bitcoin-qt|bitcoind) set -walletnotify on the command line to execute a script, calling your callback URL with a status of pending if a transaction to any your address enters mempool (caveat: I only believe that walletnotify executes when a transaction to your wallet enters mempool - you will have to test this). Your script will need to extract the payto address and BTC amount to compare with the unpaid_address table. Further, walletnotify should run again when the transaction has its first confirmation, you can call your callback URL with a status of green after checking the transaction details. See How do I use walletnotify?.

  6. If blockchain callback my URL then I remove the address from unpaid_address else the address has been there for the next request by other user **if not even pending*. I will give that address to the next user for paying.

Note that on many wallets you can increase the gap limit to, say, 100 or 1000 as you have understood. I would certainly consider a gap limit of 1000 for the implementation that you propose.

Note also that you will need to carefully consider how to evaluate a transaction that exists that is not yet confirmed. Unless the fee is ridiculously low it should confirm eventually, even as much as more than 30 days is not inconceivable as I have experienced this with a moderate, but not particularly low fee targeting 3 day confirmation time.

I would also recommend storing the address along with the BTC amount requested and never remove it once it is marked as pending, although, in doing so there is no reason that you cannot re-use the address at some future time anyway (without removing it since you store the address and amount) provided, of course, that people pay the full amount exactly and without deducting the fees from the paid amount.

If you are selling high value good you might consider waiting until the payment is marked green before shipping as I beleive that this is what you have intended.

3
  • Please explain these to me: 1. Why did you change the expire time to 1 hour when you are saying low fee targeting 3 day confirmation time? what is the use of 1 hour expire time then? if it's like that, the user can send the amount to the address and see the expire invoice message. another user paying to the same address with more fee and get the invoice as paid in 10 min. then this could lead to a big flaw. 2. about storing address and amount and never remove it: how to satisfy callback with two users paid amount to the same address? Seems pretty dangerous. Check the edit on my question.
    – ICE
    Commented Apr 30, 2018 at 14:12
  • @ICE In my own case, a transaction targeting 3 day confirmation time (the fee was not exceptionally low) took so long. If you can make use of step 5 you should know about a transaction nearly immediately it is created. I know you tell the customer 15 minutes but, if you are giving them longer perhaps 1 hour is still more than is needed. The point is, log the address given and the amount requested. I envision you may often have the same address in your unpaid table several times with differing amounts. Once pending, provided the transaction is not dust, it should confirm eventually.
    – Willtech
    Commented May 1, 2018 at 11:06
  • @ICE In the case of my long pending transaction, my node kept re-broadcasting it every so often. I believe that the default (on Bitcoin Core) is to drop a transaction from mempool after fourteen days but, not when it is from your own wallet. Does your callback not include the amount?
    – Willtech
    Commented May 1, 2018 at 11:09
1

Possible solutions are very nicely listed in this article. Basically few options:

  1. Send small amount of funds to the 20th bitcoin address manually to keep things going
  2. Use a HD wallet like electrum that allows for a higher gap limit setting
  3. Switch to services like blockonomics that automatically send funds to the 20th addresses allowing merchant to keep on generating receiving addresses without any interruption
1

it's simple if you use multi xpubs, because there is no limit to generate wallet inside and by creating multi wallets inside you will be able to get multiple xpubs and then you can still set them as if one reach it's gap limit use another one. you can set unlimited xpub like this.

0

This way is safe for dynamically generating address; - notify the user to pay only withing 24 hours - reserve the address for the user for at least 1 day (2 days recommended) - run a cron job to reset the address after the 1 or 2 days

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.