Kas 기반 클레이튼 서버 개발

FeelSoo·2022년 6월 9일
0

CodeStates

목록 보기
42/43
post-thumbnail

Web3.js과 비슷한 Caver를 사용하여 KAS기반 클레이튼 서버 개발을 진행해봤다.

https://github.com/PILSUCHOI/Cas-Server -- 코드 저장소

https://ko.docs.klaytn.foundation/dapp/sdk/caver-js/getting-started#smart-contract --- 클레이튼 공식 문서

원했던 기능 구현 :

ㄱ. 버전 체크

ㄴ. 계정 생성

ㄷ. 잔고 확인

ㄹ. 토큰 전송

ㅁ. 스마트 컨트랙트 배포



현재 완성된 기능 : ㄱ, ㄴ, ㄷ

ㄹ & ㅁ, 즉 토큰 전송과 스마트 컨트랙트 배포는 에러로 인해 디버깅 중이다..



< cas 서버용 환경 셋팅 >


바탕화면에 cas 폴더 생성 

VS CODE로 접속 후 해당 폴더 (cas) 오픈. 이후 터미널 열기

npm init // json 파일 생성 위한 모듈 설치

npm install caver-js // cas 구축 위한 모듈 설치

npm install express // 미들웨어 사용 위한 express 설치

.env 파일 생성 // 본인의 카이카스 address 및 비밀키(개인키) 보관용

.gitignore 파일 생성 // .env 파일이 git에 올라가는 것을 막기 위해 파일 생성


셋팅이 완료되면 좌측 디렉토리에 파일이 5개 생성되어 있을 것이다. 이제 index.js에 각각의 기능들을 간단하게 구현하면 된다. 그 전에 우리가 사용할 모듈들을 상단에 import 하는 작업을 먼저 진행하자


const express = require('express'); // 미들웨어 적용 위한 express 모듈 갖고오기
const app = express(); // 미들웨어 적용
const port = 8080;

const Caver = require('caver-js');      // cas 구현 위한 모듈 caver-js 설치 후 import
const { application } = require('express');
const caver = new Caver('https://api.baobab.klaytn.net:8651/')

require('dotenv').config(); // 환경 변수 .env파일 사용을 위한 dotenv import

app.use(express.json());
app.use(express.urlencoded({ extended: false })); // undefined 오류 방지 위한 urlencoded

app.listen(port, () => { console.log('서버 시작') }); // 터미널에 찍히는 멘트. 서버 렌더링 위한 코드

app.get("/", async (req, res) => { res.send("서버 start") }); // 서버 페이지에 찍히는 멘트. 서버 정상 실행시 응답 돌려준다



기본 모듈들을 가져왔다면 첫 번째 기능인 버젼 체크를 구현해보자.
서버를 실행하기 위해서는 터미널에 다음을 입력하자.

node index.js

물론 package.json에 scripts 파트에 start를 집어넣어서 npm start로 진행해도 된다.

"scripts" : { 

----- 중략 ----

"start" : "node index.js"

----- 중략 ----
}

그리고 중간 중간 서버가에러로 인해 포트를 점유하고 있지만 정상적인 응답이 불가한 경우 강제로 포트를 중지시켜야 한다. 다음의 명령어가 도움이 될 것이다.
lsof -i : (포트번호) // 포트번호에 점유된 pid 검색   ex) --- lsof -i :8080  

kill -9 (pid)  // 검색된 pid를 해당 명령어로 강제 종료시킬 수 있다



< 버전 확인 기능 구현 >


// 1. 버젼 확인
app.get('/version', async (req, res)=> {
    const version = await caver.rpc.klay.getClientVersion();
    res.send(version);
}) 

postman에서 get 메소드로 다음의 주소를 입력하면 body를 통해 현재 버젼을 응답한다

http://localhost:8080/version




< 계정 생성 >


// 2. 계정(주소, 비밀키) 생성
app.get('/createaccount', async(req, res)=> {
    const account = await caver.klay.accounts.create();
    const create = await caver.klay.accounts.wallet.add(account);
    
    const newAccount = {
        Address : create.address,
        Privatekey : create.privateKey
    }
    res.json(newAccount)
}) // create() 메서드로 계정 만들고 계정을 지갑에 넣어 사용가능한 지갑으로 만든다

마찬가지로 포스트맨을 활용하여 createaccount 루트로 get 메소드로 요청하면 주소와 키를 생성할 수 있다.



< 잔고 확인 >


// 3. 잔고 확인
app.get('/getbalance', async(req,res) => {
    const balance = await caver.klay.getBalance(req.body.address)
    const show = caver.utils.convertFromPeb(balance, 'KLAY')
    res.json(`현재 잔고 : ${show}`);
}) // 바디로 받은 주소값을 getBalance에 넣어주면 현재 잔고값을 가져온다.
   // 잔고값을 convertFromPeb 메서드로 지갑에 디스플레이한다


카이카스에서 잔고를 확인하고 싶은 계정 주소를 복사한 후 postman에서 Body의 key와 value를 채워서 get 메소드로 요청한다.

key : address, value : (해당 주소)



< 토큰 전송 >

// 4. 토큰 전송
app.get('/transfer', async(req, res) => {

    let to = req.body.toAddress // 받을 사람 주소
    let amount = req.body.amount

    let balance = await caver.klay.getBalance(process.env.FROM_ADDRESS)
        balance = caver.utils.fromPeb(balance, 'KLAY')

    let check = await caver.klay.accountCreated(to); // 계정 존재 유무 체크
    console.log(check); 

    if(check && balance > amount) { // 계정 존재하고 토큰 부족 여부를 체크한 후 요청 갯수보다 예치된 금액이 더 크면 전송 
        const keyring = caver.wallet.keyring.createFromPrivateKey(process.env.PRIVATE_KEY);
        const valueTransfer = caver.transaction.valueTransfer.create({
            
            from : keyring.address,
            to : to,
            value : caver.utils.toPeb(`${amount}`, 'KLAY'),
            gas : 30000,
        });
        
        const signed = await valueTransfer.sign(keyring)
        const receipt = await caver.rpc.klay.sendRawTransaction(signed)

        console.log(receipt)
        res.send(receipt)
    }

    else { // 계정 없거나 잔액 부족시
        res.status(400).send('유효하지 않은 계정이거나 잔액 부족입니다')
    }   
}) 

이렇게 구현은 해놓았는데 응답으로 '유효하지 않은 계정이거나 잔액 부족입니다'만 돌아오는 상황이다.

즉, 정상 응답 처리가 아닌 에러 처리로만 응답 중이다.

터미널에서 true가 찍히는걸 보아하니 console.log(check) 까지는 정상적으로 넘어가는 것 같은데 다음단부터가 문제다.

keyring이고 valueTransfer고 signed고 다 콘솔을 넣어서 어느 부분부터 막히나 확인하려 했지만 아예 반응이 없다..

이게 뭐지..?

그냥 개인적인 추측인데 클레이튼 서버가 최근 자주 다운되고 메인넷이 불안정하기에 메서드를 교체하거나 수정한거 같은데 아직 docs가 업데이트가 되지 않은거 같다. cas 개발 관련 커뮤니티가 활성화된것도 아니라서 디버깅에 상당히 애를 먹고 있는 중이다. 우선은 그래서 막히는 부분은 스킵하고 여유가 있을 때 다시 시도해보기로 했다


< 스마트 컨트랙트 배포 >

// 5. smart contract 배포
app.post('/deploy', async(req, res) => {
    const account = caver.klay.accounts.wallet.add(process.env.PRIVATE_KEY)

    const ABI = req.body.abi
    const Bytecode = req.body.bytecode ;

    await caver.klay.sendTransaction({
        
        type : 'SMART_CONTRACT_DEPLOY',
        from : account.address,
        data : caver.klay.abi.encodeContractDeploy(ABI, Bytecode, 1, 2),
         gas : '300000',
       value : 0,

    }).on('transactionHash', function(hash){
        console.log('transaction Hash!', hash)
    
    }).on('receipt', function(receipt){
        console.log(receipt)
        res.json('contract deploy success!')

    }).on('error', console.error);

})

역시 작성은 해놓았지만 에러가 발생하고 있는 상황이다. gas가 너무적다거나 gas가 오바된다든가 감 잡기가 힘들다.. 처음에는 docs 디폴트값인 300000 으로 햇더니 gas가 오바된대서 100000으로 낮췃더니 또 너무 적다그래서 200000부터 300000 까지 무작위로 넣어서 일일이 확인해봤지만 응답이 없었다. 이 부분도 차후에 여유가 생기면 디버깅 할 예정이다.



< 회고 >

원했던 기능들을 다 구현하지 못해서 살짝 찝찝한 기분이다. 메소드의 문제인가, syntax의 문제인가 감이 아직 오지 않는거 같다. 추후에 시간이 생긴다면 다시 건들여보고 수정해야겠다

profile
세상은 넓고 배울건 많다

0개의 댓글