<p>If you want to do Bitcoin stuff in nodejs, I recommend using bcoin:</p>

<p>repo: <a href="https://github.com/bcoin-org/bcoin" rel="nofollow noreferrer">https://github.com/bcoin-org/bcoin</a></p>

<p>docs, guides: <a href="https://bcoin.io" rel="nofollow noreferrer">https://bcoin.io</a></p>

<p>It has a fully-validating full node implementation, SPV implementation, and BIP44 wallet that is used by Purse.io and several other Bitcoin-accepting merchants for this exact use case: Each customer gets a dedicated account and the wallet can track balances per-user, generating new addresses each time the current receive is used (a la BIP44)</p>

<p>You can set up your server with a watch-only wallet to report incoming deposits, and keep the private keys either offline or on more secure, local machine.</p>

<p>Example:</p>

<h3>On secure or offline machine:</h3>

<pre><code>$ bcoin --daemon
$ bwallet-cli mkwallet --witness=true --id=HOT
$ bwallet-cli --if=HOT account get default
{
  "name": "default",
  "initialized": true,
  "witness": false,
  "watchOnly": false,
  ..
  "accountKey": "tpubDD3BFBuLYg2cspeDSWZgo9qv4qYi7KQF5oov8theqbFRUFqXPmsowPqAY1PQqnEdUe5JrFqf8ZGWLwEQEKB5WjJjxgMwcXmFuu1XDrG4RSr",
  ..
}
</code></pre>

<h3>On "hot" production server:</h3>

<pre><code>$ bcoin --daemon
$ bwallet-cli mkwallet --id=WATCH --watch-only=true --account-key=tpubDD3BFBuLYg2cspeDSWZgo9qv4qYi7KQF5oov8theqbFRUFqXPmsowPqAY1PQqnEdUe5JrFqf8ZGWLwEQEKB5WjJjxgMwcXmFuu1XDrG4RSr
$ bwallet-cli --id=WATCH address default
{
  "name": "default",
  "account": 0,
  "branch": 0,
  "index": 1,
  "witness": false,
  "nested": false,
  "publicKey": "026f1afcab2942fd932760557943b287957bb8aa6ebe0f8dc64fa25862e23d52a2",
  "script": null,
  "program": null,
  "type": "pubkeyhash",
  "address": "mjdcszSLXHd6awrnM4bgJiFEbTFZdyw7de"
}
</code></pre>

<p>...etc</p>

<p>From here you can use API calls to create transaction templates and sign them on the offline machine.</p>

<p>If you are queasy about running an alternative implantation of Bitcoin, you can still run bitcoind on the hot server and run bcoin behind it (even in SPV mode) with bitcoind as it's <code>--only=</code> peer, like a Bitcoin Core Firewall</p>

<hr>

<p>(edit)</p>

<h3>Generate static addresses</h3>

<pre><code>'use strict';

const bcoin = require('bcoin');
const m = bcoin.Mnemonic.fromPhrase(
  'abandon abandon abandon abandon abandon abandon'
  + ' abandon abandon abandon abandon abandon about');
const master = bcoin.HDPrivateKey.fromMnemonic(m);
const key0 = master.derivePath("m'/44'/0'/0'/0/0");
const ring0 = new bcoin.KeyRing({privateKey: key0});
console.log(ring0)
</code></pre>

<p>Will output:</p>

<pre><code>{
  witness: false,
  nested: false,
  publicKey: '03aaeb52dd7494c361049de67cc680e83ebcbbbdbeb13637d92cd845f70308af5e',
  script: null,
  program: null,
  type: 'pubkeyhash',
  address: '1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA'
}
</code></pre>

<p>You can verify this is address 0 from that mnemonic phrase using <a href="https://iancoleman.io/bip39/" rel="nofollow noreferrer">https://iancoleman.io/bip39/</a> and of course because this phrase is so abysmally insecure and used by developers testing on mainnet (sigh) there are several transactions to this address: <a href="https://blockstream.info/address/1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA" rel="nofollow noreferrer">https://blockstream.info/address/1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA</a></p>

CC BY-SA 4.0
2020-06-08T13:08:10.877Z
I haven't tried this but in my case, I only want to generate addresses for a single account. It's not a wallet and I don't have any users, I just want multiple receiving public addresses for my own account. Won't this be overkill for that?
Himanshu Chandra
CC BY-SA 4.0
2020-06-08T14:21:48.943Z
I added a new section to my answer that demonstrates how to generate static addresses from a minimal script using a phrase. This is the same logic the bcoin wallet uses. I noticed your phrase in the original question had a checksum error, so I'm demonstrating with a null mnemonic (a private key of all 0's, commonly used in testing)
pinhead
CC BY-SA 4.0
2020-06-11T00:31:05.423Z
I tried using the static method and the address I got in ring0.address is exactly same as I got using the method I added in question => address0.  And also changing last digit of m'/44'/0'/0'/0/0 to 1 gives me address1 and so on. So I guess I am already generating the right address but when I sent some bitcoin to the address, none showed up in the account? Why is my account balance still 0 if the address is right?
Himanshu Chandra
CC BY-SA 4.0
2020-06-11T00:42:03.000Z
What wallet software are you using to check the account balance?
pinhead
CC BY-SA 4.0
2020-06-11T11:35:33.567Z
edge wallet https://edge.app/
Himanshu Chandra
CC BY-SA 4.0
2020-06-11T11:49:27.093Z
So your wallet shows you an address. You send BTC to that address, and the wallet never receives it? Are you sure your transaction was broadcast over the network? Can you find it on any block explorers?
pinhead
CC BY-SA 4.0
2020-06-11T12:56:59.757Z
No, the address that wallet shows works but when I try to generate more public addresses as above using the seed phrase from the app, then it doesn't work
Himanshu Chandra
CC BY-SA 4.0
2020-06-11T13:02:28.130Z
This is the transaction https://blockchair.com/bitcoin/transaction/1293da90d81506041571f7aee138f2bcb0dc1e489ceb078a5ed02f84d5b43c07
Himanshu Chandra
CC BY-SA 4.0
2020-06-11T13:05:45.400Z
Oh, contact edge or look through their documentation. Not all wallets derive keys along the same path. There is unfortunately no standard for this and different wallet developers will use different BIP44 paths for native/nested segwit addresses, etc. See BIP84 and BIP49
pinhead
CC BY-SA 4.0
2020-06-12T09:40:09.390Z
I couldn't find the standard for edge wallet in their docs. Can you suggest me any other wallet where I can test this?
Himanshu Chandra
CC BY-SA 4.0
2020-06-06T12:20:49.083Z
2020-06-08T14:20:47.390Z
2020-06-08T14:20:47.390Z
pinhead
<p>I want to generate a new receiving address for my bitcoin wallet for each new user. Bitcoin transferred to all these address should be received in my bitcoin wallet. I don't want to expose my private key or seed on the server.I found that this is how HD wallets work so I tried this.</p>

<pre><code>const bip39 = require('bip39')
const bitcoin = require('bitcoinjs-lib')   //ver 3.0.2

let phrase = 'width humor wheat sad obscure outer ancient grab edit labor record express devote humble recipe occur refuse tooth original fluid learn scheme fuel assault';
let seedBuffer = bip39.mnemonicToSeedSync(phrase)
// &lt;Buffer 85 19 18 81 cf 0e cc f7 9c 5d 61 ......

let masterNode = bitcoin.HDNode.fromSeedBuffer(seedBuffer)
// Deriving the first account based on BIP44
let account0 = masterNode.derivePath("m/44'/0'/0'")

let xpubString = account0.neutered().toBase58()
console.log(xpubString)
let address0FromXpub = bitcoin.HDNode.fromBase58(xpubString)


let address0 = address0FromXpub.derivePath("0/0").keyPair.getAddress()
let address1 = address0FromXpub.derivePath("0/1").keyPair.getAddress()
let address2 = address0FromXpub.derivePath("0/2").keyPair.getAddress()
let address3 = address0FromXpub.derivePath("0/3").keyPair.getAddress()
// address0.toBase58()
console.log("address0",address0)
console.log("address1",address1)
console.log("address2",address2)
console.log("address3",address3)
</code></pre>

<p>but I tried sending bitcoin to the generated address and didn't received any? If anyone could help.</p>

CC BY-SA 4.0
2020-06-05T14:58:30.377Z
Which address did you send to? Additionally, your code above has a seed phrase in it, so you're not really hiding the keys on your server
Raghav Sood
CC BY-SA 4.0
2020-06-06T11:58:27.010Z
I used address0 and address1. Once I have generated the xpubString I don't need to use the above steps again so only the extended key generation code will be on server.
Himanshu Chandra
<wallet><bip32-hd-wallets><public-key><mnemonic-seed>
Generate multiple public bitcoin receiving addresses (HD wallet) from seed phrase in nodejs
Himanshu Chandra
# Generate multiple public bitcoin receiving addresses (HD wallet) from seed phrase in nodejs

(Asked by: username_0 on 2020-06-05)

I want to generate a new receiving address for my bitcoin wallet for each new user. Bitcoin transferred to all these address should be received in my bitcoin wallet. I don't want to expose my private key or seed on the server.I found that this is how HD wallets work so I tried this.

```
const bip39 = require('bip39')
const bitcoin = require('bitcoinjs-lib')   //ver 3.0.2

let phrase = 'width humor wheat sad obscure outer ancient grab edit labor record express devote humble recipe occur refuse tooth original fluid learn scheme fuel assault';
let seedBuffer = bip39.mnemonicToSeedSync(phrase)
// <Buffer 85 19 18 81 cf 0e cc f7 9c 5d 61 ......

let masterNode = bitcoin.HDNode.fromSeedBuffer(seedBuffer)
// Deriving the first account based on BIP44
let account0 = masterNode.derivePath("m/44'/0'/0'")

let xpubString = account0.neutered().toBase58()
console.log(xpubString)
let address0FromXpub = bitcoin.HDNode.fromBase58(xpubString)

let address0 = address0FromXpub.derivePath("0/0").keyPair.getAddress()
let address1 = address0FromXpub.derivePath("0/1").keyPair.getAddress()
let address2 = address0FromXpub.derivePath("0/2").keyPair.getAddress()
let address3 = address0FromXpub.derivePath("0/3").keyPair.getAddress()
// address0.toBase58()
console.log("address0",address0)
console.log("address1",address1)
console.log("address2",address2)
console.log("address3",address3)

```

but I tried sending bitcoin to the generated address and didn't received any? If anyone could help.

**Tags:** wallet, bip32-hd-wallets, public-key, mnemonic-seed

> **Comments:**
> **username_1**: Which address did you send to? Additionally, your code above has a seed phrase in it, so you're not really hiding the keys on your server  
> **username_0**: I used address0 and address1. Once I have generated the xpubString I don't need to use the above steps again so only the extended key generation code will be on server.  

---

## 1 answers

### Answer by username_2 on 2020-06-06. Score: 0 | Accepted answer

If you want to do Bitcoin stuff in nodejs, I recommend using bcoin:

repo: <https://github.com/bcoin-org/bcoin>

docs, guides: <https://bcoin.io>

It has a fully-validating full node implementation, SPV implementation, and BIP44 wallet that is used by Purse.io and several other Bitcoin-accepting merchants for this exact use case: Each customer gets a dedicated account and the wallet can track balances per-user, generating new addresses each time the current receive is used (a la BIP44)

You can set up your server with a watch-only wallet to report incoming deposits, and keep the private keys either offline or on more secure, local machine.

Example:

### On secure or offline machine:

```
$ bcoin --daemon
$ bwallet-cli mkwallet --witness=true --id=HOT
$ bwallet-cli --if=HOT account get default
{
  "name": "default",
  "initialized": true,
  "witness": false,
  "watchOnly": false,
  ..
  "accountKey": "tpubDD3BFBuLYg2cspeDSWZgo9qv4qYi7KQF5oov8theqbFRUFqXPmsowPqAY1PQqnEdUe5JrFqf8ZGWLwEQEKB5WjJjxgMwcXmFuu1XDrG4RSr",
  ..
}

```

### On "hot" production server:

```
$ bcoin --daemon
$ bwallet-cli mkwallet --id=WATCH --watch-only=true --account-key=tpubDD3BFBuLYg2cspeDSWZgo9qv4qYi7KQF5oov8theqbFRUFqXPmsowPqAY1PQqnEdUe5JrFqf8ZGWLwEQEKB5WjJjxgMwcXmFuu1XDrG4RSr
$ bwallet-cli --id=WATCH address default
{
  "name": "default",
  "account": 0,
  "branch": 0,
  "index": 1,
  "witness": false,
  "nested": false,
  "publicKey": "026f1afcab2942fd932760557943b287957bb8aa6ebe0f8dc64fa25862e23d52a2",
  "script": null,
  "program": null,
  "type": "pubkeyhash",
  "address": "mjdcszSLXHd6awrnM4bgJiFEbTFZdyw7de"
}

```

...etc

From here you can use API calls to create transaction templates and sign them on the offline machine.

If you are queasy about running an alternative implantation of Bitcoin, you can still run bitcoind on the hot server and run bcoin behind it (even in SPV mode) with bitcoind as it's `--only=` peer, like a Bitcoin Core Firewall

---

(edit)

### Generate static addresses

```
'use strict';

const bcoin = require('bcoin');
const m = bcoin.Mnemonic.fromPhrase(
  'abandon abandon abandon abandon abandon abandon'
  + ' abandon abandon abandon abandon abandon about');
const master = bcoin.HDPrivateKey.fromMnemonic(m);
const key0 = master.derivePath("m'/44'/0'/0'/0/0");
const ring0 = new bcoin.KeyRing({privateKey: key0});
console.log(ring0)

```

Will output:

```
{
  witness: false,
  nested: false,
  publicKey: '03aaeb52dd7494c361049de67cc680e83ebcbbbdbeb13637d92cd845f70308af5e',
  script: null,
  program: null,
  type: 'pubkeyhash',
  address: '1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA'
}

```

You can verify this is address 0 from that mnemonic phrase using <https://iancoleman.io/bip39/> and of course because this phrase is so abysmally insecure and used by developers testing on mainnet (sigh) there are several transactions to this address: <https://blockstream.info/address/1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA>

> **Comments:**
> **username_0**: I haven't tried this but in my case, I only want to generate addresses for a single account. It's not a wallet and I don't have any users, I just want multiple receiving public addresses for my own account. Won't this be overkill for that?  
> **username_2**: I added a new section to my answer that demonstrates how to generate static addresses from a minimal script using a phrase. This is the same logic the bcoin wallet uses. I noticed your phrase in the original question had a checksum error, so I'm demonstrating with a null mnemonic (a private key of all 0's, commonly used in testing)  
> **username_0**: I tried using the static method and the address I got in ring0.address is exactly same as I got using the method I added in question => address0.  And also changing last digit of m'/44'/0'/0'/0/0 to 1 gives me address1 and so on. So I guess I am already generating the right address but when I sent some bitcoin to the address, none showed up in the account? Why is my account balance still 0 if the address is right?  
> **username_2**: What wallet software are you using to check the account balance?  
> **username_0**: edge wallet https://edge.app/  
> **username_2**: So your wallet shows you an address. You send BTC to that address, and the wallet never receives it? Are you sure your transaction was broadcast over the network? Can you find it on any block explorers?  
> **username_0**: No, the address that wallet shows works but when I try to generate more public addresses as above using the seed phrase from the app, then it doesn't work  
> **username_0**: This is the transaction https://blockchair.com/bitcoin/transaction/1293da90d81506041571f7aee138f2bcb0dc1e489ceb078a5ed02f84d5b43c07  
> **username_2**: Oh, contact edge or look through their documentation. Not all wallets derive keys along the same path. There is unfortunately no standard for this and different wallet developers will use different BIP44 paths for native/nested segwit addresses, etc. See BIP84 and BIP49  
> **username_0**: I couldn't find the standard for edge wallet in their docs. Can you suggest me any other wallet where I can test this?  

---

