니모닉 지갑을 개발해보자

vinson·2022년 4월 7일
0

BlockChain 매운맛

목록 보기
2/3
post-thumbnail

니모닉 ?

니모닉(Mnemonic)은 지갑을 복구하기 위한 일반적인 단어들의 조합을 뜻한다.

니모닉 Wallet은 비밀 키 관리를 용이하게 해준다.
사실 암호화폐 지갑에는 코인이 들어있지 않고 정확하게는 비밀 키가 들어있다. 이 때 비밀키를 복구(리커버리) 할 수 있는게 니모닉이다.

지갑 개발 과정

  • eth-lightwallet 모듈을 사용해 개발을 해본다.
  • Postman을 사용해 API 테스트

1. newMnemonic API 만들기

router.post('/newMnemonic', async(req,res) => {
  let mnemonic;
  try {
      mnemonic = lightwallet.keystore.generateRandomSeed();
      res.json({mnemonic});
  } catch(err) {
      console.log(err);
  }
});
  • mnemonic 변수를 만든다
  • mnemonic 변수에 (응답)lightwallet.keystore.generateRandomSeed()를 담아, mnemonic을 응답으로 전송한다.
  • (에러) 에러를 응답한다.

2. Postman으로 테스트하고 니모닉 코드 얻기

  • 로컬 서버를 실행하고, 엔드포인트를 입력한다.
  • 엔드포인트 : http://localhost:3000/wallet/newMnemonic
  • Postman에 POST를 send하여 서버로 요청.
  • 위와같이 서버가 니모닉 코드를 반환한다.

3. mnemonic code와 password를 이용해 newWallet API 만들기

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);
    }
});
  • passwordmnemoic을 입력값으로 서버에 요청
  • 이 때 변수는 req.body를 통해 할당
  • (오류) 에러를 응답.
  • (응답) lightwallet.keystore.createVault를 사용하여 키스토어 생성
  • 첫번째 인자(options)에는 password, seedPhrase, hdPathString을 담습니다.
  • 두번째 인자(callback)에는 키스토어를 인자로 사용하는 함수를 만듭니다.
  • eth-lightwallet 모듈의keystore.keyFromPassword(password, callback) 내장 함수를 사용합니다.
  • 첫번째 인자에는 password, 두번째 인자(callback)에는 pwDerivedKey를 인자로 사용하는 함수를 만듭니다.
  • 두번째 콜백함수가 실행되면, eth-lightwallet 모듈의 - keystore.generateNewAddress(pwDerivedKey, [num])을 이용해 새로운 주소 생성 함수를 실행합니다.
  • address 변수를 만들고, keystore.getAddresses()을 문자열로 할당합니다.
  • keystore 변수를 만들고, keystore.serialize()을 할당합니다.
    위에서 만들어준 변수를 응답으로 전송합니다.

4. Postman을 이용해 keystoreaddress의 응답 API테스트

5. 생성된 keystore를 json파일로 만들어 로컬 서버에 저장

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();

          fs.writeFile('wallet.json',keystore,function(err,data){
            if(err) {
                res.json({code:999,message:"실패"});
            } else {
                res.json({code:1,message:"성공"});
            }
          });
        });
      }
    );
  } catch (exception) { 
    console.log("NewWallet ==>>>> " + exception);
  }
});
  • wallet/index.js 파일에 fs 모듈을 import 합니다. (fs 모듈은 Node.js 내장 모듈입니다.)
  • 3.의 함수 keyFromPassword의 콜백 함수에서, 응답대신 fs.writeFile 또는 fs.writeFileSync 를 사용합니다.
  • 첫번째 인자에는 .json 형식의 파일이름을, 두번째 인자에는 keystore 을 입력합니다.
  • 세번째 인자에는 응답에 대한 콜백 함수를 입력합니다.
  • 로컬 서버에 파일을 저장하기 때문에, 응답으로는 성공 또는 실패 메세지만 전송합니다.

6. Postman을 실행하여, 로컬에 키스토어 파일이 생기는지 확인


전체 코드

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

router.post('/newMnemonic', async(req,res) => {
  let mnemonic;

  try {
	mnemonic = lightwallet.keystore.generateRandomSeed();
	res.json({mnemonic});
  } catch(err) {
	console.log(err);
	res.json({message: err});
  }
});


router.post('/newWallet', async(req, res) => {
  const password = req.body.password;
  const mnemonic = req.body.mnemonic;

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

		const addresses = ks.getAddresses();
		const keystore = ks.serialize();

		fs.writeFile('wallet.json', keystore, (err) => {
		  if(err) {
			res.json({message: 'Failed to create new wallet'});
		  } else {
			res.json({address: addresses[0], message: 'Successfully created new wallet'});
		  }
		});
	  });
	});
  } catch(err) {
	console.log(err);
	res.json({message: err});
  }
});

module.exports = router;

회고

공식문서를 참고하면 큰 어려움 없이 진행할 수 있다. 이해가 잘 되지 않는 부분은 stackoverflow를 참고하면 워낙 기초적인 내용이라 금방 찾을 수 있었다. 개념을 이해했으면 직접 개발해보는게 체화하는데 도움이 된다. package를 이용해 개발했지만 기회가 되면 바닥부터 직접 개발해보고 싶다.

https://github.com/livermore2025/MnemonicWallet

profile
Pay it forward

0개의 댓글