본문 바로가기
etc/블록체인 뉴딜일자리사업

KAS와 node.js를 이용한 블록체인 지갑 기능 구현하기 3 - 토큰 발행, 토큰 확인

by vellahw 2023. 6. 30.

 

📁 이전글

2023.06.26 - [Dev/블록체인 뉴딜일자리사업] - KAS와 node.js를 이용한 블록체인 지갑 기능 구현하기

2023.06.28 - [Dev/블록체인 뉴딜일자리사업] - KAS와 node.js를 이용한 블록체인 지갑 기능 구현하기 2 - 로그인, 회원가입 기능

 

회원가입과 로그인 기능까지 구현해보았고 이제 토큰 발행과 마이페이지를 통해 내 지갑 주소와 가지고 있는 토큰의 개수를 확인해보겠다.


 

✔️ Account Pools 생성

우리는 회원가입을 함과 동시에 유저의 지갑을 만들어주도록 했다. 그 지갑들은 Accounts Pools를 생성하면 확인할 수 있다.

Account Pools 탭에 접속해 생성 버튼을 누르고 이름을 지정해주면 Pool이 생성된다.

 

이때 상단의 네트워크가 바오밥인 것을 확인 할 것!

 

 

어카운트풀을 뒤늦게 생성했어도 이렇게 생성된 지갑들이 뜰 것이다!

 

 

 

✔️ 토큰 발행하기

caver.js-ext-kas 모듈을 사용한 kip7.js 파일을 작성하면서 토큰을 생성하는 함수를 만들었었다. (해당 게시글)

별도의 페이지를 만들지 않고 js 파일 내에서 함수를 호출하여 토큰을 생성하고, 그때 얻은 토큰 생성 컨트랙트 주소를 kip7.json 파일에 넣어뒀었는데, 페이지를 만들어 발행하기 위해 기존에 작성한 함수를 조금 수정해보겠다!

 

토큰 발행은 일반 유저가 아닌 관리자의 권한이라고 해주고, 관리자 번호(아이디)로 로그인 했을 때 토큰 발행 페이지로 이동하게 구현해보았다.

 

main.js 파일을 열고, post 방식 요청 /signin 주소 코드의 DB와의 커넥션 부분(?)을 아래와 같이 수정해주자.

(여기를 수정)

// 생략

if(result.length != 0) {
    if(input_phone == '01099998888') { // 관리자라는 조건
        // 세션에 데이터 저장
        req.session.admin = result[0] // 관리자 저장 키: admin
    } else {
        req.session.logined = result[0] // 일반 유저 저장 키: logined
    }
}
                    
// 생략

올려놓기 민망하지만 시간이 없는 관계로... 조건문으로 나름의 인터셉터를 구현해봤다. 

01099998888이라는 번호를 관리자 아이디라고 가정하고, 로그인 폼에 입력한 번호가 01099998888이라면 세션에 admin 이라는 키로 회원 정보 조회 결과를 저장했다.

일반 유저라면 기존 코드와 동일하게 logined라는 키로 결과를 저장했다.

 

router.get('/', (req, res)=>{
    if(req.session.admin){ // 로그인 계정이 관리자라면
        return res.render('create_token.ejs')
    } 
    if(req.session.logined) {
        return res.redirect('/main') // 세션에 로그인 있다면 main 보여줌
    }
    if(!req.session.logined) {
        // Session logined에 데이터가 존재하지 않는다면 login.ejs 보여줌
        return res.render('login.ejs')
    }
})

그리고 main.js의 로그인 요청에 따라 메인 페이지를 달리 보여주던 get 방식 요청의 '/' 주소 코드를 위와 같이 수정해주었다.

req.session.admin이 true라면, 즉 로그인한 유저가 관리자(01099998888)라면 create_token.ejs를 렌더링한다.

동일하게 req.session.logined가 true라면 즉, 로그인한 유저가 일반유저라면 메인페이지로 리다이렉트하고, 로그인 데이터가 존재하지 않는다면 로그인 페이지를 보여준다.

 

관리자 로그인 시 보여질 create_token.ejs는 아래와 같이 작성했다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Publish Token</title>
    <style>
        body {
            padding: 15px;
            text-align: center;
        }

        input {
            border: 1px solid darkgray;
            border-radius: 20px;
            height: 30px;
            margin-bottom: 10px;
            padding-left: 10px;
            width: 180px;
            font-size: 11px;
            outline: none;
        }
        
        input::placeholder  {
            color: darkgray;
        }
        
        .btn {
            width: 193px;
            color: white;
            background-color: black;
            cursor: pointer;
            font-weight: bold;
            border: none;
        }
    </style>
</head>
<body>
    <h3>토큰 발행하기</h3>
    <!-- 토큰의 이름, 심볼, 소수점, 발행량 입력하는 공간 -->
    <form action="/token/create" method="get">
        <input type="text" name="_name" placeholder="Name"><br>
        <input type="text" name="_symbol" placeholder="Symbol"><br>
        <input type="number" name="_decimal" placeholder="Decimal"><br>
        <input type="number" name="_amount" placeholder="Amount"><br>
        <input type="submit" value="발행" class="btn">
    </form>
</body>
</html>

단순히 토큰 발행시 필요한 토큰의 이름, 심볼, 소수점 자리, 발행할 양을 입력할 폼을 만들었다.

 

 

관리자 아이디로 로그인하면 위와 같이 토큰 발행 페이지가 보여진다.

form이 전송되면 이동할 주소 '/token/create'에 대한 처리는 token.js 파일에 아래와 같이 작성했다.

저번 글에서 main.js에 회원에 관련된 기능들을 모아 작성했으니, token.js엔 토큰 관련 기능들을 모아 작성할 것이다.

 

const express = require('express')
const router = express.Router()

// token 폴더의 kip7.js 로드
const token = require('../token/kip7.js')

// 외부에서 함수로 바로 호출되게
module.exports = function(){
    // token.js 파일의 기본 경로는 localhost:3000/token

    // 토큰을 발행하는 api
    //localhost:3000/token/create [get]
    router.get('/create', async (req, res)=>{
        // 유저가 보낸 데이터를 변수에 대입, 확인
        const input_name = req.query._name
        const input_symbol = req.query._symbol
        const input_decimal = Number(req.query._decimal)
        const input_amount = Number(req.query._amount)
        console.log("-> name, symbol, decimal, amount: ",
            input_name, input_symbol, input_decimal, input_amount
        )
       
        // 토큰 발행 함수 실행
        const receipt = await token.create_token(
            input_name, input_symbol, input_decimal, input_amount
        )
        
        console.log("-> receipt: ", receipt)
        res.send(receipt)
    })
}

 

토큰 관련 처리를 위해선 kip7.js 파일의 함수를 가져다 써야 하기 때문에 kip7.js를 token 이라는 이름으로 로드해주었다.

 

이전에 token.js 파일은 '/token' 이라는 주소에 사용 되기로(?) index.js에 설정해주었다.

따라서 위처럼 '/create'만 붙여줘도 자동으로 '/token/create' 주소로 동작하게 된다.

 

토큰 발행 함수를 돌릴 때 시간이 다소 걸릴 수 있기 때문에 await를 걸어주기 위해 async로 함수를 선언해주었다.

get 방식 요청의 유저가 보낸 데이터는 url에 파라미터로 찍히는데, 이 파라미터는 request의 query 안에 있다.

유저가 폼에 작성한 내용을 각각 변수로 저장해주도록 했는데, kip7.js에서 작성한 create_token 함수에 매개변수로 들어갈 소수점과 발행량은 숫자로 입력해주어야 한다. 하지만 req.query는 문자열의 파라미터를 받기 때문에 Number 타입으로 형변환 처리를 해주었다.

 

kip7.js의 토큰 발행 함수인 create_token에 매개변수로 유저가 입력한 정보를 넣어 실행되게 하고, 결과를 변수에 담은 후 단순히 화면에 결과를 띄우도록 처리했다.

서버를 실행하고 토큰을 발행해보자!

 

내용을 입력하고 발행 버튼을 누르면 get 방식 처리였기 때문에 url에 파라미터로 입력 정보가 찍혀 나온다.

kip7.js에서 create_token은 정상적으로 실행되면 "토큰 발행 완료" 라는 문자열을 리턴해주도록 작성했다. 따라서 화면과 같이 화면에 토큰 발행 완료가 뜬다면 정상적으로 토큰이 발행된 것이다.

 

 

 

✔️ 토큰 충전하기

이제 발행한 토큰을 충전해보자! 일반 유저 아이디로 로그인하면 아래와 같이 토큰 충전 화면이 보여진다.

 

localhost:3000/main
main.ejs

메인 페이지에서 충전 버튼을 누르면 /token/charge 주소로 이동한다.

token.js의 '/create' 주소 처리 아래에 이어 아래와 같이 작성한다.

 

router.get('/charge', async (req, res)=>{
    if(!req.session.logined){
        res.redirect('/')
    }else{
        const input_amount = Number(req.query._amount)
        console.log('-> 입력한 Amount: ', input_amount)
            
        const wallet = req.session.logined.wallet
        console.log('-> 로그인한 유저 지갑 주소: ', wallet)
            
        // kip7.js에 있는 transfer() 호출 : 토큰을 거래하는 함수
        const receipt = await token.transfer(wallet, input_amount)
        console.log('-> 결과 확인: ', receipt)

        res.redirect('/')
    }
})

토큰 거래 함수에 await를 걸어주기 위해 async로 함수를 선언해주었다.

우선 토큰 충전은 로그인된 유저만 가능하기 때문에 로그인 되지 않았다면 메인페이지(로그인 페이지)로 리다이렉트 하도록 조건을 걸어주었다.

로그인 되었다면 유저가 입력한 충전량과 세션에 저장된 유저 정보에서 지갑 주소를 가져와 각각 변수에 담아주었다.

 

kip7.js에 작성한 transfer 함수에 await를 걸어주었고, 유저의 지갑 주소와 유저가 입력한 충전할 토큰의 양을 매개변수로 넣어 호출했다.

결과를 콘솔에 찍히도록 하고 메인 페이지로 리다이렉트 되게 처리했다.

 

정상적으로 되었다면 로그가 찍힌다.

 

Accounts pool에서 로그인한 계정에 해당하는 지갑 주소를 찾아 들어가보면 토큰이 발행된 것을 확인할 수 있다!

 

 

 

✔️ 마이페이지 - 지갑 주소, 토큰의 양

로그인 했을 때 보이는 메인페이지에서 마이페이지로 이동할 수 있는 버튼이 있다.

마이페이지에서는 유저의 핸드폰 번호(아이디), 지갑주소 뿐만 아니라 kip7.js에서 작성한 함수를 이용해 보유하고 있는 토큰의 양도 보여줄 것이다.

마이페이지 주소 '/token/info' 에 대한 처리를 token.js에 아래와 같이 작성한다.

 

// 마이페이지
router.get('/info', async (req, res)=>{
    // 로그인을 한 지갑의 토큰 양을 로드
    // kip7.js의 balance_of() 함수 호출
    if(!req.session.logined){
        res.redirect('/')
    } else {
        const wallet = req.session.logined.wallet
        console.log('-> 조회할 주소: ', wallet)
        const balance = await token.balance_of(wallet)
        console.log('-> 조회할 주소가 가진 토큰양: ', balance)
        res.render('info.ejs', {
            //유저의 phone, wallet, 토큰의 양
            'user' : req.session.logined,
            'balance' : balance
        })
    }
})

마이페이지 역시 로그인 되어야 보여질 화면이기 때문에 로그인 되지 않았다면 로그인 페이지로 리다이렉트 하게 구현했다.

로그인 되었다면 세션에서 지갑 주소를 가져와 변수로 저장하고, kip7.js의 balance_of 함수의 매개변수로 넣어준다.

info.ejs를 렌더링하며 세션에 저장된 로그인한 유저 정보와 토큰 보유량을 보내준다.

 

info.ejs는 아래와 같이 작성했다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>마이페이지</title>
</head>
<body>
    <h3>My Page</h3>
    <ul>
        <li>
            유저의 핸드폰번호: <%= user.phone %>
        </li>
        <li>
            유저의 지갑주소: <%= user.wallet %>
        </li>
        <li>
            유저의 토큰의 양: <%= balance %> VLT
        </li>
    </ul>
</body>
</html>

user라는 키로 로그인 유저의 정보를 저장해 보내주었기 때문에 위와 같이 데이터를 꺼내왔다. (phone과 wallet은 DB에 저장된 컬럼명이다.)

 

css 작업은 보류...

마이페이지 버튼을 누르면 위와 같이 정보가 출력된다!

 

 

 

 

 

💭 마치며

하루에 진행된 수업인데 분석하며 내용을 정리하다보니 3편으로 나눠서 쓰게 되었다. 프로젝트 진행 전 동작을 완전히..! 이해하게 되어서 다행.. 사실 연재(?)한 구현 내용이 백엔드라고 봐야해서.. 팀플에선 프론트를 맡을 예정이라 따로 더 공부를 해야지. 노드 덕분에 백엔드도 프론트 만큼이나 재밌어져서 기쁘다!! 노드가 좋다... 

댓글