일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- CSS
- javascript
- Factory 함수
- http 모듈
- 안정 정렬
- npm
- #1인게임개발
- ES6 모듈
- CSS Specificity
- 명시도
- Hybrid Blockchain
- short-circuiting
- IP
- UTXO
- 블록체인
- Factory Functions
- 불안정 정렬
- skip ci
- 2티어 아키텍처
- react
- caverjs
- NoSQL
- CLI
- 텍스트 가운데 정렬
- #유니티
- SQL
- solidity
- 3티어 아키텍처
- Private Blockchain
- Relational Database
- Today
- Total
짹뚜 스튜디오
caver-js-ext-kas 를 활용한 클레이튼 API 구현 본문
caver-js-ext-kas를 활용해서 클레이튼의 블록, 트랜잭션, 계정 정보들을 응답해주는 API 서버를 만들어보았다. API 서버는 클레이튼 바오밥 네트워크와 연결해서 구현했다. (https://github.com/JJakDDo/klaytnAPI)
GitHub - JJakDDo/klaytnAPI
Contribute to JJakDDo/klaytnAPI development by creating an account on GitHub.
github.com
가장 먼저 해야 할 일은 KAS를 사용하기 위해 API 인증 키를 받아야 한다.
https://www.klaytnapi.com/ko/landing/main 여기에 접속하고 가입해서 인증키를 받을 수 있다.
그 다음 프로젝트에 KAS 모듈을 설치해야 한다. caver-js-ext-kas는 caver-js 모듈에서 KAS에서 제공하는 API를 사용할 수 있게 기능이 추가된 모듈이다. 그래서 caver-js 모듈에서 제공하는 함수들과 KAS에서 제공하는 API들을 모두 사용할 수 있다.
npm install caver-js-ext-kas
KAS를 사용하려면 다음과 같은 코드를 작성해야 한다.
const chainId = 1001; //baobab network
const CaverExtKAS = require("caver-js-ext-kas");
const caver = new CaverExtKAS(
chainId,
process.env.ACCESSKEYID,
process.env.SECRETACCESSKEY
);
여기서 chainID 1001은 바오밥 네트워크를 의미한다. Cypress 네트워크는 8217이다. 그리고 KAS 웹페이지에서 발급받은 AccessKeyId와 SecretAccessKey를 인자 값으로 같이 전달하면 된다.
블록 확인
GET /blocks/{BlockNumber or hash}
//Get Block By Number or Hash
getByNumberOrHash: async function (req, res) {
const blockNumberOrHash = req.params.blockNumberOrHash;
try {
const response = await caver.rpc.klay.getBlock(blockNumberOrHash, true);
res.status(200);
res.send(response);
} catch (err) {
res.status(400);
res.send({ message: "The block does not exist" });
}
}
블록 번호 또는 해쉬값으로 블록에 대한 정보를 가져오고 해당 블록 객체를 응답으로 보내준다. 만약 블록이 존재하지 않으면 400 status code와 함께 에러 메시지를 보낸다.
최신 블록 확인
GET /blocks?amount=N
//Get latest N Blocks
getLatestBlocks: async function (req, res) {
const amount = req.query.amount;
const result = [];
const latestBlockNumberInHex = await caver.rpc.klay.getBlockNumber();
const latestBlockNumberInDec = parseInt(latestBlockNumberInHex, 16);
for (
let i = latestBlockNumberInDec;
i > latestBlockNumberInDec - amount;
i--
) {
const response = await caver.rpc.klay.getBlock(i);
res.status(200);
result.push(response);
}
res.send(result);
}
query로 응답받고자 하는 블록의 개수를 요청과 함께 보내면 가장 최신 블록부터 해당 개수만큼 배열로 만들어서 응답으로 보낸다.
트랜잭션 확인
GET /txs/{transaction hash}
get: async function (req, res) {
const txHash = req.params.txHash;
try {
const response = await caver.rpc.klay.getTransactionByHash(txHash);
res.status(200);
res.send(response);
} catch (err) {
res.status(400);
res.send({ message: "The transaction does not exist" });
}
}
트랜잭션 해쉬값으로 트랜잭션을 가져오고 해당 트랜잭션 객체를 응답으로 보내준다. 만약 해당 트랜잭션이 존재하지 않으면 400 status code와 함께 에러 메시지를 보낸다.
어카운트 확인
GET /accounts/{account address}
get: async function (req, res) {
const accountAddress = req.params.accountAddress;
let response;
try {
response = await caver.rpc.klay.getAccount(accountAddress);
} catch (err) {
res.status(400);
res.send({ message: "The account does not exist" });
return;
}
switch (response.accType) {
// Account가 EOA 계정일 때
case 1: {
res.status(200);
res.send({ type: "EOA", data: response });
return;
}
// Acount가 SCA 계정일 때
case 2: {
try {
// KIP7 Interface가 구현되었는지 확인
const isKIP7 = await caver.kct.kip7.detectInterface(accountAddress);
if (isKIP7.IKIP7) {
const kip7 = await new caver.kct.kip7(accountAddress);
const name = await kip7.name();
const symbol = await kip7.symbol();
const decimals = await kip7.decimals();
const totalSupply = await kip7.totalSupply();
res.status(200);
res.send({
type: "KIP7 Token",
name,
symbol,
decimals,
totalSupply,
data: response,
});
return;
}
// KIP17 Interface가 구현되었는지 확인
const isKIP17 = await caver.kct.kip17.detectInterface(
accountAddress
);
if (isKIP17.IKIP17) {
const kip17 = await new caver.kct.kip17(accountAddress);
const name = await kip17.name();
const symbol = await kip17.symbol();
const totalSupply = await kip17.totalSupply();
res.status(200);
res.send({
type: "KIP17 Token",
name,
symbol,
totalSupply,
data: response,
});
return;
}
} catch (err) {
res.status(200);
res.send({
type: "SCA",
data: response,
});
return;
}
}
}
클레이튼에는 account의 종류가 2가지가 있다. 하나는 EOA이고 다른 하나는 SCA이다. EOA는 외부소유계정으로 트랜잭션을 보내는 계정이다. SCA는 Smart Contract Address로 클레이튼 네트워크에 배포된 Smart Contract의 계정 주소를 나타낸다. caver.rpc.klay.getAccount({address})의 반환된 객체 중 accType이 있는데 만약 이 값이 1이라면 EOA이고 2이면 SCA이다. 그리고 만약 SCA 계정이라면 추가로 확인할 것이 해당 스마트 컨트랙트가 Fungible Token인지 Non-Fungible Token인지를 확인하는 기능을 추가했다. caver.kct.kip7.detectInterface({address})를 호출해서 해당 컨트랙트가 KIP7 인터페이스를 구현했는지, 즉 Fungible Token인지 확인할 수 있다. NFT는 kip17.detectInterface({address}) 함수를 호출해서 확인이 가능하다.
detectInterface 함수를 호출할 때 문제가 생겼었다. 정상적인 Smart Contract 주소를 검색해도 error가 발생하는 것이었다. 알고 보니 detectInterface 함수는 내부적으로 KIP13 인터페이스가 구현되어있지 않으면 에러를 발생시킨다. 즉 KIP7 또는 KIP17으로 구현되어있지 않은 일반적인 Smart Contract인 경우에는 바로 에러를 발생시킨다. 그래서 detectInterface 함수를 trycatch문 안에서 호출하는 방법으로 구현해서 에러 처리를 해주었다.
이더리움 네트워크와 인터렉트 하기 위한 web3js와 caverjs의 함수들이 비슷한 형태로 구현되어있기 때문에 caverjs를 사용할 때 큰 어려움은 없었다. 앞으로도 클레이튼 네트워크를 활용한 dApp 개발에 관심이 있기 때문에 이번 경험을 통해서 caverjs와 친해질 수 있었다. 그리고 추가로 KAS에서 제공하는 TokenHistory API를 활용해서 서버 API를 만들 예정이다. 그리고 만든 API 서버를 사용해서 react로 클라이언트 부분도 구현할 예정이다.
'개발 공부 > 블록체인' 카테고리의 다른 글
[프로젝트] Opensea 클론코딩 (0) | 2022.04.18 |
---|---|
ICO 스마트 컨트랙트 구현하기 (0) | 2022.04.07 |
[암호화폐] 채굴 (0) | 2022.03.07 |
[암호화폐] UTXO (0) | 2022.03.03 |
[블록체인] Public vs Private vs Hybrid (0) | 2022.03.03 |