How to create your own Mnemonic Wallet API for Ethereum

Jinwoo CheonJinwoo Cheon
4 min read

What is Mnemonic?

Well for starters, mnemonic in the blockchain world refers to a set of words that are used recover a crypto wallet.

Crypto wallets use asymmetric key algorithm so you'll have a 'public key' and a 'private key'. With just the private key one can figure out the public key but the opposite is not possible. And obviously that means your private key is very important.

But when your private key is expressed like below it is obviously not easy to remember. Zeros(0) and Os(O) can be confusing as well when you handwrite your private key to a paper (which a lot of crypto users do to prevent keys from being hacked).

Private Key: 5KRQ7XK5oU48pqABR2bkiwqP6oZj2W1Fb6stJgjdoNhBZsVYK7m

In order to remember or write down your private key in a more intuitive way, we can turn it into mnemonic words. The process behind this is as below.

image.png

image.png

Let's make our own Mnemonic Wallet API Server ๐Ÿš€

1) Preparation

We'll be using:

  • eth-lightwallet to create random mnemonic codes and turn them into a keystore
  • Express to create a local API
  • Postman to check results
  • fs module to store the key in local

For starter code: HERE

After downloading the starter code start off with npm i to install the required dependencies.

We'll be working with the routes/wallet.js file. A simple express app.js that'll import the wallet file is already coded up like below.

const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');

const walletRouter = require('./routes/wallet');

const app = express();
const port = 3000;

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(
  cors({
    origin: ['http://localhost:3000'],
    methods: ['GET', 'POST'],
    credentials: true
  })
);

app.get('/', function(req, res, next) {
  res.status(200).send({"message": "Mnemonic server is running..."});
});
app.use('/wallet', walletRouter);

// catch 404 and forward to error handler
app.use((req, res, next) => {
  const err = new Error('Not Found');
  err['status'] = 404;
  next(err);
});

// error handler
app.use((err, req, res, next) => {
  res.status(err.status || 500);
  res.json({
      errors: {
          message: err.message,
      },
  });
});

app.listen(port, () => {
  console.log(`
  ################################################
  ๐Ÿ›ก๏ธ  Server listening on port: ${port} ๐Ÿ›ก๏ธ
  http://localhost:${port}
  ################################################
  `);
});

module.exports = app;

2) Creating newMnemonic API

In the routes/wallet.js we can simply use eth-lightwallet to generate random seed for the mnemonic code.

const express = require('express');
const router = express.Router();
const lightwallet = require("eth-lightwallet");
const fs = require('fs');

// TODO : use lightwallet module to create random mnemonic code
router.post('/newMnemonic', async(req,res) => {
    let mnemonic;
    try {
        mnemonic = lightwallet.keystore.generateRandomSeed();
        res.json({mnemonic});
    } catch(err) {
        console.log(err);
    }
});

And I've checked that it functions with Postman. A mnemonic code was returned.

image.png

3) Creating newWallet API

We only have the mnemonic code at the moment. So now we're going to request the keystore and address from our API server by sending in the mnemonic and password of our choice.

lightwallet.keystore.createVault is used for this.

We pass in the password, seedPhrase, hdPathString for options and in the callback we use the functions: keystore.keyFromPassword(password, callback) and keystore.generateNewAddress(pwDerivedKey, [num]).

Save address and keystore to return as response. (using keystore.getAddresses() and keystore.serialize())

// TODO : use mnemonic code and password to create keystore & address
router.post('/newWallet', async(req, res) => {
    let password = req.body.password
    let mnemonic = req.body.mnemonic;

    try {
      lightwallet.keystore.createVault(
        {
          password: password, 
          seedPhrase: mnemonic,
          hdPathString: "m/0'/0'/0'"
        },
        function (err, ks) {
            ks.keyFromPassword(password, function (err, pwDerivedKey) {
            ks.generateNewAddress(pwDerivedKey, 1);

            let address = (ks.getAddresses()).toString();
            let keystore = ks.serialize();

            res.json({ keystore: keystore, address: address });
          });
        }
      );
    } catch (exception) { 
      console.log("NewWallet ==>>>> " + exception);
    }
});

And with Postman we can check that our local API server returns a keystore and address properly.

image.png

4) Saving keystore on local server

If you want you can replace the newWallet API response like below.

It'll no longer return the keystore and wallet as a server response but save it as a json file on the server.

fs.writeFile('wallet.json',keystore,function(err,data){
   if(err) {
        res.json({code:999,message:"Failed"});
    } else {
        res.json({code:1,message:"Success"});
    }
});

With this change, when we call the server we'll only get a 'success' response. And the keystore will be saved as a json file.

image.png

image.png

Inside that json file it'll look like this:

{"encSeed":{"encStr":"wA3c+1Ub3nKGNSFRdXYebeePZXRFgsaKqrhvn0sFe6WTyp/uSwrqWs77dsGZLA/8JQq8OxUhlE+nqCOjXH3/lhTa/7JJQ/LAgWhajwgAruFGre6gq08AGhshE8qK9XTkUqqks6x7gAQIZyoBclRWLbpf8iUL+gJpJp/+inbuhRlBewRvMSQXDQ==","nonce":"t7VykU0PENO37RNUJiIdmFJozWl8jLqM"},"encHdRootPriv":{"encStr":"+nGvncTU5pJiXKHBf7SdBbmyeWom0GHx1Qh9ibuNBavc1Utctq9Ew/4kkSg2axpJxFROf/fKlIai/t3ItoElwg7ZdAMkh3NhCZXXgqx2aDr56zXGtNDdnddzBdUZd7lguXr1NxHjDcuNbFaEmKW5UEWA8cvvUGFCuR4l9LRMfQ==","nonce":"TvIE0pV34lawGQTlCGptrrAyfud9gCWm"},"addresses":["821f5000f463c95ef5662590a98724e16b8dc884"],"encPrivKeys":{"821f5000f463c95ef5662590a98724e16b8dc884":{"key":"rEAP+LADhqGMEbgXyia9q+8zmQLFWfFGGWktSgtv71IREL8WjiScF0ttWqdXqRGX","nonce":"yKrB5C51mxCL537zuZC9aDCCCruo8APs"}},"hdPathString":"m/0'/0'/0'","salt":"HPE+2W31twXQ8KTBVR9SCzJpvTBDjEKYM5aGYLRg0a0=","hdIndex":1,"version":3}

And that's it!

If you have followed along well you'll have your own local API server that can be used to request a mnemonic code and turn that into a keystore & address for your use in blockchain.

Check out the full code here.

Hope that helped and sparked some new ideas :)

0
Subscribe to my newsletter

Read articles from Jinwoo Cheon directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jinwoo Cheon
Jinwoo Cheon

Former PO @ Naver Financial. Now working my way to become a pro Web3 Dev w/ Solidity and React. Passionate about NFTs.