diff --git a/genesis-local.json b/genesis-local.json deleted file mode 100644 index a2cef0c9..00000000 --- a/genesis-local.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "balances": [ - { - "address": "agoric1estsewt6jqsx77pwcxkn5ah0jqgu8rhgflwfdl", - "coins": [ - { - "denom": "ubld", - "amount": "999999995000000000" - } - ] - } - ] -} diff --git a/genesis-main.json b/genesis-main.json deleted file mode 100644 index 55851a92..00000000 --- a/genesis-main.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "balances": [ - { - "address": "agoric1qc3r5tlh9ldvcg54lj8ukrwhytpffkmjxav87c", - "coins": [ - { - "denom": "ubld", - "amount": "1000000" - } - ] - }, - { - "address": "agoric18du3gnu9qqgrcfln804g8gcmruv2gjwgs7mj3l", - "coins": [ - { - "denom": "ubld", - "amount": "497000000" - } - ] - }, - { - "address": "agoric18c72hdqrcc4hkpewvpf7grrx8rawk0045g3tm0", - "coins": [ - { - "amount": "200000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric18m9lqhqas8qrwafj92kta0ek2q96kwvyt84793", - "coins": [ - { - "amount": "49999400000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1grgelyng2v6v3t8z87wu3sxgt9m5s03x7dax7m", - "coins": [ - { - "amount": "1000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1gmru5vv2zrz9m0d3vwjz6fcchw9ddmq9w3s2qy", - "coins": [ - { - "amount": "1000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1fl48vsnmsdzcv85q5d2q4z5ajdha8yu38xtsfp", - "coins": [ - { - "amount": "100000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1w89nsqmcjfw9la2x8pk5k8pwwsgh8mhqs53tsr", - "coins": [ - { - "amount": "300000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric10fz6uxxlg7pdkscgpzcny4z6lzhqcluyqhr8au", - "coins": [ - { - "amount": "30000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric10mmdskqh6nv8tzd4lhzpevwlky35m43s45ssg5", - "coins": [ - { - "amount": "125000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1kxquj9rnprhyaq2laulgqznz7t6yqmw6wm5ucx", - "coins": [ - { - "amount": "45000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1euw2t0lxgeerlpj0tcy77f9syrmgx26ehdx3sq", - "coins": [ - { - "amount": "100000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric1a0fktnlglcpj3pkzwftnr63uqr42mmcskuhakj", - "coins": [ - { - "amount": "25000000000000", - "denom": "ubld" - } - ] - }, - { - "address": "agoric179gfr279yh3zhdw7aw85t7kj4vcsazdckzd42e", - "coins": [ - { - "amount": "125000000000000", - "denom": "ubld" - } - ] - } - ] -} diff --git a/schema.graphql b/schema.graphql index 81cf0500..0fd219c6 100644 --- a/schema.graphql +++ b/schema.graphql @@ -130,16 +130,40 @@ type Vault @entity { id: ID! blockHeight: BigInt! blockTime: Date! - balance: BigInt + balance: BigInt # use lockedValue instead lockedValue: BigInt coin: String @index # use denom instead denom: String @index debt: BigInt state: String wallet: Wallet! - liquidatingAt: Date - liquidatedAt: Date - liquidated: Boolean +} + +type VaultManagerGovernanceJson @jsonField { + liquidationMarginDenominator: BigInt + liquidationMarginNumerator: BigInt +} + +type OraclePriceJson @jsonField { + typeInAmount: BigInt + typeOutAmount: BigInt +} + +type VaultLiquidation @entity { + id: ID! + blockHeight: BigInt! + blockTime: Date! + balance: BigInt # use lockedValue instead + lockedValue: BigInt + coin: String @index # use denom instead + denom: String @index + debt: BigInt + state: String + wallet: Wallet! + currentState: Vault! + liquidatingState: VaultLiquidation! + vaultManagerGovernance: VaultManagerGovernanceJson + oraclePrice: OraclePriceJson } type VaultManagerMetrics @entity { @@ -242,6 +266,10 @@ type ReserveMetrics @entity { allocations: [ReserveAllocationMetrics] @derivedFrom(field: "reserveMetrics") } +type Account @entity { + id: ID! +} + type IBCChannel @entity { id: ID! channelName: String! @@ -265,15 +293,13 @@ type IBCTransfer @entity { transferType: TransferType! } -type Balance @entity { +type VaultStatesDaily @entity { id: ID! - address: String @index - balance: BigInt - denom: String @index - account: Account! -} - -type Account @entity { - id: ID! - balances: [Balance] @derivedFrom(field: "account") + blockHeightLast: BigInt! + blockTimeLast: Date! + active: BigInt! + closed: BigInt! + liquidating: BigInt! + liquidated: BigInt! + liquidatedClosed: BigInt! } diff --git a/src/mappings/constants.ts b/src/mappings/constants.ts index d5180a18..73ebff26 100644 --- a/src/mappings/constants.ts +++ b/src/mappings/constants.ts @@ -1,33 +1,56 @@ -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", + ACTIVE: 'active', + CLOSED: 'closed', + 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 BALANCE_FIELDS = { amount: 'amount', // Bank Events @@ -36,33 +59,16 @@ export const BALANCE_FIELDS = { coin_spent: 'spender', transfer_recipient: 'recipient', transfer_sender: 'sender', - burn: "burner", + burn: 'burner', // Distribution Events rewards: 'validator', commission: 'validator', proposer_reward: 'validator', withdraw_rewards: 'validator', withdraw_commission: 'validator', - }; -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 FETCH_ACCOUNTS_URL = + 'http://localhost:1317/cosmos/auth/v1beta1/accounts'; +export const GET_FETCH_BALANCE_URL = (address: string) => + `http://localhost:1317/cosmos/bank/v1beta1/balances/${address}`; diff --git a/src/mappings/custom-types.ts b/src/mappings/custom-types.ts new file mode 100644 index 00000000..8400039d --- /dev/null +++ b/src/mappings/custom-types.ts @@ -0,0 +1,44 @@ +export type Balance = { + denom: string; + amount: string; +}; + +interface PubKey { + '@type': string; + key: string; +} + +export type BaseAccount = { + '@type': string; + address: string; + pub_key: PubKey | null; + account_number: string; + sequence: string; +}; + +export type ModuleAccount = { + '@type': string; + base_account: { + address: string; + pub_key: PubKey | null; + account_number: string; + sequence: string; + }; + name: string; + permissions: string[]; +}; + +type Pagination = { + next_key: string | null; + total: string; +}; + +export type BalancesResponse = { + balances: Balance[]; + pagination: Pagination; +}; + +export type AccountsResponse = { + accounts: (BaseAccount | ModuleAccount)[]; + pagination: Pagination; +}; diff --git a/src/mappings/events/balances.ts b/src/mappings/events/balances.ts index 63ee67de..6f797de8 100644 --- a/src/mappings/events/balances.ts +++ b/src/mappings/events/balances.ts @@ -1,4 +1,4 @@ -import { Account, Balance } from '../../types'; +import { Account, Balances } from '../../types'; import { BALANCE_FIELDS } from '../constants'; import { b64decode } from '../utils'; import { CosmosEvent } from '@subql/types-cosmos'; @@ -72,7 +72,7 @@ export const balancesEventKit = () => { address: string, denom: string ): Promise { - const balance = await Balance.getByFields([ + const balance = await Balances.getByFields([ ['address', '=', address], ['denom', '=', denom], ]); @@ -88,7 +88,7 @@ export const balancesEventKit = () => { denom: string, primaryKey: string ) { - const newBalance = new Balance(primaryKey, address); + const newBalance = new Balances(primaryKey); newBalance.address = address; newBalance.balance = BigInt(0); newBalance.denom = denom; @@ -136,7 +136,7 @@ export const balancesEventKit = () => { amount: bigint, operation: Operation ): Promise { - const balances = await Balance.getByFields([ + const balances = await Balances.getByFields([ ['address', '=', address], ['denom', '=', denom], ]); diff --git a/src/mappings/mappingHandlers.ts b/src/mappings/mappingHandlers.ts index f35a10da..d22c6523 100644 --- a/src/mappings/mappingHandlers.ts +++ b/src/mappings/mappingHandlers.ts @@ -1,18 +1,14 @@ -import { - StateChangeEvent, - Balance, - IBCTransfer, - IBCChannel, - TransferType -} from "../types"; -import { CosmosBlock, CosmosEvent } from "@subql/types-cosmos"; +import { StateChangeEvent, IBCChannel, IBCTransfer, TransferType, Balances } from '../types'; +import { CosmosBlock, CosmosEvent } from '@subql/types-cosmos'; import { b64decode, extractStoragePath, getStateChangeModule, resolveBrandNamesAndValues, getEscrowAddress, -} from "./utils"; + isBaseAccount, + isModuleAccount, +} from './utils'; import { EVENT_TYPES, @@ -30,15 +26,24 @@ import { PACKET_SRC_PORT_KEY, TRANSFER_PORT_VALUE, BALANCE_FIELDS, -} 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"; -import { DecodedEvent, Operation, balancesEventKit } from "./events/balances"; -import localGenesisData from "../../genesis-local.json"; -import mainnetGenesisData from "../../genesis-main.json"; + FETCH_ACCOUNTS_URL, + GET_FETCH_BALANCE_URL, +} 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'; +import { + AccountsResponse, + BaseAccount, + ModuleAccount, + BalancesResponse, + Balance, +} from './custom-types'; +import { Operation, balancesEventKit } from './events/balances'; +import axios from 'axios'; + // @ts-ignore BigInt.prototype.toJSON = function () { return this.toString(); @@ -48,36 +53,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, @@ -90,37 +95,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, @@ -133,14 +138,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; } @@ -151,13 +157,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; } @@ -171,13 +177,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); @@ -230,7 +236,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 { @@ -250,20 +256,14 @@ export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise< await Promise.allSettled(recordSaves); } -export async function handleBalanceEvent( + +export const handleBalanceEvent = async ( cosmosEvent: CosmosEvent -): Promise { +): Promise => { const { event } = cosmosEvent; - const incrementEventTypes = [ - EVENT_TYPES.COMMISSION, - EVENT_TYPES.REWARDS, - EVENT_TYPES.PROPOSER_REWARD, - EVENT_TYPES.COIN_RECEIVED, - EVENT_TYPES.COINBASE, - ]; - - const decrementEventTypes = [EVENT_TYPES.COIN_SPENT, EVENT_TYPES.BURN]; + const incrementEventTypes = [EVENT_TYPES.COIN_RECEIVED]; + const decrementEventTypes = [EVENT_TYPES.COIN_SPENT]; let operation: Operation | null = null; @@ -294,7 +294,7 @@ export async function handleBalanceEvent( ); if (!address) { - logger.error(`Address ${address} is missing or invalid.`); + logger.error('Address is missing or invalid.'); return; } @@ -306,37 +306,79 @@ export async function handleBalanceEvent( return; } - for (let coin of coins) { - const { amount, denom } = coin; + for (let { denom, amount } of coins) { const entryExists = await balancesKit.addressExists(address, denom); if (!entryExists) { - const primaryKey = `${address}-${denom}`; + const primaryKey = address + denom; await balancesKit.createBalancesEntry(address, denom, primaryKey); } - const formattedAmount = BigInt(Math.round(Number(amount))); + const formattedAmount = BigInt(Math.round(Number(amount.slice(0, -4)))); await balancesKit.updateBalance(address, denom, formattedAmount, operation); } -} +}; -export async function initiateBalancesTable(block: CosmosBlock): Promise { +const fetchAccounts = async (): Promise => { try { - const data = mainnetGenesisData; - for (let element of data.balances) { - let newBalance; - for (const coin of element.coins) { - newBalance = new Balance(`${element.address}-${coin.denom}`, element.address); - newBalance.address = element.address; - newBalance.balance = BigInt(coin.amount); - newBalance.denom = coin.denom; - - await newBalance.save(); + const response = await axios.get(FETCH_ACCOUNTS_URL); + const accounts: AccountsResponse = response.data; + return accounts; + } catch (error) { + logger.error(`Error fetching accounts: ${error}`); + } +}; + +const extractAddresses = ( + accounts: (BaseAccount | ModuleAccount)[] +): Array => { + return accounts + .map((account) => { + if (isBaseAccount(account)) { + return account.address; + } else if (isModuleAccount(account)) { + return account.base_account.address; } - } + return ''; + }) + .filter((address) => address !== null); +}; - logger.info(`Balances Table Initiated`); +const fetchBalance = async ( + address: string +): Promise => { + try { + const response = await axios.get(GET_FETCH_BALANCE_URL(address)); + const balance: BalancesResponse = response.data; + return balance; } catch (error) { - logger.error(`Error initiating balances table: ${error}`); + logger.error(`Error fetching balance for address ${address}: ${error}`); + } +}; + +const saveAccountBalances = async (address: string, balances: Balance[]) => { + for (let { denom, amount } of balances) { + const newBalance = new Balances(address); + newBalance.address = address; + newBalance.balance = BigInt(amount); + newBalance.denom = denom; + + await newBalance.save(); } -} \ No newline at end of file +}; + +export const initiateBalancesTable = async ( + block: CosmosBlock +): Promise => { + const response = await fetchAccounts(); + if (response) { + const accountAddresses = extractAddresses(response.accounts); + for (let address of accountAddresses) { + const response = await fetchBalance(address); + + if (response) { + await saveAccountBalances(address, response.balances); + } + } + } +}; diff --git a/src/mappings/utils.ts b/src/mappings/utils.ts index 53b62faf..0cffc450 100644 --- a/src/mappings/utils.ts +++ b/src/mappings/utils.ts @@ -1,5 +1,6 @@ import { bech32 } from "bech32"; import sha256 from "js-sha256"; +import { BaseAccount, ModuleAccount } from "./custom-types"; export function extractBrand(str: string): string { return str.replace("Alleged: ", "").replace(" brand", ""); @@ -108,3 +109,11 @@ export const getEscrowAddress = (port: string, channel: string) => { const address = bech32.encode(chainPrefix, bechWords); return address; }; + +export const isBaseAccount = (account: any): account is BaseAccount => { + return account['@type'] === '/cosmos.auth.v1beta1.BaseAccount'; +}; + +export const isModuleAccount = (account: any): account is ModuleAccount => { + return account['@type'] === '/cosmos.auth.v1beta1.ModuleAccount'; +}; \ No newline at end of file