Smart Contract for Token Swap #5 Node js - web3 모듈로 contract 호출하기 (마지막 편)

Jina Kim·2022년 10월 5일
0

Smart Contract

목록 보기
9/9
post-thumbnail

🚨 Caution 🚨

I am not specialist of blockchain..
저는 코인도 안하는 블새싹입니다.ㅎ🌱
틀린게 있을 수 있는 점 양해 부탁드립니다.

과제

  1. BSC 테스트넷에서 Pancake Router Contract를 이용하여 직접 Swap 해보기
    (어떤걸 스왑할지는 자유)

  2. BSC 테스트넷에 직접 만든 Contract 를 배포하여 Contract를 통하여 Swap 하기
    컨트랙트를 어떻게 만드는지는 자유이지만 Contract의 함수 내에서 Pancake Router를 통해 Swap할 수 있어야 함
    (사용자 입장에서는 Pancake Router에 접근을 안해도 되도록)

3. Web3를 이용하여 직접 만든 Contract의 함수를 호출하기 // 요거 할 차례!


이제 Web3를 통해 Contract를 써보자아아악

🦺 사전 준비

Node js, npm 설치

https://nodejs.org/ko/
node js 설치는 구글링하면 많다. 위의 사이트에서 nodejs 설치하면 npm까지 같이 설치됨.

node, npm 버전 체크

npm init

위 cmd 실행하면 프로젝트에 package.json이 생성됨

express 설치

npm install express

nodemon 설치

npm install nodemon

로컬 파일 새로 저장시마다 새로 서버 restart 해줘서 편함

web3 설치

npm install web3

🧵 코드 작성


먼저 test 목적이니까 아키텍쳐 설계는 간단하게!
파일은 server.js, index.js, views/index.ejs(이건 사실 필요없긴 하지만..)

server.js

node 서버 셋팅 관련

// server.js 파일
const express = require('express');
const index = require('./index'); // 이따가 index.js 파일 만들어줄꺼임
const app = express();
const port = 3000;

app.set('view engine', 'ejs');
app.set('views', './views');

app.get("/test", index.test);

app.listen(port, () => {
    console.log(`
    ###################################
    ##  Contract Test on port: ${port}  ##
    ###################################`);
});

view 엔진은 ejs
route는 /test 로 설정했고, index.js의 test() 펑션을 호출할 것이다.
port는 마음대로~

index.js

// index.js 파일
const Web3 = require('web3');
const dotenv = require('dotenv').config();

exports.test = (req, res) => {
    // Web3 provider 연결을 위한 구문, 해당 링크는 BSC testnet 오픈 노드
    const web3 = new Web3("https://data-seed-prebsc-1-s1.binance.org:8545/");

    // Contract의 interface(ABI), address
    const contractAbi = require('./abi/router.json');
    const contractAddress = process.env.CONTRACT_ADDRESS;

    // 트랜잭션 요청자의 private key
    const privateKey = process.env.PRIVATE_KEY;

    // private key로 account 정보 변환
    const account = web3.eth.accounts.privateKeyToAccount('0x'+privateKey);

    // web3에 account 추가
    web3.eth.accounts.wallet.add(account);

    // contract 주소와 abi를 사용하여 contract 불러오기
    const contract = new web3.eth.Contract(contractAbi, contractAddress);

    // read 트랜잭션 요청
    contract.methods.WETH().call()
    .then(function(res){
        console.log("Text : " + res);
    });

    res.render("index");
}

web3.js와 연결된 노드를 provider라고 함.
먼저 이 provider 연결을 해야한다.
BSC testnet 오픈 노드 중 하나를 쓸 것이다.(https://data-seed-prebsc-1-s1.binance.org:8545/)

contract의 abi는 기존의 custom 컨트랙트 만들 때 remix에서 복사 가능하다. (하단 이미지 참고)

위의 abi를 따로 json으로 빼서 require 했다.

contract address는 본인이 만든 컨트랙트 주소,
private Key는 컨트랙트 작성자(=본인)의 비공개 키인데
메타마스크 > 계정 세부 정보 > 비공개 키 내보내기 누르면 확인 가능하다.
(이건 남에게 절대 보여주면 안됨~!)

그래서 위의 코드에서는 따로 .env 파일로 뺐다.


web3.eth.accounts.wallet.add(account);

그렇게 내 지갑을 web3에 연결하고

const contract = new web3.eth.Contract(contractAbi, contractAddress);

contract 불러오기~!

🪐 코드 실행

처음에 회사컴으로 couldn't connect to node 에러 뜨면서 코드 실행이 안됐는데,
회사 보안 네트워크 때문이었다.. 노트북으로 망 바꾸니 바로 됨
나처럼 에러 있으신 분들 네트워크도 체크해보시길..

1. Read 트랜잭션

// read 트랜잭션 요청
contract.methods.WETH().call().then(function(res){
    console.log("Text : " + res);
});

먼저 read 트랜잭션을 실행해본다.
WETH() 펑션을 call하면

Text : 0x8d58045432168caCF9bBd019E7CD938212D0e084

라는 값이 찍힌다!!!

2. Write 트랜잭션

// write 트랜잭션 요청
contract.methods.swapExactTokensForTokens(BigInt(10000000000000000000), BigInt(1000000000000000),["0x57B3d32f4E26438E5c73AC9A2a961c4F37dd3Bc7","0x8d58045432168caCF9bBd019E7CD938212D0e084"], "0xe4BD1D9F556eF3a6E85357E2425e7c8457A053Fb", 1664956000).send({
    from: account.address,
    gas: 210000
}).then(function(hash){
    console.log("swap result" + hash);
})

swapExactTokensForTokens 트랜잭션을 실행해본다.

10 JNB를 JNT로 swap하기 위해

인자값에는
uint amountIn, // BigInt(10000000000000000000) BigInt로 안감싸니 오류나더라
uint amountOutMin, // BigInt(1000000000000000)
address[] calldata path,// ["0x57B3d32f4E26438E5c73AC9A2a961c4F37dd3Bc7","0x8d58045432168caCF9bBd019E7CD938212D0e084"] 각 JNB, JNT 컨트랙트 주소
address to, // "0xe4BD1D9F556eF3a6E85357E2425e7c8457A053Fb" 내 지갑 주소
uint deadline // 1664956000 Unix timestamp 값

read 펑션은 call()이 아닌 send()를 쓴다.

💡TIP
view 함수를 호출할 때는 call,
일반함수랑 payable 함수를 호출할 때는 send를 사용

저렇게 하면

swap result [object Object]

가 찍힌다.
(어랏.. 내가 예상한게 아닌데....ㅎ)

된 것 같긴 해서 황급히 내 지갑의 bscscan 들어가보니

됐다!!!!!!! 해냈어!!!!!!!!!!!!!

10 JNB가 0.009 JNT로 (?? 왜케 적어 ㅋㅋㅋㅋ)
쨌든 swap 성공 ^_^

🎠 마무리

router 파악부터 token 직접 생성하고, contract를 web3로 실행까지 완료했다.
꽤 오래 걸렸고, 리서치 진행하면서 정말 개발자는 영어를 잘해야 한다는걸 느꼈다.
(구글링 중 영어문서 90%.. ㅎㅎ)

한글 문서가 너무 없어서 내가 만들었다.
거의 뭐 "답답하면 네가 뛰던가" 수준

profile
Hello, World!

0개의 댓글