[React] KAS 와 Caver-js를 이용한 NFT 마켓 dApp 개발 세팅
NFT 블록체인 마켓 앱 만들기 3기 / Klaytn IDE / KAS (Klaytn API Service) / Caver-js
🦁 [PROJECT LION] NFT 블록체인 마켓 앱 만들기 with 그라운드X 3기 - 챕터 4-3 회고
KAS ( Klaytn API Service )
Klaytn에서 제공하는 클레이튼 네트워크 전용 API
클레이튼 환경에서 dApp을 개발하려면
클레이튼 네트워크에 엔드포인트(Endpoint Node) 를 띄워야 하는데KAS를 사용하면 Endpoint Node 역할을 해줘서
따로 노드를 띄울 필요없이 API 로 개발이 가능하다
Caver-js
‘caver-js’ 는 개발자가 HTTP 또는 웹소켓 연결을 사용하여
Klaytn 노드와 상호작용할 수 있도록하는 자바스크립트 API 라이브러리
-1. 블록체인 노드에 직접적으로 콜하기 어려워서 KAS 를 사용
-2. KAS 는 우리가 블록체인에 ‘접근’ 하는걸 도와준다
-3. 스마트 컨트랙트에 있는 데이터를 읽고 실행하는걸 도와준다
-4. 이 과정에서 Caver-js 를 쓰면 우리가 사용하는 코드를
-5. 스마트 컨트랙트 블록체인이 이해할수 있는 코드로 ‘변형’ 해줘서
-6. Klaytn 노드와 상호작용할 수 있도록 도와준다
KAS 와 Caver-js를 이용한 dApp 개발 세팅
-1. KSA 웹페이지에 접속하여 키를 생성한다
https://console.klaytnapi.com/ko/security/credential
(👆 Klaytn API Service 키 생성)
생성한 키 AccessKey ID / Secret AccessKey / Authorization
따로 적어두거나 다운로드 받아서 보관해야한다 (노출되면 안됨)
👉.env
환경변수로 설정해줘야한다
-2. 간단한 스마트 컨트랙트 코드를 작성하고 배포(Deploy)
👉 카운터 숫자를 증가시키는 예제
배포하고 나온 ABI / 컨트랙트 주소 를 복사한다
-3. npx create-react-app .
을 이용하여 리액트 개발환경을 만들어주고 코드를 입력한다
3-1. KAS 에서 발급받은 키를 변수에 담아주고
3-2. Klaytn IDE에서 배포하고 나온 ABI / 컨트랙트 주소도 변수에 담아준다
3-3. 네트워크 체인의 아이디도 입력
-4. ‘생성한 키’ 를 대입하여 Klaytn Node API를 사용하기 위한 코드를 입력한다
https://console.klaytnapi.com/ko/service/node
(👆 코드는 KAS Docs에 나와있음)
-5. Caver-js 를 이용하여 컨트랙트와 리액트 연동작업
5-1. Klaytn IDE 에서 작성한
count
메소드를 호출( Call ) 해본다5-2. caver-js 에서 기본으로 제공하는
getBalance
함수를 이용하여 지갑의 잔고를 확인해본다
-6. npm run start
로 실행시킨뒤 콘솔을 찍어보면
👆 스마트 컨트랙트
count
의 값과
지갑의 잔고가 잘 찍히는걸 확인 할 수 있다
-7. Klaytn IDE에서 배포된 컨트랙트의 값을 변경해보면
콘솔에 실시간으로 변경된 값과 / 지갑의 잔고 변경 값이 반영이 된다
카운터 숫자를 증가시키는 스마트컨트랙트 예제 코드
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.24 <=0.5.6;
contract Count {
uint256 public count = 0;
function getBlockNumber() public view returns (uint256) {
return block.number;
}
function setCount(uint256 _count) public {
count = _count;
}
}
KAS 와 Caver-js를 이용한 dApp 개발 셋팅코드
import "./App.css";
import Caver from "caver-js";
const COUNT_CONTRACT = "0xdB4854fd2d3c6D65F0d5f581f9d3aE2d93C821FA";
// 배포하고 나온 컨트랙트 주소
const COUNT_ABI = [
{
constant: true,
inputs: [],
name: "count",
outputs: [
{
name: "",
type: "uint256",
},
],
payable: false,
stateMutability: "view",
type: "function",
},
{
constant: true,
inputs: [],
name: "getBlockNumber",
outputs: [
{
name: "",
type: "uint256",
},
],
payable: false,
stateMutability: "view",
type: "function",
},
{
constant: false,
inputs: [
{
name: "_count",
type: "uint256",
},
],
name: "setCount",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function",
},
];
// 배포하고 나온 ABI
const ACCESS_KEY_ID = "KASKQOJG0EB473CRCRCGBH3S";
// KAS에서 발급받은 엑세스 키
const SECRET_ACCESS_KEY = "zkjGXV5JakSEyVtOX3Iy3RdU0lZpgQ3CJYt_YeO0";
// KAS에서 발급받은 비밀 키
const CHAIN_ID = "1001";
// 체인 아이디 바오밥테스트넷은 1001 / 클레이튼 메인넷은 8217
const option = {
// Klaytn Node API를 사용하기 위한 코드 (Docs에 나와있음)
headers: [
{
name: "Authorization",
value:
"Basic " +
Buffer.from(ACCESS_KEY_ID + ":" + SECRET_ACCESS_KEY).toString("base64"),
},
{ name: "x-chain-id", value: CHAIN_ID },
],
};
const caver = new Caver(
new Caver.providers.HttpProvider(
"https://node-api.klaytnapi.com/v1/klaytn",
option
)
); // Klaytn Node API를 사용하기 위한 코드 (Docs에 나와있음)
const CountContract = new caver.contract(COUNT_ABI, COUNT_CONTRACT);
// ⭐ 개발자는 '스마트 컨트랙트 주소'와 'ABI'를 알면 'caver' 를 통해
// ⭐ 스마트 컨트랙트를 생성하고 / 특정 함수를 실행할 수 있다
const readCount = async () => {
const _count = await CountContract.methods.count().call();
// 스마트컨트랙트 배포후에 나오는 함수
console.log(_count);
};
// 블록체인 노드에 직접적으로 콜하기 어려워서 KAS 를 사용
// KAS 는 우리가 블록체인에 접근하는걸 도와준다
// 스마트컨트랙트에 있는 데이터를 읽고 실행하는걸 도와준다
// 이 과정에서 Caver-js 를 쓰면 인간이 사용하는 코드를
// 스마트컨트랙트 블록체인이 이해할수 있는 코드로 변형해줘서
// Klaytn 노드와 상호작용할 수 있도록 도와준다
//
const getBalance = (address) => {
return caver.rpc.klay.getBalance(address).then((res) => {
// 클레이 잔고를 확인 (다른코인이 있다면 klay말고 적으면 된다)
const balance = caver.utils.convertFromPeb(
// convertFromPeb 👉 10 ** 18 로 클레이단위를 변경
caver.utils.hexToNumberString(res)
// hexToNumberString 👉 16진수문자열로 변경
);
console.log(balance);
return balance;
});
};
function App() {
readCount();
getBalance("0x21e90d232a37530041469a2d7e7fa3e62fe9d18a");
return <div className="App"></div>;
}
export default App;