Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: link asset transactions and pool fee transactions to epoch entity #203

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -205,24 +205,24 @@ type TrancheSnapshot @entity {
type Epoch @entity {
id: ID! #poolId-epochIndex
pool: Pool!

index: Int!

openedAt: Date!
openedAt: Date
closedAt: Date
executedAt: Date

# Aggregated data during this epoch
sumBorrowedAmount: BigInt!
sumRepaidAmount: BigInt!
sumInvestedAmount: BigInt!
sumRedeemedAmount: BigInt!
sumBorrowedAmount: BigInt
sumRepaidAmount: BigInt
sumInvestedAmount: BigInt
sumRedeemedAmount: BigInt

sumPoolFeesPaidAmount: BigInt

epochStates: [EpochState] @derivedFrom(field: "epoch")

investorTransactions: [InvestorTransaction] @derivedFrom(field: "epoch")
assetTransactions: [AssetTransaction] @derivedFrom(field: "epoch")
poolFeeTransactions: [PoolFeeTransaction] @derivedFrom(field: "epoch")
}

type EpochState @entity {
Expand All @@ -232,9 +232,9 @@ type EpochState @entity {

tokenPrice: BigInt

sumOutstandingInvestOrders: BigInt!
sumOutstandingRedeemOrders: BigInt!
sumOutstandingRedeemOrdersCurrency: BigInt!
sumOutstandingInvestOrders: BigInt
sumOutstandingRedeemOrders: BigInt
sumOutstandingRedeemOrdersCurrency: BigInt
sumFulfilledInvestOrders: BigInt
sumFulfilledRedeemOrders: BigInt
sumFulfilledRedeemOrdersCurrency: BigInt
Expand Down Expand Up @@ -615,6 +615,7 @@ type PoolFeeTransaction @entity {
timestamp: Date!
blockNumber: Int!
epochNumber: Int!
epoch: Epoch!

amount: BigInt

Expand Down
8 changes: 7 additions & 1 deletion src/mappings/handlers/blockHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
TrancheSnapshot,
} from '../../types/models'
import { AssetPositionService } from '../services/assetPositionService'
import { EpochService } from '../services/epochService'

const timekeeper = TimekeeperService.init()

Expand All @@ -40,6 +41,7 @@ async function _handleBlock(block: SubstrateBlock): Promise<void> {
// Update Pool States
const pools = await PoolService.getCfgActivePools()
for (const pool of pools) {
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
await pool.updateState()
await pool.resetDebtOverdue()

Expand Down Expand Up @@ -92,6 +94,10 @@ async function _handleBlock(block: SubstrateBlock): Promise<void> {
for (const accruals of accruedFees) {
const [feeId, pending, disbursement] = accruals
const poolFee = await PoolFeeService.getById(pool.id, feeId)
if (!poolFee) {
logger.error(`Unable to retrieve PoolFee ${pool.id}-${feeId}, skipping accruals!`)
continue
}
await poolFee.updateAccruals(pending, disbursement)
await poolFee.save()

Expand All @@ -102,7 +108,7 @@ async function _handleBlock(block: SubstrateBlock): Promise<void> {
feeId,
blockNumber,
amount: poolFee.sumAccruedAmountByPeriod,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: block.hash.toHex(),
timestamp: block.timestamp,
})
Expand Down
4 changes: 2 additions & 2 deletions src/mappings/handlers/ethHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async function _handleEthBlock(block: EthereumBlock): Promise<void> {
const poolUpdateCalls: PoolMulticall[] = []
for (const tinlakePool of tinlakePools) {
if (block.number >= tinlakePool.startBlock) {
const pool = await PoolService.getOrSeed(tinlakePool.id, false, blockchain.id)
const pool = await PoolService.getOrSeed(tinlakePool.id, false, false, blockchain.id)

// initialize new pool
if (!pool.isActive) {
Expand Down Expand Up @@ -89,7 +89,7 @@ async function _handleEthBlock(block: EthereumBlock): Promise<void> {
const tinlakePool = tinlakePools.find((p) => p.id === callResult.id)
const latestNavFeed = getLatestContract(tinlakePool?.navFeed, blockNumber)
const latestReserve = getLatestContract(tinlakePool?.reserve, blockNumber)
const pool = await PoolService.getOrSeed(tinlakePool?.id, false, blockchain.id)
const pool = await PoolService.getOrSeed(tinlakePool?.id, false, false, blockchain.id)

// Update pool
if (callResult.type === 'currentNAV' && latestNavFeed) {
Expand Down
22 changes: 14 additions & 8 deletions src/mappings/handlers/poolFeesHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ async function _handleFeeProposed(event: SubstrateEvent<PoolFeesProposedEvent>):
`Fee with id ${feeId.toString(10)} proposed for pool ${poolId.toString(10)} ` +
`on block ${event.block.block.header.number.toNumber()}`
)
const pool = await PoolService.getOrSeed(poolId.toString(10))
const pool = await PoolService.getOrSeed(poolId.toString(10), true, true)
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
const poolFeeData: PoolFeeData = {
poolId: pool.id,
feeId: feeId.toString(10),
blockNumber: event.block.block.header.number.toNumber(),
timestamp: event.block.timestamp,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: event.hash.toString(),
}
const type = fee.feeType.type
Expand All @@ -51,13 +52,14 @@ async function _handleFeeAdded(event: SubstrateEvent<PoolFeesAddedEvent>): Promi
`Fee with id ${feeId.toString(10)} added for pool ${poolId.toString(10)} ` +
`on block ${event.block.block.header.number.toNumber()}`
)
const pool = await PoolService.getOrSeed(poolId.toString(10))
const pool = await PoolService.getOrSeed(poolId.toString(10), true, true)
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
const poolFeeData: PoolFeeData = {
poolId: pool.id,
feeId: feeId.toString(10),
blockNumber: event.block.block.header.number.toNumber(),
timestamp: event.block.timestamp,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: event.hash.toString(),
}
const type = fee.feeType.type
Expand All @@ -84,12 +86,13 @@ async function _handleFeeRemoved(event: SubstrateEvent<PoolFeesRemovedEvent>): P
)
const pool = await PoolService.getById(poolId.toString(10))
if (!pool) throw missingPool
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
const poolFeeData: PoolFeeData = {
poolId: pool.id,
feeId: feeId.toString(10),
blockNumber: event.block.block.header.number.toNumber(),
timestamp: event.block.timestamp,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: event.hash.toString(),
}

Expand All @@ -109,12 +112,13 @@ async function _handleFeeCharged(event: SubstrateEvent<PoolFeesChargedEvent>): P
)
const pool = await PoolService.getById(poolId.toString(10))
if (!pool) throw missingPool
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
const poolFeeData = {
poolId: pool.id,
feeId: feeId.toString(10),
blockNumber: event.block.block.header.number.toNumber(),
timestamp: event.block.timestamp,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: event.hash.toString(),
amount: amount.toBigInt(),
pending: pending.toBigInt(),
Expand All @@ -141,12 +145,13 @@ async function _handleFeeUncharged(event: SubstrateEvent<PoolFeesUnchargedEvent>
)
const pool = await PoolService.getById(poolId.toString(10))
if (!pool) throw missingPool
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
const poolFeeData = {
poolId: pool.id,
feeId: feeId.toString(10),
blockNumber: event.block.block.header.number.toNumber(),
timestamp: event.block.timestamp,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: event.hash.toString(),
amount: amount.toBigInt(),
pending: pending.toBigInt(),
Expand All @@ -173,12 +178,13 @@ async function _handleFeePaid(event: SubstrateEvent<PoolFeesPaidEvent>): Promise
)
const pool = await PoolService.getById(poolId.toString(10))
if (!pool) throw missingPool
const currentEpoch = await EpochService.getById(pool.id, pool.currentEpoch)
const poolFeeData = {
poolId: pool.id,
feeId: feeId.toString(10),
blockNumber: event.block.block.header.number.toNumber(),
timestamp: event.block.timestamp,
epochNumber: pool.currentEpoch,
epochId: currentEpoch.id,
hash: event.hash.toString(),
amount: amount.toBigInt(),
}
Expand Down
53 changes: 25 additions & 28 deletions src/mappings/services/epochService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,36 @@ import { Epoch, EpochState } from '../../types'
export class EpochService extends Epoch {
private states: EpochState[]

constructor(
id: string,
poolId: string,
index: number,
openedAt: Date,
sumBorrowedAmount: bigint,
sumRepaidAmount: bigint,
sumInvestedAmount: bigint,
sumRedeemedAmount: bigint
) {
super(id, poolId, index, openedAt, sumBorrowedAmount, sumRepaidAmount, sumInvestedAmount, sumRedeemedAmount)
constructor(id: string, poolId: string, index: number) {
super(id, poolId, index)
this.states = []
}

static async init(poolId: string, epochNr: number, trancheIds: string[], timestamp: Date) {
logger.info(`Initialising epoch ${epochNr} for pool ${poolId}`)
const epoch = new this(
`${poolId}-${epochNr.toString(10)}`,
poolId,
epochNr,
timestamp,
BigInt(0),
BigInt(0),
BigInt(0),
BigInt(0)
)
static seed(poolId: string, index = 0) {
logger.info(`Seeding epoch ${index} for pool ${poolId}`)
return new this(`${poolId}-${index}`, poolId, index)
}

static init(poolId: string, epochNr: number, trancheIds: string[], timestamp: Date) {
logger.info(`Initialising epoch ${epochNr} for pool ${poolId}`)
const epoch = new this(`${poolId}-${epochNr.toString(10)}`, poolId, epochNr)
epoch.openedAt = timestamp
epoch.sumBorrowedAmount = BigInt(0)
epoch.sumRepaidAmount = BigInt(0)
epoch.sumInvestedAmount = BigInt(0)
epoch.sumRedeemedAmount = BigInt(0)
epoch.sumPoolFeesPaidAmount = BigInt(0)

epoch.states = trancheIds.map(
(trancheId) =>
new EpochState(`${poolId}-${epochNr}-${trancheId}`, epoch.id, trancheId, BigInt(0), BigInt(0), BigInt(0))
)
epoch.states = trancheIds.map((trancheId) => {
const epochState = new EpochState(`${poolId}-${epochNr}-${trancheId}`, epoch.id, trancheId)
epochState.sumOutstandingInvestOrders = BigInt(0)
epochState.sumOutstandingRedeemOrders = BigInt(0)
epochState.sumOutstandingRedeemOrdersCurrency = BigInt(0)
epochState.sumFulfilledInvestOrders = BigInt(0)
epochState.sumFulfilledRedeemOrders = BigInt(0)
epochState.sumFulfilledRedeemOrdersCurrency = BigInt(0)
return epochState
})

return epoch
}
Expand All @@ -59,7 +56,7 @@ export class EpochService extends Epoch {
}

public getStates() {
return [ ...this.states ]
return [...this.states]
}

public closeEpoch(timestamp: Date) {
Expand Down
2 changes: 1 addition & 1 deletion src/mappings/services/poolFeeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface PoolFeeData {
feeId: string
blockNumber: number
timestamp: Date
epochNumber: number
epochId: string
hash: string
amount?: bigint
pending?: bigint
Expand Down
9 changes: 5 additions & 4 deletions src/mappings/services/poolFeeTransactionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import { PoolFeeData } from './poolFeeService'

export class PoolFeeTransactionService extends PoolFeeTransaction {
static init(data: PoolFeeData, type: keyof typeof PoolFeeTransactionType) {
const { hash, epochNumber, poolId, feeId, timestamp, blockNumber } = data
const { hash, epochId, poolId, feeId, timestamp, blockNumber } = data
const _type = PoolFeeTransactionType[type]
const _epochNumber = epochNumber ?? 0
const epochNumber = parseInt(epochId.split('-')[1],10)
return new this(
`${hash}-${_epochNumber}-${type}`,
`${epochId}-${feeId}-${type}-${hash}`,
`${poolId}-${feeId}`,
_type,
timestamp,
blockNumber,
_epochNumber
epochNumber,
epochId
)
}

Expand Down
18 changes: 16 additions & 2 deletions src/mappings/services/poolService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,32 @@ import { paginatedGetter } from '../../helpers/paginatedGetter'
import { ExtendedCall, NavDetails, PoolDetails, PoolFeesList, PoolMetadata, TrancheDetails } from '../../helpers/types'
import { Pool } from '../../types'
import { cid, readIpfs } from '../../helpers/ipfsFetch'
import { EpochService } from './epochService'

export class PoolService extends Pool {
static seed(poolId: string, blockchain = '0') {
logger.info(`Seeding pool ${poolId}`)
return new this(`${poolId}`, blockchain, 'ALL', false)
}

static async getOrSeed(poolId: string, saveSeed = true, blockchain = '0') {
static async getOrSeed(
poolId: string,
saveSeed = true,
seedEpoch = false,
blockchain = '0',
epochService = EpochService
) {
let pool = await this.getById(poolId)
if (!pool) {
pool = this.seed(poolId, blockchain)
if (saveSeed) await pool.save()
if (saveSeed) {
if(seedEpoch) pool.currentEpoch = 1
await pool.save()
if (seedEpoch) {
const epoch = epochService.seed(poolId, 1)
await epoch.save()
}
}
}
return pool
}
Expand Down
Loading