I am not specialist of blockchain..
저는 코인도 안하는 블새싹입니다.ㅎ🌱
틀린게 있을 수 있는 점 양해 부탁드립니다.
3. Web3를 이용하여 직접 만든 Contract의 함수를 호출하기 // 요거 할 차례!
이제 Web3를 통해 Contract를 써보자아아악
https://nodejs.org/ko/
node js 설치는 구글링하면 많다. 위의 사이트에서 nodejs 설치하면 npm까지 같이 설치됨.
node, npm 버전 체크
npm init
위 cmd 실행하면 프로젝트에 package.json이 생성됨
npm install express
npm install nodemon
로컬 파일 새로 저장시마다 새로 서버 restart 해줘서 편함
npm install web3
먼저 test 목적이니까 아키텍쳐 설계는 간단하게!
파일은 server.js, index.js, views/index.ejs(이건 사실 필요없긴 하지만..)
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 파일
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 에러 뜨면서 코드 실행이 안됐는데,
회사 보안 네트워크 때문이었다.. 노트북으로 망 바꾸니 바로 됨
나처럼 에러 있으신 분들 네트워크도 체크해보시길..
// read 트랜잭션 요청
contract.methods.WETH().call().then(function(res){
console.log("Text : " + res);
});
먼저 read 트랜잭션을 실행해본다.
WETH() 펑션을 call하면
Text : 0x8d58045432168caCF9bBd019E7CD938212D0e084
라는 값이 찍힌다!!!
// 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%.. ㅎㅎ)
한글 문서가 너무 없어서 내가 만들었다.
거의 뭐 "답답하면 네가 뛰던가" 수준
끝