Skip to content

Commit

Permalink
feat: index transfer events
Browse files Browse the repository at this point in the history
  • Loading branch information
rabi-siddique committed Apr 30, 2024
1 parent 1b45aa1 commit 534ce8c
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 0 deletions.
7 changes: 7 additions & 0 deletions project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ const project: CosmosProject = {
type: "state_change",
},
},
{
handler: "handleTransferEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "transfer",
},
},
],
},
},
Expand Down
7 changes: 7 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,10 @@ type ReserveMetrics @entity {
totalFeeMinted: BigInt!
allocations: [ReserveAllocationMetrics] @derivedFrom(field: "reserveMetrics")
}

type Balances @entity {
id: ID!
address: String @index
balance: BigInt
denom: String @index
}
6 changes: 6 additions & 0 deletions src/mappings/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export const VAULT_STATES = {
LIQUIDATED: "liquidated"
}

export const TRANSACTION_FIELDS = {
RECIPIENT: 'recipient',
SENDER: 'sender',
AMOUNT: 'amount'
}

export const VALUE_KEY = b64encode("value");
export const STORE_KEY = b64encode("store");
export const VSTORAGE_VALUE = b64encode("vstorage");
Expand Down
97 changes: 97 additions & 0 deletions src/mappings/events/balances.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Balances } from '../../types';
import { b64decode } from '../utils';
import { CosmosEvent } from '@subql/types-cosmos';

interface Attribute {
key: string;
value: string;
}

export interface DecodedEvent {
type: string;
attributes: Attribute[];
}
export const balancesEventKit = () => {
function decodeEvent(cosmosEvent: CosmosEvent): DecodedEvent {
const { event } = cosmosEvent;

const decodedData: DecodedEvent = {
type: event.type,
attributes: [],
};

event.attributes.forEach((attribute) => {
const decodedKey = b64decode(attribute.key);
const decodedValue = b64decode(attribute.value);

decodedData.attributes.push({
key: decodedKey,
value: decodedValue,
});
});

return decodedData;
}

async function addressExists(address: string): Promise<boolean> {
const balance = await Balances.getByAddress(address);
if (!balance) {
return false;
}
return true;
}

async function createBalancesEntry(address: string) {
const newBalance = new Balances(address);
newBalance.address = address;
newBalance.balance = BigInt(0);
newBalance.denom = '';

await newBalance.save();

logger.info(`Created new entry for address: ${address}`);
}

async function updateBalances(
senderAddress: string,
recipientAddress: string,
amount: bigint
): Promise<void> {
const senderBalances = await Balances.getByAddress(senderAddress);
const senderBalance = senderBalances ? senderBalances[0] : undefined;

const recipientBalances = await Balances.getByAddress(recipientAddress);
const recipientBalance = recipientBalances
? recipientBalances[0]
: undefined;

if (senderBalance && recipientBalance) {
senderBalance.balance = (senderBalance.balance || BigInt(0)) - amount;
recipientBalance.balance =
(recipientBalance.balance || BigInt(0)) + amount;

await senderBalance.save();
await recipientBalance.save();

logger.info(
`Updated balances: Sender (${senderAddress}) balance: ${senderBalance.balance}, Recipient (${recipientAddress}) balance: ${recipientBalance.balance}`
);
} else {
if (!senderBalance) {
logger.error(`Sender balance not found for address: ${senderAddress}`);
}
if (!recipientBalance) {
logger.error(
`Recipient balance not found for address: ${recipientAddress}`
);
}
}
}

return {
decodeEvent,
addressExists,
createBalancesEntry,
updateBalances,
};
};
42 changes: 42 additions & 0 deletions src/mappings/mappingHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ import {
STORE_NAME_KEY,
SUBKEY_KEY,
UNPROVED_VALUE_KEY,
TRANSACTION_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, balancesEventKit } from "./events/balances";

// @ts-ignore
BigInt.prototype.toJSON = function () {
Expand Down Expand Up @@ -163,3 +165,43 @@ export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise<

await Promise.allSettled(recordSaves);
}

export async function handleTransferEvent(
cosmosEvent: CosmosEvent
): Promise<void> {
const { event, block } = cosmosEvent;

if (event.type != EVENT_TYPES.TRANSFER) {
logger.warn('Not valid transfer event.');
return;
}

const balancesKit = balancesEventKit();
const decodedData: DecodedEvent = balancesKit.decodeEvent(cosmosEvent);

const recipientAddress =
decodedData.attributes.find(
(attr) => attr.key === TRANSACTION_FIELDS.RECIPIENT
)?.value || '';

if (recipientAddress && (await balancesKit.addressExists(recipientAddress))) {
await balancesKit.createBalancesEntry(recipientAddress);
}

const senderAddress =
decodedData.attributes.find(
(attr) => attr.key === TRANSACTION_FIELDS.SENDER
)?.value || '';

if (senderAddress && (await balancesKit.addressExists(senderAddress))) {
await balancesKit.createBalancesEntry(senderAddress);
}

const amount = BigInt(
decodedData.attributes
.find((attr) => attr.key === TRANSACTION_FIELDS.AMOUNT)
?.value.slice(0, -3) || 0
);

balancesKit.updateBalances(senderAddress, recipientAddress, amount);
}

0 comments on commit 534ce8c

Please sign in to comment.