diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..764fbde2 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "overrides": [ + { + "files": ".prettierrc", + "options": { "parser": "json" } + } + ] +} diff --git a/src/mappings/constants.ts b/src/mappings/constants.ts index d9b27544..9dff9cdd 100644 --- a/src/mappings/constants.ts +++ b/src/mappings/constants.ts @@ -1,50 +1,50 @@ -import { b64encode } from "./utils"; +import { b64encode } from './utils'; export const EVENT_TYPES = { - ACTIVE_PROPOSAL: "active_proposal", - BURN: "burn", - COIN_RECEIVED: "coin_received", - COIN_SPENT: "coin_spent", - COINBASE: "coinbase", - COMMISSION: "commission", - MESSAGE: "message", - MINT: "mint", - PROPOSAL_DEPOSIT: "proposal_deposit", - PROPOSAL_VOTE: "proposal_vote", - PROPOSER_REWARD: "proposer_reward", - REWARDS: "rewards", - STATE_CHANGE: "state_change", - STORAGE: "storage", - SUBMIT_PROPOSAL: "submit_proposal", - TRANSFER: "transfer", - SEND_PACKET: "send_packet", - RECEIVE_PACKET: "recv_packet", - IBC_TRANSFER: "ibc_transfer", - FUNGIBLE_TOKEN_PACKET: "fungible_token_packet", + ACTIVE_PROPOSAL: 'active_proposal', + BURN: 'burn', + COIN_RECEIVED: 'coin_received', + COIN_SPENT: 'coin_spent', + COINBASE: 'coinbase', + COMMISSION: 'commission', + MESSAGE: 'message', + MINT: 'mint', + PROPOSAL_DEPOSIT: 'proposal_deposit', + PROPOSAL_VOTE: 'proposal_vote', + PROPOSER_REWARD: 'proposer_reward', + REWARDS: 'rewards', + STATE_CHANGE: 'state_change', + STORAGE: 'storage', + SUBMIT_PROPOSAL: 'submit_proposal', + TRANSFER: 'transfer', + SEND_PACKET: 'send_packet', + RECEIVE_PACKET: 'recv_packet', + IBC_TRANSFER: 'ibc_transfer', + FUNGIBLE_TOKEN_PACKET: 'fungible_token_packet', }; export const VAULT_STATES = { - LIQUIDATING: "liquidating", - LIQUIDATED: "liquidated", + LIQUIDATING: 'liquidating', + LIQUIDATED: 'liquidated', }; -export const VALUE_KEY = b64encode("value"); -export const STORE_KEY = b64encode("store"); -export const VSTORAGE_VALUE = b64encode("vstorage"); -export const KEY_KEY = b64encode("key"); -export const STORE_NAME_KEY = b64encode("store_name"); -export const SUBKEY_KEY = b64encode("store_subkey"); -export const UNPROVED_VALUE_KEY = b64encode("unproved_value"); -export const PACKET_DATA_KEY = "packet_data"; -export const PACKET_SRC_CHANNEL_KEY = "packet_src_channel"; -export const PACKET_DST_CHANNEL_KEY = "packet_dst_channel"; -export const PACKET_SRC_PORT_KEY = "packet_src_port"; -export const PACKET_DST_PORT_KEY = "packet_dst_port"; -export const ACTION_KEY = b64encode("action"); -export const IBC_MESSAGE_TRANSFER_VALUE = b64encode("/ibc.applications.transfer.v1.MsgTransfer"); -export const IBC_MESSAGE_RECEIVE_PACKET_VALUE = b64encode("/ibc.core.channel.v1.MsgRecvPacket"); -export const RECEPIENT_KEY = b64encode("recipient"); -export const SENDER_KEY = b64encode("sender"); -export const RECEIVER_KEY = b64encode("receiver"); -export const AMOUNT_KEY = b64encode("amount"); -export const TRANSFER_PORT_VALUE = "transfer"; +export const VALUE_KEY = b64encode('value'); +export const STORE_KEY = b64encode('store'); +export const VSTORAGE_VALUE = b64encode('vstorage'); +export const KEY_KEY = b64encode('key'); +export const STORE_NAME_KEY = b64encode('store_name'); +export const SUBKEY_KEY = b64encode('store_subkey'); +export const UNPROVED_VALUE_KEY = b64encode('unproved_value'); +export const PACKET_DATA_KEY = 'packet_data'; +export const PACKET_SRC_CHANNEL_KEY = 'packet_src_channel'; +export const PACKET_DST_CHANNEL_KEY = 'packet_dst_channel'; +export const PACKET_SRC_PORT_KEY = 'packet_src_port'; +export const PACKET_DST_PORT_KEY = 'packet_dst_port'; +export const ACTION_KEY = b64encode('action'); +export const IBC_MESSAGE_TRANSFER_VALUE = b64encode('/ibc.applications.transfer.v1.MsgTransfer'); +export const IBC_MESSAGE_RECEIVE_PACKET_VALUE = b64encode('/ibc.core.channel.v1.MsgRecvPacket'); +export const RECEPIENT_KEY = b64encode('recipient'); +export const SENDER_KEY = b64encode('sender'); +export const RECEIVER_KEY = b64encode('receiver'); +export const AMOUNT_KEY = b64encode('amount'); +export const TRANSFER_PORT_VALUE = 'transfer'; diff --git a/src/mappings/events/boardAux.ts b/src/mappings/events/boardAux.ts index de573c22..22145797 100644 --- a/src/mappings/events/boardAux.ts +++ b/src/mappings/events/boardAux.ts @@ -1,4 +1,4 @@ -import { BoardAux } from "../../types"; +import { BoardAux } from '../../types'; export const boardAuxEventKit = (block: any, data: any, module: string, path: string) => { async function saveBoardAux(payload: any): Promise[]> { @@ -8,7 +8,7 @@ export const boardAuxEventKit = (block: any, data: any, module: string, path: st block.block.header.time as any, payload.allegedName, payload.displayInfo.assetKind, - payload.displayInfo.decimalPlaces ?? 0 + payload.displayInfo.decimalPlaces ?? 0, ).save(); return [boardAux]; diff --git a/src/mappings/events/priceFeed.ts b/src/mappings/events/priceFeed.ts index 2e0f838f..d7590f69 100644 --- a/src/mappings/events/priceFeed.ts +++ b/src/mappings/events/priceFeed.ts @@ -1,5 +1,5 @@ -import { OraclePrice, OraclePriceDaily } from "../../types"; -import { dateToDayKey } from "../utils"; +import { OraclePrice, OraclePriceDaily } from '../../types'; +import { dateToDayKey } from '../utils'; export const priceFeedEventKit = (block: any, data: any, module: string, path: string) => { async function savePriceFeed(payload: any): Promise[]> { @@ -22,7 +22,7 @@ export const priceFeedEventKit = (block: any, data: any, module: string, path: s BigInt(payload.amountIn.__value), BigInt(payload.amountOut.__value), typeInName, - typeOutName + typeOutName, ).save(); return [oraclePrice, oraclePriceDaily]; @@ -49,15 +49,10 @@ export const priceFeedEventKit = (block: any, data: any, module: string, path: s } async function getOraclePriceDaily(feedName: string, dateKey: number): Promise { - const id = feedName + ":" + dateKey.toString(); + const id = feedName + ':' + dateKey.toString(); let state = await OraclePriceDaily.get(id); if (!state) { - state = new OraclePriceDaily( - id, - dateKey, - BigInt(data.blockHeight), - new Date(block.block.header.time as any) - ); + state = new OraclePriceDaily(id, dateKey, BigInt(data.blockHeight), new Date(block.block.header.time as any)); } return state; } diff --git a/src/mappings/events/psm.ts b/src/mappings/events/psm.ts index c5003336..03d293c3 100644 --- a/src/mappings/events/psm.ts +++ b/src/mappings/events/psm.ts @@ -1,5 +1,5 @@ -import { PsmGovernance, PsmMetrics, PsmMetricsDaily } from "../../types"; -import { dateToDayKey } from "../utils"; +import { PsmGovernance, PsmMetrics, PsmMetricsDaily } from '../../types'; +import { dateToDayKey } from '../utils'; export const psmEventKit = (block: any, data: any, module: string, path: string) => { async function savePsmMetrics(payload: any): Promise[]> { @@ -8,13 +8,13 @@ export const psmEventKit = (block: any, data: any, module: string, path: string) path, BigInt(data.blockHeight), block.block.header.time as any, - path.split(".")[3], - path.split(".")[3], + path.split('.')[3], + path.split('.')[3], BigInt(payload.anchorPoolBalance.__value), BigInt(payload.feePoolBalance.__value), BigInt(payload.mintedPoolBalance.__value), BigInt(payload.totalAnchorProvided.__value), - BigInt(payload.totalMintedProvided.__value) + BigInt(payload.totalMintedProvided.__value), ).save(); return [psmMetric, psmMetricDaily]; @@ -25,7 +25,7 @@ export const psmEventKit = (block: any, data: any, module: string, path: string) let state = await getPsmMetricDaily(dateKey); - state.denom = path.split(".")[3]; + state.denom = path.split('.')[3]; state.anchorPoolBalanceLast = BigInt(payload.anchorPoolBalance.__value); state.feePoolBalanceLast = BigInt(payload.feePoolBalance.__value); @@ -39,10 +39,16 @@ export const psmEventKit = (block: any, data: any, module: string, path: string) } async function getPsmMetricDaily(dateKey: number): Promise { - const id = path + ":" + dateKey.toString(); + const id = path + ':' + dateKey.toString(); let state = await PsmMetricsDaily.get(id); if (!state) { - state = new PsmMetricsDaily(id, path, dateKey, BigInt(data.blockHeight), new Date(block.block.header.time as any)); + state = new PsmMetricsDaily( + id, + path, + dateKey, + BigInt(data.blockHeight), + new Date(block.block.header.time as any), + ); } return state; } @@ -52,13 +58,13 @@ export const psmEventKit = (block: any, data: any, module: string, path: string) path, BigInt(data.blockHeight), block.block.header.time as any, - path.split(".")[3], - path.split(".")[3], + path.split('.')[3], + path.split('.')[3], BigInt(payload.current.MintLimit.value.__value), BigInt(payload.current.GiveMintedFee?.value?.denominator?.__value ?? 0), BigInt(payload.current.GiveMintedFee?.value?.numerator?.__value ?? 0), BigInt(payload.current.WantMintedFee?.value?.denominator?.__value ?? 0), - BigInt(payload.current.WantMintedFee?.value?.numerator?.__value ?? 0) + BigInt(payload.current.WantMintedFee?.value?.numerator?.__value ?? 0), ).save(); return [psmGovernance]; } diff --git a/src/mappings/events/reserves.ts b/src/mappings/events/reserves.ts index 4c93ad70..52827e91 100644 --- a/src/mappings/events/reserves.ts +++ b/src/mappings/events/reserves.ts @@ -1,6 +1,6 @@ -import { promises } from "dns"; -import { ReserveAllocationMetrics, ReserveAllocationMetricsDaily, ReserveMetrics } from "../../types"; -import { dateToDayKey, extractBrand } from "../utils"; +import { promises } from 'dns'; +import { ReserveAllocationMetrics, ReserveAllocationMetricsDaily, ReserveMetrics } from '../../types'; +import { dateToDayKey, extractBrand } from '../utils'; export const reservesEventKit = (block: any, data: any, module: string, path: string) => { async function saveReserveMetrics(payload: any): Promise[]> { @@ -11,7 +11,7 @@ export const reservesEventKit = (block: any, data: any, module: string, path: st block.block.header.time as any, BigInt(payload.shortfallBalance.__value), BigInt(payload.totalFeeBurned.__value), - BigInt(payload.totalFeeMinted.__value) + BigInt(payload.totalFeeMinted.__value), ); promises.push(reserveMetric.save()); @@ -30,7 +30,7 @@ export const reservesEventKit = (block: any, data: any, module: string, path: st brand, key, BigInt(allocation.__value), - reserveMetric.id + reserveMetric.id, ); promises.push(reserveAllocationMetric.save()); @@ -40,7 +40,12 @@ export const reservesEventKit = (block: any, data: any, module: string, path: st return promises; } - async function saveReserveAllocationMetricDaily(brand: string, payload: any, allocation: any, key: string): Promise { + async function saveReserveAllocationMetricDaily( + brand: string, + payload: any, + allocation: any, + key: string, + ): Promise { const dateKey = dateToDayKey(block.block.header.time); let state = await getReserveAllocationMetricDaily(brand, dateKey); @@ -54,9 +59,9 @@ export const reservesEventKit = (block: any, data: any, module: string, path: st async function getReserveAllocationMetricDaily( brand: string, - dateKey: number + dateKey: number, ): Promise { - const id = brand + ":" + dateKey.toString(); + const id = brand + ':' + dateKey.toString(); let state = await ReserveAllocationMetricsDaily.get(id); if (!state) { state = new ReserveAllocationMetricsDaily( @@ -64,7 +69,7 @@ export const reservesEventKit = (block: any, data: any, module: string, path: st brand, dateKey, BigInt(data.blockHeight), - new Date(block.block.header.time as any) + new Date(block.block.header.time as any), ); } return state; diff --git a/src/mappings/mappingHandlers.ts b/src/mappings/mappingHandlers.ts index d383490d..c97d6167 100644 --- a/src/mappings/mappingHandlers.ts +++ b/src/mappings/mappingHandlers.ts @@ -1,17 +1,12 @@ -import { - StateChangeEvent, - IBCChannel, - IBCTransfer, - TransferType, -} from "../types"; -import { CosmosEvent } from "@subql/types-cosmos"; +import { StateChangeEvent, IBCChannel, IBCTransfer, TransferType } from '../types'; +import { CosmosEvent } from '@subql/types-cosmos'; import { b64decode, extractStoragePath, getStateChangeModule, resolveBrandNamesAndValues, getEscrowAddress, -} from "./utils"; +} from './utils'; import { EVENT_TYPES, @@ -28,12 +23,12 @@ import { PACKET_DST_PORT_KEY, PACKET_SRC_PORT_KEY, TRANSFER_PORT_VALUE, -} from "./constants"; -import { psmEventKit } from "./events/psm"; -import { boardAuxEventKit } from "./events/boardAux"; -import { priceFeedEventKit } from "./events/priceFeed"; -import { vaultsEventKit } from "./events/vaults"; -import { reservesEventKit } from "./events/reserves"; +} from './constants'; +import { psmEventKit } from './events/psm'; +import { boardAuxEventKit } from './events/boardAux'; +import { priceFeedEventKit } from './events/priceFeed'; +import { vaultsEventKit } from './events/vaults'; +import { reservesEventKit } from './events/reserves'; // @ts-ignore BigInt.prototype.toJSON = function () { @@ -44,36 +39,36 @@ async function saveIbcChannel(channelName: string) { const generatedEscrowAddress = getEscrowAddress(TRANSFER_PORT_VALUE, channelName); const channelRecord = new IBCChannel(channelName, channelName, generatedEscrowAddress); - await channelRecord.save(); + return channelRecord.save(); } export async function handleIbcSendPacketEvent(cosmosEvent: CosmosEvent): Promise { const { event, block, tx } = cosmosEvent; if (event.type != EVENT_TYPES.SEND_PACKET) { - logger.warn("Not valid send_packet event."); + logger.warn('Not valid send_packet event.'); return; } const packetSrcPortAttr = event.attributes.find((a) => a.key === PACKET_SRC_PORT_KEY); if (!packetSrcPortAttr || packetSrcPortAttr.value !== TRANSFER_PORT_VALUE) { - logger.warn("packet_src_port is not transfer"); + logger.warn('packet_src_port is not transfer'); return; } const packetDataAttr = event.attributes.find((a) => a.key === PACKET_DATA_KEY); if (!packetDataAttr) { - logger.warn("No packet data attribute found"); + logger.warn('No packet data attribute found'); return; } const packetSrcChannelAttr = event.attributes.find((a) => a.key === PACKET_SRC_CHANNEL_KEY); if (!packetSrcChannelAttr) { - logger.warn("No packet source channel found"); + logger.warn('No packet source channel found'); return; } const { amount, denom, receiver, sender } = JSON.parse(packetDataAttr.value); const sourceChannel = packetSrcChannelAttr.value; - await saveIbcChannel(sourceChannel); + const ibcChannel = saveIbcChannel(sourceChannel); const transferRecord = new IBCTransfer( tx.hash, @@ -86,37 +81,37 @@ export async function handleIbcSendPacketEvent(cosmosEvent: CosmosEvent): Promis amount, TransferType.SEND, ); - await transferRecord.save(); + await Promise.allSettled([transferRecord.save(), ibcChannel]); } export async function handleIbcReceivePacketEvent(cosmosEvent: CosmosEvent): Promise { const { event, block, tx } = cosmosEvent; if (event.type != EVENT_TYPES.RECEIVE_PACKET) { - logger.warn("Not valid recv_packet event."); + logger.warn('Not valid recv_packet event.'); return; } const packetDataAttr = event.attributes.find((a) => a.key === PACKET_DATA_KEY); if (!packetDataAttr) { - logger.warn("No packet data attribute found"); + logger.warn('No packet data attribute found'); return; } const packetDestPortAttr = event.attributes.find((a) => a.key === PACKET_DST_PORT_KEY); if (!packetDestPortAttr || packetDestPortAttr.value !== TRANSFER_PORT_VALUE) { - logger.warn("packet_dest_port is not transfer"); + logger.warn('packet_dest_port is not transfer'); return; } const packetDstChannelAttr = event.attributes.find((a) => a.key === PACKET_DST_CHANNEL_KEY); if (!packetDstChannelAttr) { - logger.warn("No packet destination channel found"); + logger.warn('No packet destination channel found'); return; } const { amount, denom, receiver, sender } = JSON.parse(packetDataAttr.value); const destinationChannel = packetDstChannelAttr.value; - await saveIbcChannel(destinationChannel); + const ibcChannel = saveIbcChannel(destinationChannel); const transferRecord = new IBCTransfer( tx.hash, @@ -129,14 +124,15 @@ export async function handleIbcReceivePacketEvent(cosmosEvent: CosmosEvent): Pro amount, TransferType.RECEIVE, ); - await transferRecord.save(); + + await Promise.allSettled([transferRecord.save(), ibcChannel]); } export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise { const { event, block } = cosmosEvent; if (event.type != EVENT_TYPES.STATE_CHANGE) { - logger.warn("Not valid state_change event."); + logger.warn('Not valid state_change event.'); return; } @@ -147,13 +143,13 @@ export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise< const valueAttr = event.attributes.find((a) => a.key === VALUE_KEY || a.key === UNPROVED_VALUE_KEY); if (!valueAttr || !valueAttr.value) { - logger.warn("Value attribute is missing or empty."); + logger.warn('Value attribute is missing or empty.'); return; } const keyAttr = event.attributes.find((a) => a.key === KEY_KEY || a.key === SUBKEY_KEY); if (!keyAttr) { - logger.warn("Key attribute is missing or empty."); + logger.warn('Key attribute is missing or empty.'); return; } @@ -167,13 +163,13 @@ export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise< } if (!data.values) { - logger.warn("Data has not values."); + logger.warn('Data has not values.'); return; } const decodedKey = keyAttr.key === SUBKEY_KEY - ? b64decode(b64decode(keyAttr.value)).replaceAll("\u0000", "\x00") + ? b64decode(b64decode(keyAttr.value)).replaceAll('\u0000', '\x00') : b64decode(keyAttr.value); const path = extractStoragePath(decodedKey); const module = getStateChangeModule(path); @@ -226,7 +222,7 @@ export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise< } const value = JSON.parse(rawValue); - const payload = JSON.parse(value.body.replace(/^#/, "")); + const payload = JSON.parse(value.body.replace(/^#/, '')); resolveBrandNamesAndValues(payload); try { diff --git a/src/mappings/utils.ts b/src/mappings/utils.ts index 53b62faf..e0a05639 100644 --- a/src/mappings/utils.ts +++ b/src/mappings/utils.ts @@ -1,63 +1,63 @@ -import { bech32 } from "bech32"; -import sha256 from "js-sha256"; +import { bech32 } from 'bech32'; +import sha256 from 'js-sha256'; export function extractBrand(str: string): string { - return str.replace("Alleged: ", "").replace(" brand", ""); + return str.replace('Alleged: ', '').replace(' brand', ''); } export function extractStoragePath(value: string): string { - const parts = value.split("\x00"); + const parts = value.split('\x00'); if (parts.length === 0) { - return ""; + return ''; } - const length = parseInt(parts.shift() || "0", 10); + const length = parseInt(parts.shift() || '0', 10); if (length !== parts.length) { throw new Error(`unexpected path ${value}`); } - return parts.join("."); + return parts.join('.'); } export function resolveBrandNamesAndValues(body: any, names: { [key: string]: any } = {}): void { const slotPattern = /^\$(\d+).?(.*)/; const numberPattern = /^[+-]{1}(\d+)$/; - if (typeof body === "object" && body !== null) { + if (typeof body === 'object' && body !== null) { for (const key in body) { if (body.hasOwnProperty(key)) { const value = body[key]; // Deprecated but exists in chains - if (typeof value === "object" && value !== null) { - if (value["@qclass"] === "slot") { - if (value["iface"]) { - names[value["index"]] = extractBrand(value["iface"]); + if (typeof value === 'object' && value !== null) { + if (value['@qclass'] === 'slot') { + if (value['iface']) { + names[value['index']] = extractBrand(value['iface']); } - if (value["index"] in names) { - body["__" + key] = names[value["index"]]; + if (value['index'] in names) { + body['__' + key] = names[value['index']]; } } - if (value["@qclass"] === "bigint") { - body["__" + key] = value["digits"]; + if (value['@qclass'] === 'bigint') { + body['__' + key] = value['digits']; } } // Smallcaps - if (typeof value === "string") { + if (typeof value === 'string') { const sm = value.match(slotPattern); if (sm && sm.length > 0) { const idx = parseInt(sm[1], 10); - if (sm[2] !== "") { + if (sm[2] !== '') { names[idx] = extractBrand(sm[2]); } if (idx in names) { - body["__" + key] = names[idx]; + body['__' + key] = names[idx]; } continue; @@ -65,7 +65,7 @@ export function resolveBrandNamesAndValues(body: any, names: { [key: string]: an const nm = value.match(numberPattern); if (nm) { - body["__" + key] = nm[1]; + body['__' + key] = nm[1]; } } else { resolveBrandNamesAndValues(value, names); @@ -80,28 +80,28 @@ export function resolveBrandNamesAndValues(body: any, names: { [key: string]: an } export function getStateChangeModule(path: string): string { - return path.split(".")[0] + "." + path.split(".")[1]; + return path.split('.')[0] + '.' + path.split('.')[1]; } export function b64decode(val: string) { - return new Buffer(val, "base64").toString(); + return new Buffer(val, 'base64').toString(); } export function b64encode(val: string) { - return Buffer.from(val).toString("base64"); + return Buffer.from(val).toString('base64'); } export function dateToDayKey(timestamp: any): number { const date = new Date(timestamp); const year = date.getUTCFullYear(); - const month = (date.getUTCMonth() + 1).toString().padStart(2, "0"); - const day = date.getUTCDate().toString().padStart(2, "0"); + const month = (date.getUTCMonth() + 1).toString().padStart(2, '0'); + const day = date.getUTCDate().toString().padStart(2, '0'); return parseInt(`${year}${month}${day}`); } export const getEscrowAddress = (port: string, channel: string) => { - const version = "ics20-1"; - const chainPrefix = "agoric"; + const version = 'ics20-1'; + const chainPrefix = 'agoric'; const stringtoSha = Buffer.from([...Buffer.from(version), 0, ...Buffer.from(`${port}/${channel}`)]); const shaHash = sha256.sha256.array(stringtoSha.toString()); const bechWords = bech32.toWords(shaHash.slice(0, 20));