Skip to content

Commit

Permalink
feat: extra events Sentio (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
martines3000 authored Oct 22, 2024
1 parent e492456 commit 69f5dd9
Show file tree
Hide file tree
Showing 5 changed files with 652 additions and 244 deletions.
2 changes: 0 additions & 2 deletions apps/frontend/src/hooks/useUserRole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ export const useUserRole = () => {
return USER_ROLE.NONE;
}

// FIXME: Extract to separate hook to calculate supply/borrow value in dollars
// then specify a $ treshold in CONSTANTS for supply/borrow
const supplyTreshold = BigNumber(0.1).times(
BigNumber(10).pow(marketConfiguration.baseTokenDecimals)
);
Expand Down
15 changes: 15 additions & 0 deletions apps/indexer-sentio/queries/events.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
SELECT timestamp,
chainId as chain_id,
blockNumber as block_number,
logIndex as log_index,
transactionHash as transaction_hash,
userAddress as user_address,
takerAddress as taker_address,
poolAddress as pool_address,
tokenAddress as token_address,
amountNormalized as amount,
amountUsd,
eventType as event_type
FROM `EventEntity`
WHERE timestamp > timestamp('{{timestamp}}')
ORDER BY timestamp asc
237 changes: 237 additions & 0 deletions apps/indexer-sentio/src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
CollateralPoolSnapshot,
CollateralPosition,
CollateralPositionSnapshot,
EventEntity,
MarketBasic,
MarketConfiguration,
Pool,
Expand Down Expand Up @@ -427,6 +428,7 @@ Object.values(appConfig.markets).forEach(({ marketAddress, startBlock }) => {
asset_id: { bits: asset_id },
amount,
},
receiptIndex,
} = event;

const address = (account.Address?.bits ?? account.ContractId?.bits)!;
Expand Down Expand Up @@ -521,6 +523,33 @@ Object.values(appConfig.markets).forEach(({ marketAddress, startBlock }) => {
.times(BigDecimal(collateralPrice));

await ctx.store.upsert(collateralPool);

// Collateral supply event
const blockNumber = ctx.transaction?.blockNumber!;
const eventId = `${chainId}_${ctx.contractAddress}_${blockNumber}_${receiptIndex}`;

const eventEntity = new EventEntity({
id: eventId,
timestamp: dayjs(ctx.timestamp.getTime()).utc().unix(),
chainId,
poolAddress: ctx.contractAddress,
blockNumber: Number(blockNumber),
logIndex: receiptIndex,
transactionHash: ctx.transaction?.id,
userAddress: address,
takerAddress: address,
tokenAddress: asset_id,
amount: BigInt(amount.toString()),
amountNormalized: BigDecimal(amount.toString()).dividedBy(
BigDecimal(10).pow(collateralConfiguration.decimals)
),
amountUsd: BigDecimal(amount.toString())
.dividedBy(BigDecimal(10).pow(collateralConfiguration.decimals))
.times(collateralPrice),
eventType: 'Supply',
});

await ctx.store.upsert(eventEntity);
})
.onLogUserWithdrawCollateralEvent(async (event, ctx) => {
if (ctx.transaction?.isStatusFailure) {
Expand All @@ -533,6 +562,7 @@ Object.values(appConfig.markets).forEach(({ marketAddress, startBlock }) => {
asset_id: { bits: asset_id },
amount,
},
receiptIndex,
} = event;

const address = (account.Address?.bits ?? account.ContractId?.bits)!;
Expand Down Expand Up @@ -609,6 +639,33 @@ Object.values(appConfig.markets).forEach(({ marketAddress, startBlock }) => {
.times(collateralPrice);

await ctx.store.upsert(collateralPool);

// Collateral withdraw event
const blockNumber = ctx.transaction?.blockNumber!;
const eventId = `${chainId}_${ctx.contractAddress}_${blockNumber}_${receiptIndex}`;

const eventEntity = new EventEntity({
id: eventId,
timestamp: dayjs(ctx.timestamp.getTime()).utc().unix(),
chainId,
poolAddress: ctx.contractAddress,
blockNumber: Number(blockNumber),
logIndex: receiptIndex,
transactionHash: ctx.transaction?.id,
userAddress: address,
takerAddress: address,
tokenAddress: asset_id,
amount: BigInt(amount.toString()),
amountNormalized: BigDecimal(amount.toString()).dividedBy(
BigDecimal(10).pow(collateralConfiguration.decimals)
),
amountUsd: BigDecimal(amount.toString())
.dividedBy(BigDecimal(10).pow(collateralConfiguration.decimals))
.times(collateralPrice),
eventType: 'Withdrawal',
});

await ctx.store.upsert(eventEntity);
})
.onLogAbsorbCollateralEvent(async (event, ctx) => {
if (ctx.transaction?.isStatusFailure) {
Expand Down Expand Up @@ -693,6 +750,186 @@ Object.values(appConfig.markets).forEach(({ marketAddress, startBlock }) => {

await ctx.store.upsert(collateralPosition);
})
.onLogUserSupplyBaseEvent(async (event, ctx) => {
if (ctx.transaction?.isStatusFailure) {
return;
}

const {
data: { account, repay_amount, supply_amount },
receiptIndex,
} = event;

const address = (account.Address?.bits ?? account.ContractId?.bits)!;
const chainId = CHAIN_ID_MAP[ctx.chainId as keyof typeof CHAIN_ID_MAP];

// Market configuration
const marketConfiguration = await ctx.store.get(
MarketConfiguration,
`${chainId}_${ctx.contractAddress}`
);

if (!marketConfiguration) {
throw new Error(
`Market configuration not found for market ${ctx.contractAddress} on chain ${chainId}`
);
}

// Get base asset price
const baseAssetPrice = await getPriceBySymbol(
appConfig.assets[marketConfiguration.baseTokenAddress],
ctx.timestamp
);

if (!baseAssetPrice) {
console.error(
`No price found for ${marketConfiguration.baseTokenAddress} at ${ctx.timestamp}`
);
}

const basePrice = BigDecimal(baseAssetPrice ?? 0);

const blockNumber = ctx.transaction?.blockNumber!;
const eventId = `${chainId}_${ctx.contractAddress}_${blockNumber}_${receiptIndex}`;

// Repay event
let eventEntity = new EventEntity({
id: `${eventId}_repay`,
timestamp: dayjs(ctx.timestamp.getTime()).utc().unix(),
chainId,
poolAddress: ctx.contractAddress,
blockNumber: Number(blockNumber),
logIndex: receiptIndex,
transactionHash: ctx.transaction?.id,
userAddress: address,
takerAddress: address,
tokenAddress: marketConfiguration.baseTokenAddress,
amount: BigInt(repay_amount.toString()),
amountNormalized: BigDecimal(repay_amount.toString()).dividedBy(
BigDecimal(10).pow(marketConfiguration.baseTokenDecimals)
),
amountUsd: BigDecimal(repay_amount.toString())
.dividedBy(BigDecimal(10).pow(marketConfiguration.baseTokenDecimals))
.times(basePrice),
eventType: 'Repay',
});

await ctx.store.upsert(eventEntity);

// Supply event
eventEntity = new EventEntity({
id: `${eventId}_supply`,
timestamp: dayjs(ctx.timestamp.getTime()).utc().unix(),
chainId,
poolAddress: ctx.contractAddress,
blockNumber: Number(blockNumber),
logIndex: receiptIndex,
transactionHash: ctx.transaction?.id,
userAddress: address,
takerAddress: address,
tokenAddress: marketConfiguration.baseTokenAddress,
amount: BigInt(supply_amount.toString()),
amountNormalized: BigDecimal(supply_amount.toString()).dividedBy(
BigDecimal(10).pow(marketConfiguration.baseTokenDecimals)
),
amountUsd: BigDecimal(supply_amount.toString())
.dividedBy(BigDecimal(10).pow(marketConfiguration.baseTokenDecimals))
.times(basePrice),
eventType: 'Deposit',
});

await ctx.store.upsert(eventEntity);
})
.onLogUserWithdrawBaseEvent(async (event, ctx) => {
if (ctx.transaction?.isStatusFailure) {
return;
}

const {
data: { account, borrow_amount, withdraw_amount },
receiptIndex,
} = event;

const address = (account.Address?.bits ?? account.ContractId?.bits)!;
const chainId = CHAIN_ID_MAP[ctx.chainId as keyof typeof CHAIN_ID_MAP];

// Market configuration
const marketConfiguration = await ctx.store.get(
MarketConfiguration,
`${chainId}_${ctx.contractAddress}`
);

if (!marketConfiguration) {
throw new Error(
`Market configuration not found for market ${ctx.contractAddress} on chain ${chainId}`
);
}

// Get base asset price
const baseAssetPrice = await getPriceBySymbol(
appConfig.assets[marketConfiguration.baseTokenAddress],
ctx.timestamp
);

if (!baseAssetPrice) {
console.error(
`No price found for ${marketConfiguration.baseTokenAddress} at ${ctx.timestamp}`
);
}

const basePrice = BigDecimal(baseAssetPrice ?? 0);

const blockNumber = ctx.transaction?.blockNumber!;
const eventId = `${chainId}_${ctx.contractAddress}_${blockNumber}_${receiptIndex}`;

// Withdraw event
let eventEntity = new EventEntity({
id: `${eventId}_withdraw`,
timestamp: dayjs(ctx.timestamp.getTime()).utc().unix(),
chainId,
poolAddress: ctx.contractAddress,
blockNumber: Number(blockNumber),
logIndex: receiptIndex,
transactionHash: ctx.transaction?.id,
userAddress: address,
takerAddress: address,
tokenAddress: marketConfiguration.baseTokenAddress,
amount: BigInt(withdraw_amount.toString()),
amountNormalized: BigDecimal(withdraw_amount.toString()).dividedBy(
BigDecimal(10).pow(marketConfiguration.baseTokenDecimals)
),
amountUsd: BigDecimal(withdraw_amount.toString())
.dividedBy(BigDecimal(10).pow(marketConfiguration.baseTokenDecimals))
.times(basePrice),
eventType: 'Withdraw',
});

await ctx.store.upsert(eventEntity);

// Borrow event
eventEntity = new EventEntity({
id: `${eventId}_borrow`,
timestamp: dayjs(ctx.timestamp.getTime()).utc().unix(),
chainId,
poolAddress: ctx.contractAddress,
blockNumber: Number(blockNumber),
logIndex: receiptIndex,
transactionHash: ctx.transaction?.id,
userAddress: address,
takerAddress: address,
tokenAddress: marketConfiguration.baseTokenAddress,
amount: BigInt(borrow_amount.toString()),
amountNormalized: BigDecimal(borrow_amount.toString()).dividedBy(
BigDecimal(10).pow(marketConfiguration.baseTokenDecimals)
),
amountUsd: BigDecimal(borrow_amount.toString())
.dividedBy(BigDecimal(10).pow(marketConfiguration.baseTokenDecimals))
.times(basePrice),
eventType: 'Borrow',
});

await ctx.store.upsert(eventEntity);
})
.onLogMarketBasicEvent(async (event, ctx) => {
if (ctx.transaction?.isStatusFailure) {
return;
Expand Down
Loading

0 comments on commit 69f5dd9

Please sign in to comment.