[ 프런트 ]
매번 새로 생기는 트러플 네트워크 id 확인
$ truffle migration --reset
가끔 트러플이 꺼져서 재배포를 할경우 간혹 이렇게 networks에 네트워크 id가 두개가 생겨있을 수 있다.
트러플을 새로 켤때 네트워크 id가 새로 생성되어서 그런거니까 고유 id값을 확인해서 아닌걸 지우면 된다.
$ truffle console
$ web3.eth.net.getId()
CA 데이터가 자동갱신 되도록 만들기
저번 블로그 글에서 CA값을 json파일에서 찾아서 직접 붙여넣었다.
const Deployed = new web3.eth.Contract(
CounterContract.abi,
"0xE538196bCb40F7cc12E3e041D24A9b04FA3A16A8"
);
하지만 트러플을 끄고켤때마다 네트워크 id만 새로 생성되는게 아니라, 그 안의 값들도 모두 바뀐다.
컨트랙트에 접근하려면 ABI와 CA값이 필요한데, CA가 변할때마다 모든 파일을 찾아다니면서 값을 새로 바꾸는건 한계가 있다.
네트워크 id만 알면 그 안에 있는 속성값에 접근할 수 있는 것을 이용해 자동갱신하도록 코드를 짜주자.
const networkId = await web3.eth.net.getId()
const ca = CounterContract.networks[networkId].address
const abi = CounterContract.abi
const Deployed = new web3.eth.Contract(abi,ca)
로그를 남기는 이벤트 등록하기
로그를 찍을건데 이름은 Counter고, 데이터는 uint256에 대한 내용으로 찍는다고 선언하는 이벤트.
// Counter.sol
event Count(uint256 count);
어느 시점에 이벤트를 날릴지 작성하기
어느 시점에 데이터를 이더리움 클라이언트에 로그를 찍을지 결정해주는 코드다.
increment 메서드가 실행하면 로그를 찍어줄건데, 현재 내 상태변수에 담고있는 _count를 찍어줄거다.
uint256 private _count;
function increment() public {
_count += 1;
emit Count(_count);
}
어디에 있는 로그를 날릴지 작성하기
CA로 컨트랙트에 접근해서 해당 컨트랙트에 작성해놓은 이벤트 로그메세지를 날리겠다는 코드.
- subscribe : 정해진 이벤트( "logs" )를 등록함, 무엇에 대한( address : ca ) 이벤트
- on : ( 솔리디티 코드에서 emit이 실행될때마다 = )이벤트가 실행될때마다 콜백을 실행하고 무언가( "data" )를 받아옴.
const ca = CounterContract.networks[networkId].address;
web3.eth
.subscribe("logs", { address: ca }) //
.on("data", (log) => {
console.log(log);
});
decodeLog
decodeLog는 두가지 인자값을 받아서 객체를 반환한다.
( 디코딩 : 바이트를 문자열로 변환 / 인코딩 : 문자열을 바이트로 변환 )
- [{ type: "받을 타입", 변수:데이터 }] : 16진수로 건네받은 데이터를 어떤 타입으로 받아서 파싱할건지
- 파싱할 내용 ( 데이터 원본값은 유지하되 형태는 임의로 바꾸는것 )
const params = [{ type: "uint256", name: "_vanilla" }];
const value = web3.eth.abi.decodeLog(params, log.data); // 결과 = obj
setCount(value.count)
console.log(value);
객체를 반환하는 이유
Counter 컨트랙트를 만들 솔리디티 파일에 이벤트 Counter에서 인자값을 하나 가지고 있다.
이게 무슨 소리냐면 이벤트 하나에 데이터가 한개 연결되어있다는 소리다.
( 데이터를 여러개 넣을 수 있지만 3개 이하로 넣는게 좋다고 한다. )
event Counter(uint256 count)
결과값
배열의 첫번째 값은 current 값
배열의 두번째 값은 배열의 총 길이
배열의 세번째 값은 위에서 넣어줬던 name:_count
누군가 증가(increment)버튼을 누르면 화면은 메세지를 받게 된다.
이걸로 메세지를 받을 수 있기 때문에 각 함수 안에서 현재 값을 받던 current()를 삭제해도 된다.
const increase = async () => {
const result = await deployed.methods.increment().send({
from: account,
});
// if (!result) return;
// const current = await deployed.methods.current().call();
// setCount(current);
};
로그 확인하기
트랜잭션 해시값으로 getTransactionReceipt를 사용해서 조회하면 logs를 알 수 있다.
web3.eth.getTransactionReceipt('트랜잭션 해시값')
[ 백 ]
백에서 프론트에게 보내는 객체의 속성들
web3.eth.getTransactionReceipt('트랜잭션 해시값')
백에서 이런 객체를 만들어주고 프런트에 전달( axiois )해주면, 프런트는 여기에서 서명만! 남겨놓은채로 메타마스크에게 전달해준다.
프런트에서도 할 수 있지만 백에서 하는 이유는, 양이 점점 많아지면 번잡스럽기 때문.
CA값으로 잔액 확인하기
트랜잭션 해시값을 사용하면 CA값을 확인할 수 있다는 것을 알았다.
정말로 이 CA 값이 받는 사람의 CA 계정인지, 정말 사용할 수 있는 값인지 확인하자.
CA와 getBalance를 사용하면 잔액을 확인할 수 있다.
// web3.eth.getBalance('CA값')
web3.eth.getBalance('0xC5a75EE91130087862cc674448942EAf1cf38373')
>> 0
백에서 사용할 server.js 코드
// back/server.js
const express = require("express");
const app = express();
const cors = require("cors");
const router = require("./routes/index");
const Web3 = require('web3')
const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"))
const corsOption = {
origin: true,
credentials: true,
};
app.use(cors(corsOption));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
app.use(router);
app.listen(4001);
Eth 네트워크에게 메서드 실행 요청 메세지 보내기
let txObject = {
nonce:, // 트랜잭션 총 횟수
from:, // 해당 트랜잭션을 발생시긴 사람의 address.account
to:,
data:, // 스마트 컨트랙트 함수에 대한 내용을 적음
gasLimit:, // 가스 최대용량, 따로 설정 안하면 디폴트값이 됨
gasPrice: // 수수료, 따로 설정 안하면 디폴트값이 됨
}
data에 스마트 컨트랙트 함수에 대한 내용을 적게되는데,
솔리디티 코드에 있는 increment 메서드를 실행하고싶다고 여기에 적으면 안된다.
increment()는 배포한 ABI에 담겨셔 이더리움 네트워크에 배포된 상태기 때문이다.
여기엔 함수를 실행시킬 수 있는 메세지를 넣어야한다.
그 메세지를 보내기 위해서 바이트코드로 바꿔주는 encoded를 사용해야하고, 문자열은 함수니까 ABI를 사용해야한다.
따라서 increment 메서드를 바이트코드 메세지로 바꿔주는 코드는 다음과 같이 작성할 수 있다.
increment().encodedABI()
하지만 이 코드를 사용하려면 increment()를 사용하는게 전제조건이 되어야한다.
이더리움 네트워크에 있는 increment()에게 접근하려면 다음 코드를 작성하면 된다.
const deployed = new web3.eth.Contract(abi, ca)
const data = deployed.methods.increment().encodeABI()
총 정리하면 다음과 같은 코드가 완성된다.
const Web3 = require('web3')
const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545")) // ganache
const CounterContract = require('../truffle/build/contracts/Counter.json')
app.post("/api/increment",async (req,res)=>{
const {from} = req.body
const nonce = await web3.eth.getTransactionCount(from)
const networkId = await web3.eth.net.getId()
const to = CounterContract.networks[networkId].address; //CA
const abi = CounterContract.abi
// abi
// 이걸 쓰려면 increment함수를 호출할 수 있어야함 -> new web3.eth.Contract
const deployed = new web3.eth.Contract(abi, to)
// increment().encodeABI() 문자열을 byte코드로 바꿔주는 encodeABI()
const data = deployed.methods.increment().encodeABI()
// 트랜잭션 형태 만들기
let txObject = {
from, // 해당 트랜잭션을 발생시긴 사람의 address.account
nonce, // 트랜잭션 총 횟수
to, // 컨트랙트 어드레스
data, // 스마트 컨트랙트 함수를 실행시켜달라는 메세지
}
res.json(txObject)
})
이 상태에서 postman으로 post 요청을 보내도 트랜잭션은 일어나지 않는다.
하지만 data에 16진수가 생성되어 있는것을 볼 수 있다.
이게 increment 메서드를 호출시킬 수 있는 메세지다!
이걸 메타마스크에 전달해주면, 메타마스크가 나머지 부분을 채워주고 서명을 네트워크에 전달하면서 트랜잭션이 생성되게 된다.
[ 프런트 ]
api 요청하기 위해 코드 고치기
const increase = async () => {
const response = await axios.post("http://localhost:3001/api/increment", {
from: account,
});
console.log(response.data)
await web3.eth.sendTransaction(response.data) // 메타마스크에 던져주자!
// 프런트에서 만들어줘서 넘겨주는 코드는 이제 필요없음
// const result = await deployed.methods.increment().send({
// from: account,
// });
// api 요청을 해서 json을 받아와서 네트워크에 넘겨줄거임
};
증가 버튼을 눌러서 메타마스크가 서명처리까지 다 끝내고 트랜잭션을 생성한 후,
트러플에서 이 코드를 실행하면 각 함수별 메세지를 볼 수 있고, 객체 안에 input이 존재하는걸 알 수 있다.
Counter.deployed()
즉, input이 있다면 스마트 컨트랙트에 실행한 메서드가 있다는 소리고, to는 CA가 된다는 소리임.
( CA가 있으면 배포한 트랜잭션이고, 없으면 배포하지 않은 트랜잭션임 )
잊을까봐 다시 적는 트랜잭션 종류
- 돈을 보내는 트랜잭션 -> 금액
- 스마트 컨트랙트 배포한 트랜잭션 / 안 한 트랜잭션 -> CA
- 스마트 컨트랙트 실행한 트랜잭션 / 안 한 트랜잭션 -> input
'프로그래밍 > solidity' 카테고리의 다른 글
web3/dist/web3.js 이슈 / window.ethereum 이슈 (1) | 2022.08.22 |
---|---|
ERC721토큰 (0) | 2022.07.18 |
[220713] 스마트 컨트랙트 구현하기 - 2) 백엔드에서 요청보내기 (0) | 2022.07.14 |
[220713] 스마트 컨트랙트 구현하기 - 1) 트러플로 구현하기 (0) | 2022.07.13 |
[220712] 트러플로 스마트 컨트랙트 만들기 (0) | 2022.07.12 |
댓글