Creating an API for generating dynamic payment addresses

For creating dynamic wallet addresses on the fly for each payment request, we will be setting up an HD wallet for the merchant who is accepting payment for their products from the e-commerce gateway.

HD wallets allow us to create a set of hierarchical wallet addresses derived from the same mnemonic. If the merchant can safely preserve one mnemonic phrase, they can manage all of the addresses using the same string of words.

For providing dynamically generated, hierarchically linked addresses to our payment gateway, we'll be setting up a Node.js app with a get API service. The payment gateway can use this service to fetch a new address from the merchant's HD wallet:

  1. Create a new Node.js project directory as shown in the following. Let's call this hdwallet.
  2. Run the mkdir hdwallet command.
  1. Run npm init to create your package.json file.
  2. Start by updating package.json to the following values:
{
"name": "hdwallet",
"version": "1.0.0",
"description": "hdwallet",
"main": "app.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bip39": "^3.0.2",
"body-parser": "^1.19.0",
"ethereumjs-tx": "^2.0.0",
"ethereumjs-util": "^6.1.0",
"express": "^4.17.1",
"hdkey": "^1.1.1"
}
  1. Run npm install to install the dependencies.
  2. Let's start writing out app.js. Start by declaring all of the dependencies for our app, as shown here:
const bip39 = require('bip39')
const hdkey = require('hdkey')
const ethUtil = require('ethereumjs-util')
const ethTx = require('ethereumjs-tx')
const express = require("express");

In the preceding code, bip39, hdkey, Ethereumjs-util, and Ethereumjs-tx will be used for generating a new mnemonic and the subsequent hierarchical addresses. We'll talk more about these later.

We'll be using the express framework to create our API.

  1. Next, as shown in the following, we will declare our middleware layer. The middleware layer here allows CORS or Cross-Origin Resource Sharing. This is required so our gateway app can request a new merchant address from our API:
app.use(function (req, res, next) {

// Website to connect to. * indicates 'all'
res.setHeader('Access-Control-Allow-Origin', '*');

// Methods to allow access
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

// Request headers to allow access
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

// Send cookies
res.setHeader('Access-Control-Allow-Credentials', true);

// Move on to the next layer
next();
});
  1. Now, we will define our server settings. I am running mine on port 5000, as shown here. You can configure it as per your requirements:
var server = app.listen(process.env.PORT || 5000, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
  1. We will declare the pathid parameter. This parameter will keep a track of the last address index used to derive a hierarchical address and increment after generating a new address:
var pathid = 0;
  1. We will now start writing our API service, as shown here. The API will be a get service available at http://localhost:5000/api/getMAddress:
app.get("/api/getMAddress", function(req,res){

const mnemonic = bip39.generateMnemonic(); //generates string
console.log(mnemonic);

var sendResponseObject={};
var address;

Let's understand this code block and how it generates the mnemonic:

  • The bip39 module is used to generate a random mnemonic string. This string can be used to recover a wallet or import the wallet to a third-party wallet service provider such as MetaMask.
  • A mnemonic in the bip39 format looks somewhat like feature concert truth service energy egg able bind comfort candy harvest similar.
  • We also define our response object and address parameter.
  1. Next, we derive our seed and root address node from the mnemonic, as shown here. To do so, we make an asynchronous call to the bip39 method, mnemonictoSeed:
(async function main() {
try {
const seed = await bip39.mnemonicToSeed(mnemonic)
console.log("Seed:",seed);
  1. We derive the root node and the master public and private key for the root node, as shown here:
const root = hdkey.fromMasterSeed(seed)
const masterPrivateKey = root.privateKey.toString('hex');
console.log("Master private Key:",masterPrivateKey);
const masterPubKey = root.publicKey.toString('hex');
console.log("Master Public Key: ",masterPubKey);
  1. Next, we set the path for deriving the hierarchical addresses as shown in the following. Notice the pathid parameter at the end. As we increment the pathid parameter, the address index in the path changes. Hence, we have a new hierarchical address:
 var path = "m/44'/60'/0'/0/"+pathid;
console.log("root: ", root);
const addrNode = root.derive(path)
console.log("path: ", path);
  1. We will use the privateToPublic method to service the public key for the derived address node, as shown in the following. We also derive the hierarchical address in hex format with checksum using the publicToAddress and toCheckSumAddress methods under ethUtil:
const pubKey = ethUtil.privateToPublic(addrNode._privateKey)
console.log("Pubkey as hex:",pubKey.toString('hex'));

const addr = ethUtil.publicToAddress(pubKey).toString('hex');
console.log("pubkey to Addr:",addr);

address = ethUtil.toChecksumAddress(addr);
console.log("Address with Check sum:",address)

We now have our derived address in the address variable. We'll now return this in the request.

  1. We will add the MAddress key, which will hold the newly generated address and add this key and its value to the response body as shown in the following. We also increment the pathid parameter at the end of the asynchronous call so we get a new path and a new address next time. 

The app checks whether pathid is less than 100 before incrementing because the app is designed so that it loops between 100 hierarchical addresses. This is done so that the app only generates 100 new hierarchical addresses and then reuses the existing addresses. Our merchant wallet will track these 100 addresses for payments. If pathid is equal to or greater than 100, it resets it to zero instead of incrementing it again:

sendResponseObject['MAddress']= address;
let jsonString= JSON.stringify(sendResponseObject)
res.send(jsonString);

if (pathid < 100)
{
pathid++;
}
else
{
pathid = 0;
}
}catch(error) {
console.log(error);
};
})();

Now, we have our merchant wallet address generator ready.

  1. Start the application using node App.js. The app will print the mnemonic in the console on its first run. This mnemonic is generated only once and all addresses generated will be mapped to it. So, we need to copy and keep the mnemonic safe for future purposes.

In the next section, we will build the merchant wallet interface.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.216.174