Skip to content

Commit

Permalink
feat: add handlers for incrementing and decrementing balances
Browse files Browse the repository at this point in the history
  • Loading branch information
rabi-siddique committed May 2, 2024
1 parent 5147932 commit d92e50e
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 51 deletions.
75 changes: 71 additions & 4 deletions project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ const project: CosmosProject = {
},
network: {
// chainId: "agoriclocal",
// endpoint: ["http://host.docker.internal:26657/"],
// endpoint: ["http://agoric-subql_agd_1:26657/"],
// chainId: "agoric-emerynet-8",
// endpoint: ["https://emerynet.rpc.agoric.net:443"],
chainId: "agoric-3",
endpoint: ["https://main-a.rpc.agoric.net:443"],

Expand Down Expand Up @@ -87,11 +89,76 @@ const project: CosmosProject = {
type: "state_change",
},
},
// Bank Events
{
handler: "handleTransferEvent",
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "transfer",
type: "coinbase",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "coin_received",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "coin_spent",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "burn",
},
},
// {
// handler: "handleTransferEvent",
// kind: CosmosHandlerKind.Event,
// filter: {
// type: "transfer",
// },
// },
// Distribution Events
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "rewards",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "commission",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "proposer_reward",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "withdraw_rewards",
},
},
{
handler: "handleBalanceEvent",
kind: CosmosHandlerKind.Event,
filter: {
type: "withdraw_commission",
},
},
],
Expand All @@ -101,4 +168,4 @@ const project: CosmosProject = {
};

// Must set default to the project instance
export default project;
export default project;
22 changes: 17 additions & 5 deletions src/mappings/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,23 @@ export const VAULT_STATES = {
LIQUIDATED: "liquidated"
}

export const TRANSACTION_FIELDS = {
RECIPIENT: 'recipient',
SENDER: 'sender',
AMOUNT: 'amount'
}
export const BALANCE_FIELDS = {
amount: 'amount',
// Bank Events
coinbase: 'minter',
coin_received: 'receiver',
coin_spent: 'spender',
transfer_recipient: 'recipient',
transfer_sender: 'sender',
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");
Expand Down
76 changes: 46 additions & 30 deletions src/mappings/events/balances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export interface DecodedEvent {
type: string;
attributes: Attribute[];
}

export enum Operation {
Increment = 'increment',
Decrement = 'decrement',
}
export const balancesEventKit = () => {
function getAttributeValue(decodedData: DecodedEvent, key: string) {
const attribute = decodedData.attributes.find((attr) => attr.key === key);
Expand Down Expand Up @@ -40,7 +45,8 @@ export const balancesEventKit = () => {

async function addressExists(address: string): Promise<boolean> {
const balance = await Balances.getByAddress(address);
if (balance?.length === 0) {

if (!balance || balance.length === 0) {
return false;
}
return true;
Expand All @@ -50,55 +56,65 @@ export const balancesEventKit = () => {
const newBalance = new Balances(address);
newBalance.address = address;
newBalance.balance = BigInt(0);
newBalance.denom = '';
newBalance.denom = 'ubld';

await newBalance.save();

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

async function updateBalances(
senderAddress: string,
recipientAddress: string,
amount: bigint
function isBLDTransaction(amount: string) {
if (amount.slice(-4) === 'ubld') {
return true;
}
return false;
}

async function updateBalance(
address: string,
amount: bigint,
operation: Operation
): Promise<void> {
const senderBalances = await Balances.getByAddress(senderAddress);
const recipientBalances = await Balances.getByAddress(recipientAddress);
const balances = await Balances.getByAddress(address);

if (!senderBalances || senderBalances.length === 0) {
logger.error(`Sender balance not found for address: ${senderAddress}`);
if (!balances || balances.length === 0) {
logger.error(`Balance not found for address: ${address}`);
return;
}

if (!recipientBalances || recipientBalances.length === 0) {
logger.error(
`Recipient balance not found for address: ${recipientAddress}`
const balance = balances[0];
const currentBalance = balance.balance ?? BigInt(0);
let newBalance: bigint;

if (operation === Operation.Increment) {
newBalance = currentBalance + amount;
balance.balance = newBalance;
logger.info(
`Incremented balance for ${address} by ${amount}. New balance: ${balance.balance}`
);
} else if (operation === Operation.Decrement) {
newBalance = currentBalance - amount;
if (newBalance < 0) {
logger.error(
`Attempt to decrement ${amount} would result in a negative balance. Current balance: ${currentBalance}.`
);
return;
}
balance.balance = newBalance;
logger.info(
`Decremented balance for ${address} by ${amount}. New balance: ${balance.balance}`
);
return;
}

const senderBalance = senderBalances[0];
const recipientBalance = recipientBalances[0];

const senderCurrentBalance = senderBalance.balance ?? BigInt(0);
const recipientCurrentBalance = recipientBalance.balance ?? BigInt(0);

senderBalance.balance = senderCurrentBalance - amount;
recipientBalance.balance = recipientCurrentBalance + amount;

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

logger.info(
`Updated balances: Sender ${senderAddress} balance: ${senderBalance.balance}, Recipient ${recipientAddress} balance: ${recipientBalance.balance}`
);
await balance.save();
}

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

// @ts-ignore
BigInt.prototype.toJSON = function () {
Expand Down Expand Up @@ -169,27 +169,30 @@ export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise<
export async function handleTransferEvent(
cosmosEvent: CosmosEvent
): Promise<void> {
const { event, block } = cosmosEvent;
const { event } = cosmosEvent;

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

logger.info('Event:TRANSFER');

const balancesKit = balancesEventKit();
const decodedData: DecodedEvent = balancesKit.decodeEvent(cosmosEvent);
logger.info(`Decoded transaction data ${JSON.stringify(decodedData)}`);

const recipientAddress = balancesKit.getAttributeValue(
decodedData,
TRANSACTION_FIELDS.RECIPIENT
BALANCE_FIELDS.transfer_recipient
);
const senderAddress = balancesKit.getAttributeValue(
decodedData,
TRANSACTION_FIELDS.SENDER
BALANCE_FIELDS.transfer_sender
);
const transactionAmount = balancesKit.getAttributeValue(
decodedData,
TRANSACTION_FIELDS.AMOUNT
BALANCE_FIELDS.amount
);

if (!recipientAddress) {
Expand All @@ -202,8 +205,8 @@ export async function handleTransferEvent(
return;
}

if (!transactionAmount) {
logger.error('Transaction amount is missing or invalid.');
if (!transactionAmount || !balancesKit.isBLDTransaction(transactionAmount)) {
logger.error(`Amount ${transactionAmount?.slice(0, -4)} invalid.`);
return;
}

Expand All @@ -220,9 +223,75 @@ export async function handleTransferEvent(
await balancesKit.createBalancesEntry(senderAddress);
}

balancesKit.updateBalances(
senderAddress,
recipientAddress,
BigInt(transactionAmount.slice(0, -4))
const adjustedAmount = BigInt(Math.round(Number(transactionAmount.slice(0, -4))));

await Promise.all([
balancesKit.updateBalance(senderAddress, adjustedAmount, Operation.Decrement),
balancesKit.updateBalance(recipientAddress, adjustedAmount, Operation.Increment),
]);
}

export async function handleBalanceEvent(
cosmosEvent: CosmosEvent
): Promise<void> {
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,
];

let operation: Operation | null = null;

if (incrementEventTypes.includes(event.type)) {
operation = Operation.Increment;
} else if (decrementEventTypes.includes(event.type)) {
operation = Operation.Decrement;
} else {
logger.warn(`${event.type} is not a valid balance event.`);
return;
}

logger.info(`Event:${event.type}`);

const balancesKit = balancesEventKit();
const decodedData: DecodedEvent = balancesKit.decodeEvent(cosmosEvent);
logger.info(`Decoded transaction data ${JSON.stringify(decodedData)}`);

const address = balancesKit.getAttributeValue(
decodedData,
BALANCE_FIELDS[event.type as keyof typeof BALANCE_FIELDS]
);

const transactionAmount = balancesKit.getAttributeValue(
decodedData,
BALANCE_FIELDS.amount
);

if (!address) {
logger.error('Address is missing or invalid.');
return;
}

if (!transactionAmount || !balancesKit.isBLDTransaction(transactionAmount)) {
logger.error(`Amount ${transactionAmount} invalid.`);
return;
}

const entryExists = await balancesKit.addressExists(address);

if (!entryExists) {
await balancesKit.createBalancesEntry(address);
}

const amount = BigInt(Math.round(Number(transactionAmount.slice(0, -4))));
await balancesKit.updateBalance(address, amount, operation);
}

0 comments on commit d92e50e

Please sign in to comment.