Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
feat: index accounts and tranche balances (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
filo87 authored Sep 23, 2022
1 parent d552863 commit 28097bd
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 28 deletions.
30 changes: 20 additions & 10 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ enum InvestorTransactionType {
type InvestorTransaction @entity {
id: ID! # extrinsic hash - epoch number - transaction type
hash: String!
accountId: String #Account @index
account: Account @index #Account @index
pool: Pool! @index
tranche: Tranche! @index
epochNumber: Int! @index
Expand All @@ -221,7 +221,7 @@ type InvestorTransaction @entity {
type OutstandingOrder @entity {
id: ID! # pool id - tranche id - investor address
hash: String!
accountId: String #Account @index
account: Account! @index #Account @index
pool: Pool! @index
tranche: Tranche! @index
epochNumber: Int! @index
Expand All @@ -234,18 +234,28 @@ type OutstandingOrder @entity {
type Account @entity {
id: ID!

publicAddress: String!
anonymousProxies: [AnonymousProxy] @derivedFrom(field: "account")

investorTransactions: [InvestorTransaction] @derivedFrom(field: "account")
borrowerTransactions: [BorrowerTransaction] @derivedFrom(field: "account")

outstandingOrders: [OutstandingOrder] @derivedFrom(field: "account")
trancheBalances: [TrancheBalance] @derivedFrom(field: "account")
}

type AccountBalance @entity {
id: ID! # pool id - tranche id - account id
type TrancheBalance @entity {
id: ID! # address - pool id - tranche id
account: Account @index
pool: Pool! @index
tranche: Tranche! @index

collected: BigInt!
uncollected: BigInt!
ordered: BigInt!
investOrdered: BigInt!
investUncollected: BigInt!
investCollected: BigInt!

redeemOrdered: BigInt!
redeemUncollected: BigInt!
redeemCollected: BigInt!
}

enum LoanStatus {
Expand Down Expand Up @@ -298,7 +308,7 @@ type BorrowerTransaction @entity {
pool: Pool! @index
hash: String!

accountId: String!
account: Account! @index
epochNumber: Int! @index
epoch: Epoch!
loan: Loan! @index
Expand All @@ -311,7 +321,7 @@ type BorrowerTransaction @entity {
type AnonymousProxy @entity {
id: ID!

account: String!
account: Account! @index
createdBy: String!
proxyType: String
}
Expand Down
16 changes: 11 additions & 5 deletions src/mappings/handlers/loansHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import { errorHandler } from '../../helpers/errorHandler'
import { PoolService } from '../services/poolService'
import { LoanService } from '../services/loanService'
import { BorrowerTransactionService } from '../services/borrowerTransactionService'
import { AccountService } from '../services/accountService'

export const handleLoanCreated = errorHandler(_handleLoanCreated)
async function _handleLoanCreated(event: SubstrateEvent<LoanCreatedClosedEvent>) {
const [poolId, loanId] = event.event.data
logger.info(`Loan created event for pool: ${poolId.toString()} loan: ${loanId.toString()}`)
const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toString())

const loan = await LoanService.init(poolId.toString(), loanId.toString(), event.block.timestamp)
await loan.save()

const bt = await BorrowerTransactionService.created({
poolId: poolId.toString(),
loanId: loanId.toString(),
address: event.extrinsic.extrinsic.signer.toString(),
address: account.account.id,
epochNumber: pool.pool.currentEpoch,
hash: event.extrinsic.extrinsic.hash.toString(),
timestamp: event.block.timestamp,
Expand All @@ -35,6 +37,7 @@ async function _handleLoanBorrowed(event: SubstrateEvent<LoanBorrowedRepaidEvent
const [poolId, loanId, amount] = event.event.data
logger.info(`Loan borrowed event for pool: ${poolId.toString()} amount: ${amount.toString()}`)
const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toString())

// Update loan amount
const loan = await LoanService.getById(poolId.toString(), loanId.toString())
Expand All @@ -44,7 +47,7 @@ async function _handleLoanBorrowed(event: SubstrateEvent<LoanBorrowedRepaidEvent
const bt = await BorrowerTransactionService.borrowed({
poolId: poolId.toString(),
loanId: loanId.toString(),
address: event.extrinsic.extrinsic.signer.toString(),
address: account.account.id,
epochNumber: pool.pool.currentEpoch,
hash: event.extrinsic.extrinsic.hash.toString(),
timestamp: event.block.timestamp,
Expand All @@ -62,6 +65,7 @@ async function _handleLoanPriced(event: SubstrateEvent<LoanPricedEvent>) {
const [poolId, loanId, interestRatePerSec, loanType] = event.event.data
logger.info(`Loan priced event for pool: ${poolId.toString()} loan: ${loanId.toString()}`)
const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toString())

const loan = await LoanService.getById(poolId.toString(), loanId.toString())
await loan.activate()
Expand All @@ -72,7 +76,7 @@ async function _handleLoanPriced(event: SubstrateEvent<LoanPricedEvent>) {
const bt = await BorrowerTransactionService.priced({
poolId: poolId.toString(),
loanId: loanId.toString(),
address: event.extrinsic.extrinsic.signer.toString(),
address: account.account.id,
epochNumber: pool.pool.currentEpoch,
hash: event.extrinsic.extrinsic.hash.toString(),
timestamp: event.block.timestamp,
Expand All @@ -85,6 +89,7 @@ async function _handleLoanRepaid(event: SubstrateEvent<LoanBorrowedRepaidEvent>)
const [poolId, loanId, amount] = event.event.data
logger.info(`Loan borrowed event for pool: ${poolId.toString()} amount: ${amount.toString()}`)
const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toString())

const loan = await LoanService.getById(poolId.toString(), loanId.toString())
await loan.repay(amount.toBigInt())
Expand All @@ -93,7 +98,7 @@ async function _handleLoanRepaid(event: SubstrateEvent<LoanBorrowedRepaidEvent>)
const bt = await BorrowerTransactionService.repaid({
poolId: poolId.toString(),
loanId: loanId.toString(),
address: event.extrinsic.extrinsic.signer.toString(),
address: account.account.id,
epochNumber: pool.pool.currentEpoch,
hash: event.extrinsic.extrinsic.hash.toString(),
timestamp: event.block.timestamp,
Expand All @@ -117,6 +122,7 @@ async function _handleLoanClosed(event: SubstrateEvent<LoanCreatedClosedEvent>)
const [poolId, loanId] = event.event.data
logger.info(`Loan closed event for pool: ${poolId.toString()} loanId: ${loanId.toString()}`)
const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toString())

const loan = await LoanService.getById(poolId.toString(), loanId.toString())
await loan.close()
Expand All @@ -125,7 +131,7 @@ async function _handleLoanClosed(event: SubstrateEvent<LoanCreatedClosedEvent>)
const bt = await BorrowerTransactionService.repaid({
poolId: poolId.toString(),
loanId: loanId.toString(),
address: event.extrinsic.extrinsic.signer.toString(),
address: account.account.id,
epochNumber: pool.pool.currentEpoch,
hash: event.extrinsic.extrinsic.hash.toString(),
timestamp: event.block.timestamp,
Expand Down
16 changes: 10 additions & 6 deletions src/mappings/handlers/ormlTokensHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SubstrateEvent } from '@subql/types'
import { errorHandler } from '../../helpers/errorHandler'
import { TokensTransferEvent } from '../../helpers/types'
import { AccountService } from '../services/accountService'
import { CurrencyService } from '../services/currencyService'
import { InvestorTransactionService } from '../services/investorTransactionService'
import { PoolService } from '../services/poolService'
Expand All @@ -12,12 +13,11 @@ async function _handleTokenTransfer(event: SubstrateEvent<TokensTransferEvent>):

if (currency.isTranche) {
const [poolId, trancheId] = currency.asTranche

const fromId = String.fromCharCode(...from.toU8a())
const toId = String.fromCharCode(...to.toU8a())
const fromAddress = String.fromCharCode(...from.toU8a())
const toAddress = String.fromCharCode(...to.toU8a())

// FILTER OUT ALL TRANSACTIONS CONTAINING A POOL ADDRESS
if (fromId.startsWith('pool') || toId.startsWith('pool')) return
if (fromAddress.startsWith('pool') || toAddress.startsWith('pool')) return

logger.info(
`Token transfer tor tranche: ${poolId.toString()}-${trancheId.toString()}.
Expand All @@ -28,6 +28,10 @@ async function _handleTokenTransfer(event: SubstrateEvent<TokensTransferEvent>):
// Get corresponding pool
const pool = await PoolService.getById(poolId.toString())
const tranche = await TrancheService.getById(poolId.toString(), trancheId.toHex())
const [fromAccount, toAccount] = await Promise.all([
AccountService.getOrInit(fromAddress),
AccountService.getOrInit(toAddress),
])

// Update tranche price
await tranche.updatePriceFromRpc()
Expand All @@ -46,11 +50,11 @@ async function _handleTokenTransfer(event: SubstrateEvent<TokensTransferEvent>):

// CREATE 2 TRANSFERS FOR FROM AND TO ADDRESS
// with from create TRANSFER_OUT
const txOut = InvestorTransactionService.transferOut({ ...orderData, address: from.toString() })
const txOut = InvestorTransactionService.transferOut({ ...orderData, address: fromAccount.account.id })
await txOut.save()

// with to create TRANSFER_IN
const txIn = InvestorTransactionService.transferIn({ ...orderData, address: to.toString() })
const txIn = InvestorTransactionService.transferIn({ ...orderData, address: toAccount.account.id })
await txIn.save()
}
}
42 changes: 36 additions & 6 deletions src/mappings/handlers/poolsHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { EpochEvent, OrderEvent, OrdersCollectedEvent, PoolEvent } from '../../h
import { OutstandingOrderService } from '../services/outstandingOrderService'
import { InvestorTransactionData, InvestorTransactionService } from '../services/investorTransactionService'
import { CurrencyService } from '../services/currencyService'
import { AccountService } from '../services/accountService'
import { TrancheBalanceService } from '../services/trancheBalanceService'

export const handlePoolCreated = errorHandler(_handlePoolCreated)
async function _handlePoolCreated(event: SubstrateEvent<PoolEvent>): Promise<void> {
Expand Down Expand Up @@ -139,6 +141,12 @@ async function _handleEpochExecuted(event: SubstrateEvent<EpochEvent>): Promise<
timestamp: event.block.timestamp,
}

const trancheBalance = await TrancheBalanceService.getOrInit(
orderData.address,
orderData.poolId,
orderData.trancheId
)

if (oo.outstandingOrder.invest > BigInt(0) && epochState.investFulfillment > BigInt(0)) {
const it = InvestorTransactionService.executeInvestOrder({
...orderData,
Expand All @@ -147,6 +155,7 @@ async function _handleEpochExecuted(event: SubstrateEvent<EpochEvent>): Promise<
})
await it.save()
await oo.updateUnfulfilledInvest(it.investorTransaction.currencyAmount)
await trancheBalance.investExecuted(it.investorTransaction.currencyAmount, it.investorTransaction.tokenAmount)
}

if (oo.outstandingOrder.redeem > BigInt(0) && epochState.redeemFulfillment > BigInt(0)) {
Expand All @@ -157,8 +166,11 @@ async function _handleEpochExecuted(event: SubstrateEvent<EpochEvent>): Promise<
})
await it.save()
await oo.updateUnfulfilledRedeem(it.investorTransaction.tokenAmount)
await trancheBalance.redeemExecuted(it.investorTransaction.tokenAmount, it.investorTransaction.currencyAmount)
}

await trancheBalance.save()

// Remove outstandingOrder if completely fulfilled
if (oo.outstandingOrder.invest > BigInt(0) || oo.outstandingOrder.redeem > BigInt(0)) {
await oo.save()
Expand All @@ -181,8 +193,9 @@ async function _handleInvestOrderUpdated(event: SubstrateEvent<OrderEvent>): Pro
`New: ${newAmount.toString()} Old: ${oldAmount.toString()} at ` +
`block ${event.block.block.header.number.toString()}`
)
// Get corresponding pool

const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(address.toString())
const tranche = await TrancheService.getById(poolId.toString(), trancheId.toHex())

// Update tranche price
Expand All @@ -192,7 +205,7 @@ async function _handleInvestOrderUpdated(event: SubstrateEvent<OrderEvent>): Pro
poolId: poolId.toString(),
trancheId: trancheId.toString(),
epochNumber: pool.pool.currentEpoch,
address: address.toString(),
address: account.account.id,
hash: event.extrinsic.extrinsic.hash.toString(),
amount: newAmount.toBigInt(),
digits: (await CurrencyService.getById(pool.pool.currencyId)).currency.decimals,
Expand Down Expand Up @@ -223,6 +236,11 @@ async function _handleInvestOrderUpdated(event: SubstrateEvent<OrderEvent>): Pro
const epoch = await EpochService.getById(poolId.toString(), pool.pool.currentEpoch)
await epoch.updateOutstandingInvestOrders(trancheId.toHex(), newAmount.toBigInt(), oldAmount.toBigInt())
await epoch.save()

// Update trancheBalance
const trancheBalance = await TrancheBalanceService.getOrInit(orderData.address, orderData.poolId, orderData.trancheId)
await trancheBalance.investOrdered(orderData.amount)
await trancheBalance.save()
}

export const handleRedeemOrderUpdated = errorHandler(_handleRedeemOrderUpdated)
Expand All @@ -235,6 +253,7 @@ async function _handleRedeemOrderUpdated(event: SubstrateEvent<OrderEvent>): Pro
)
// Get corresponding pool
const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(address.toString())
const tranche = await TrancheService.getById(poolId.toString(), trancheId.toHex())
const digits = (await CurrencyService.getById(pool.pool.currencyId)).currency.decimals

Expand All @@ -244,7 +263,7 @@ async function _handleRedeemOrderUpdated(event: SubstrateEvent<OrderEvent>): Pro
poolId: poolId.toString(),
trancheId: trancheId.toString(),
epochNumber: pool.pool.currentEpoch,
address: address.toString(),
address: account.account.id,
hash: event.extrinsic.extrinsic.hash.toString(),
amount: newAmount.toBigInt(),
digits: digits,
Expand Down Expand Up @@ -281,18 +300,24 @@ async function _handleRedeemOrderUpdated(event: SubstrateEvent<OrderEvent>): Pro
digits
)
await epoch.save()

// Update trancheBalance
const trancheBalance = await TrancheBalanceService.getOrInit(orderData.address, orderData.poolId, orderData.trancheId)
await trancheBalance.redeemOrdered(orderData.amount)
await trancheBalance.save()
}

export const handleOrdersCollected = errorHandler(_handleOrdersCollected)
async function _handleOrdersCollected(event: SubstrateEvent<OrdersCollectedEvent>): Promise<void> {
const [poolId, trancheId, endEpochId, account, outstandingCollections] = event.event.data
const [poolId, trancheId, endEpochId, address, outstandingCollections] = event.event.data
logger.info(
`Orders collected for tranche ${poolId.toString()}-${trancheId.toString()}. ` +
`Address: ${account.toString()} endEpoch: ${endEpochId.toNumber()} at ` +
`Address: ${address.toString()} endEpoch: ${endEpochId.toNumber()} at ` +
`block ${event.block.block.header.number.toString()} hash:${event.extrinsic.extrinsic.hash.toString()}`
)

const pool = await PoolService.getById(poolId.toString())
const account = await AccountService.getOrInit(address.toString())
const tranche = await TrancheService.getById(poolId.toString(), trancheId.toHex())

// Update tranche price
Expand All @@ -305,20 +330,25 @@ async function _handleOrdersCollected(event: SubstrateEvent<OrdersCollectedEvent
poolId: poolId.toString(),
trancheId: trancheId.toString(),
epochNumber: endEpochId.toNumber(),
address: account.toString(),
address: account.account.id,
hash: event.extrinsic.extrinsic.hash.toString(),
timestamp: event.block.timestamp,
digits: (await CurrencyService.getById(pool.pool.currencyId)).currency.decimals,
price: tranche.trancheState.price,
}

const trancheBalance = await TrancheBalanceService.getOrInit(orderData.address, orderData.poolId, orderData.trancheId)

if (payoutTokenAmount.toBigInt() > 0) {
const it = InvestorTransactionService.collectInvestOrder({ ...orderData, amount: payoutTokenAmount.toBigInt() })
await it.save()
await trancheBalance.investCollected(payoutTokenAmount.toBigInt())
}

if (payoutCurrencyAmount.toBigInt() > 0) {
const it = InvestorTransactionService.collectRedeemOrder({ ...orderData, amount: payoutCurrencyAmount.toBigInt() })
await it.save()
await trancheBalance.redeemCollected(payoutCurrencyAmount.toBigInt())
}
await trancheBalance.save()
}
2 changes: 1 addition & 1 deletion src/mappings/handlers/proxyHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function handleProxyAnonymousCreated(event: SubstrateEvent): Promis
const [account, createdBy, proxyType] = event.event.data

const anonymousProxy = new AnonymousProxy(`${account.toString()}`)
anonymousProxy.account = account.toString()
anonymousProxy.accountId = account.toString()
anonymousProxy.createdBy = createdBy.toString()
anonymousProxy.proxyType = proxyType.toString()
await anonymousProxy.save()
Expand Down
Loading

0 comments on commit 28097bd

Please sign in to comment.