-
Notifications
You must be signed in to change notification settings - Fork 377
Description
Mainnet: Klaytn Cypress
ID: 8217
RPC: https://public-node-api.klaytnapi.com/v1/cypress
Symbol: KLAY
Block Explorer URL (For Transaction Detail): https://scope.klaytn.com/tx/
SVG Asset: https://zpl.io/jZEjrkx
Network Style Colour: #FE3300
CoinGecko API ID: klay-token
(for both chain price and Token price queries).
Testnet: Klaytn Baobab
ID: 1001
RPC: https://api.baobab.klaytn.net:8651
Symbol: KLAY
Block Explorer URL (For Transaction Detail): https://baobab.scope.klaytn.com/tx/
SVG Asset:
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill-rule="nonzero" fill="none">
<path d="M13.132 1.852A7.97 7.97 0 0 0 8.287 0L4.205 10.778l8.927-8.926z" fill="#B2C6D8" fill-rule="nonzero"/>
<path d="M14.15 2.871 9.023 8l5.126 5.124a8.004 8.004 0 0 0 0-10.253z" fill="#B2C6D8" fill-rule="nonzero"/>
<path d="M6.28 1.23.016 7.494c-.129 2.013.51 4 1.785 5.563L6.281 1.23z" fill="#B2C6D8" fill-rule="nonzero"/>
<path d="m8.004 9.017-5.126 5.126a8.004 8.004 0 0 0 10.252 0L8.004 9.017z" fill="#B2C6D8" fill-rule="nonzero"/>
</g>
</svg>
Network Style Colour: #313557
This will give you basic support. However for full support you need to integrate Covalent. I have gone for a minimal approach to begin with, converting the Covalent API data into Etherscan Transfer event objects so they can be fed into your existing transfer event handling without too much modification. Currently I am supporting only FT & NFT Transfers and Contract constructor detection. We can also easily add handling for 'Approve', and other standard contract events for ERC20, 721 and 1155 at a later date.
Here's the Covalent API endpoint you will be using:
https://api.covalenthq.com/v1/8217/address/<ACCOUNT ADDRESS>/transactions_v2/?key=<API Key>&page-number=0&page-size=800
This will return:
"data": {
"address": "<ACCOUNT ADDRESS>",
"updated_at": "2022-03-29T22:12:45.829682424Z",
"next_update_at": "2022-03-29T22:17:45.829682674Z",
"quote_currency": "USD",
"chain_id": 8217,
"items": [ <Transactions> ],
}
Each element looks like this - eg, an ERC721 Transfer event (Mint in this case):
{
"block_signed_at": "2022-03-29T22:12:43Z",
"block_height": 86708074,
"tx_hash": "0xbc1f9892f2304e8d64e0f3bd0a7ece0a4c4f39169460b1ea87beb28820f30caa",
"tx_offset": 10,
"successful": true,
"from_address": "0x424d0c6ed9addc9e80e81dbfe6e26911e4a25c8c",
"from_address_label": null,
"to_address": "0xb6fc2d963979a78fc7351695fcb829bc3c8b5b29",
"to_address_label": null,
"value": "0",
"value_quote": 0.0,
"gas_offered": 356057,
"gas_spent": 222437,
"gas_price": 25000000000,
"gas_quote": 0.006758514791113139,
"gas_quote_rate": 1.215358018875122,
"log_events": [ <--- Can be multiple of these especially if TX has has chained events
{
"block_signed_at": "2022-03-29T22:12:43Z",
"block_height": 86708074,
"tx_offset": 10,
"log_offset": 4,
"tx_hash": "0xbc1f9892f2304e8d64e0f3bd0a7ece0a4c4f39169460b1ea87beb28820f30caa",
"raw_log_topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x00000000000000000000000069dca5507a9adf8576b5cae4f1b332c75e5e5f01",
"0x00000000000000000000000000000000000000000000000000000000000026d9"
],
"sender_contract_decimals": 0,
"sender_name": "klay pixelmfers",
"sender_contract_ticker_symbol": "KPXMF",
"sender_address": "0xb6fc2d963979a78fc7351695fcb829bc3c8b5b29",
"sender_address_label": null,
"sender_logo_url": "https://logos.covalenthq.com/tokens/8217/0xb6fc2d963979a78fc7351695fcb829bc3c8b5b29.png",
"raw_log_data": null,
"decoded": {
"name": "Transfer",
"signature": "Transfer(indexed address from, indexed address to, uint256 value)",
"params": [
{
"name": "from",
"type": "address",
"indexed": true,
"decoded": true,
"value": "0x0000000000000000000000000000000000000000"
},
{
"name": "to",
"type": "address",
"indexed": true,
"decoded": true,
"value": "0x69dca5507a9adf8576b5cae4f1b332c75e5e5f01"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"decoded": false,
"value": null
}
]
}
}
]
},
I have handled this by converting it into a stream of EtherscanEvent
which matches a single element from the Etherscan transfers
API:
First handle the params:
public Map<String, Param> getParams() throws Exception
{
Map<String, Param> params = new HashMap<>();
if (decoded == null || decoded.params == null) return params;
for (int index = 0; index < decoded.params.length; index++)
{
String rawLogValue = (index + 1) < raw_log_topics.length ? raw_log_topics[index + 1] : ""; // <-- See raw_log_topics above, first entry is event hash, then the params
LogParam lp = decoded.params[index];
Param param = new Param();
param.type = lp.type;
String rawValue = TextUtils.isEmpty(lp.value) || lp.value.equals("null") ? rawLogValue : lp.value; // <-- value can be either in the 'params' from the API return or in the raw_log_topics array
if (lp.type.startsWith("uint") || lp.type.startsWith("int"))
{
param.valueBI = rawValue.startsWith("0x") ? Numeric.toBigInt(rawValue) : new BigInteger(rawValue);
param.value = "";
}
else
{
param.value = rawValue;
}
params.put(lp.name, param);
}
return params;
}
Then do full conversion to 'EtherscanEvent':
private EtherscanEvent getEtherscanTransferEvent(LogEvent logEvent) throws Exception
{
if (logEvent == null || logEvent.decoded == null || !logEvent.decoded.name.equals("Transfer")) return null; // <--- Currently only handle "Transfer" events to reduce code changes
EtherscanEvent ev = new EtherscanEvent();
ev.tokenDecimal = String.valueOf(logEvent.sender_contract_decimals);
ev.timeStamp = format.parse(block_signed_at).getTime() / 1000;
ev.hash = tx_hash;
ev.nonce = 0; // <-- Covalent doesn't provide TX nonce
ev.tokenName = logEvent.sender_name;
ev.tokenSymbol = logEvent.sender_contract_ticker_symbol;
ev.contractAddress = logEvent.sender_address;
ev.blockNumber = block_height;
Map<String, Param> logParams = logEvent.getParams();
ev.from = logParams.get("from").value;
ev.to = logParams.get("to").value;
logParams.remove("from");
logParams.remove("to");
if (logEvent.sender_contract_decimals == 0) //< --- Is an NFT transfer
{
//get TokenId
ev.tokenID = logParams.values().iterator().next().valueBI.toString();
}
else
{
ev.value = logParams.values().iterator().next().valueBI.toString(); // <-- Is ERC20 Transfer
}
ev.gasUsed = gas_spent;
ev.gasPrice = gas_price;
ev.gas = String.valueOf(gas_offered);
return ev;
}
Where EtherscanEvent
Looks like this:
public class EtherscanEvent
{
public String blockNumber;
public long timeStamp;
public String hash;
public int nonce;
String blockHash;
public String from;
public String contractAddress;
public String to;
public String tokenID;
public String value;
public String tokenName;
public String tokenSymbol;
public String tokenDecimal;
public String input;
String gas;
String gasPrice;
String gasUsed;
}
Which is the return from Etherscan Transfer API.
Using something like the above you can feed the events (which match the objects returned from the Etherscan transfer API) directly into your existing code.