Skip to content

Commit 8cb7880

Browse files
committed
feat: add tracked-underlying-backing endpoint
1 parent 8a3c0b3 commit 8cb7880

File tree

2 files changed

+55
-18
lines changed

2 files changed

+55
-18
lines changed

packages/fasset-indexer-api/src/analytics/dashboard.ts

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
const add = (x: bigint, y: bigint) => x + y
2020
const sub = (x: bigint, y: bigint) => x - y
2121
const rat = (x: bigint, y: bigint) => y == BigInt(0) ? 0 : Number(MAX_BIPS * x / y) / Number(MAX_BIPS)
22+
const div = (x: bigint, y: bigint) => y == BigInt(0) ? BigInt(0) : x / y
2223

2324
/**
2425
* DashboardAnalytics provides a set of analytics functions for the FAsset UI's dashboard.
@@ -45,10 +46,14 @@ export class DashboardAnalytics extends SharedAnalytics {
4546
const result = await qb.count().where({
4647
name: {
4748
$in: [
49+
EVENTS.ASSET_MANAGER.REDEMPTION_REQUESTED,
50+
EVENTS.ASSET_MANAGER.COLLATERAL_RESERVED,
51+
EVENTS.COLLATERAL_POOL.CP_ENTERED,
52+
EVENTS.COLLATERAL_POOL.CP_EXITED,
53+
EVENTS.COLLATERAL_POOL.CP_FEES_WITHDRAWN,
54+
EVENTS.COLLATERAL_POOL.CP_SELF_CLOSE_EXITED,
4855
EVENTS.COLLATERAL_POOL.EXIT,
4956
EVENTS.COLLATERAL_POOL.ENTER,
50-
EVENTS.ASSET_MANAGER.REDEMPTION_REQUESTED,
51-
EVENTS.ASSET_MANAGER.COLLATERAL_RESERVED
5257
]
5358
}
5459
}).execute()
@@ -84,15 +89,22 @@ export class DashboardAnalytics extends SharedAnalytics {
8489
}
8590

8691
async totalRedeemedLots(): Promise<FAssetAmountResult> {
87-
const ret = {} as FAssetAmountResult
92+
const redeemed = await this.totalRedeemed()
93+
const lotSizes = await this.lotSizeUBA()
94+
const valueResult = this.transformFAssetValueResults(redeemed, lotSizes, div)
95+
return this.convertFAssetValueResultToFAssetAmountResult(valueResult)
96+
}
97+
98+
async lotSizeUBA(): Promise<FAssetValueResult> {
8899
const em = this.orm.em.fork()
89-
const tr = await this.totalRedeemed()
90-
for (const [fasset, { value }] of Object.entries(tr)) {
91-
const fassetType = FAssetType[fasset]
92-
const settings = await em.findOneOrFail(Entities.AssetManagerSettings, { fasset: fassetType })
93-
ret[fasset] = { amount: Number(value / settings.lotSizeAmg) }
94-
}
95-
return ret
100+
const settings = await em.createQueryBuilder(Entities.AssetManagerSettings, 'ams')
101+
.select(['fasset', 'lotSizeAmg'])
102+
.execute() as { fasset: FAssetType, lotSizeAmg: string }[]
103+
return this.convertOrmResultToFAssetValueResult(settings, 'lotSizeAmg')
104+
}
105+
106+
async trackedUnderlyingBacking(): Promise<FAssetValueResult> {
107+
return this.trackedAgentBackingAt(this.orm.em.fork(), unixnow())
96108
}
97109

98110
async redemptionDefault(id: number, fasset: FAssetType): Promise<Entities.RedemptionDefault | null> {
@@ -424,7 +436,8 @@ export class DashboardAnalytics extends SharedAnalytics {
424436
return this.transformFAssetValueResults(
425437
this.convertOrmResultToFAssetValueResult(redeemed, 'value'),
426438
this.convertOrmResultToFAssetValueResult(transferred, 'value'),
427-
sub)
439+
sub
440+
)
428441
}
429442

430443
protected async coreVaultTransferredDuring(em: EntityManager, from: number, to: number): Promise<FAssetValueResult> {
@@ -483,13 +496,13 @@ export class DashboardAnalytics extends SharedAnalytics {
483496
return this.transformFAssetValueResults(inflow, outflow, sub)
484497
}
485498

486-
async trackedAgentBackingDuring(em: EntityManager, from: number, to: number): Promise<FAssetValueResult> {
499+
protected async trackedAgentBackingAt(em: EntityManager, timestamp: number): Promise<FAssetValueResult> {
487500
const knex = em.getKnex()
488501
const subquery = em.createQueryBuilder(Entities.UnderlyingBalanceChanged, 'ubc')
489502
.select(['ubc.fasset', 'ubc.agentVault', raw('max(ubc.balance_uba) as agent_balance')])
490503
.join('ubc.evmLog', 'el')
491504
.join('el.block', 'bl')
492-
.where({ 'bl.timestamp': { $gte: from, $lt: to } })
505+
.where({ 'bl.timestamp': { $lt: timestamp } })
493506
.groupBy(['ubc.fasset', 'ubc.agentVault'])
494507
.getKnexQuery()
495508
const mainquery = knex
@@ -506,10 +519,6 @@ export class DashboardAnalytics extends SharedAnalytics {
506519
return this.coreVaultInflowDuring(em, 0, timestamp)
507520
}
508521

509-
protected async trackedAgentBackingAt(em: EntityManager, timestamp: number): Promise<FAssetValueResult> {
510-
return this.trackedAgentBackingDuring(em, 0, timestamp)
511-
}
512-
513522
protected async coreVaultOutflowAt(em: EntityManager, timestamp: number): Promise<FAssetValueResult> {
514523
return this.coreVaultOutflowDuring(em, 0, timestamp)
515524
}
@@ -697,6 +706,28 @@ export class DashboardAnalytics extends SharedAnalytics {
697706
return res
698707
}
699708

709+
protected transformFAssetAmountResults(
710+
res1: FAssetAmountResult,
711+
res2: FAssetAmountResult,
712+
transformer: (x: number, y: number) => number
713+
): FAssetAmountResult {
714+
const res = {} as FAssetAmountResult
715+
for (let fasset of this.supportedFAssets) {
716+
const x = res1[fasset]?.amount ?? 0
717+
const y = res2[fasset]?.amount ?? 0
718+
res[fasset] = { amount: transformer(x, y) }
719+
}
720+
return res
721+
}
722+
723+
protected convertFAssetValueResultToFAssetAmountResult(
724+
result: FAssetValueResult
725+
): FAssetAmountResult {
726+
return Object.fromEntries(Object.entries(result).map(
727+
([fasset, { value }]) => [ fasset, { amount: Number(value) }]
728+
)) as FAssetAmountResult
729+
}
730+
700731
private convertOrmResultToFAssetValueResult<K extends string>(
701732
result: ({ fasset: number } & { [key in K]: string | bigint })[], key: K
702733
): FAssetValueResult {

packages/fasset-indexer-api/src/controllers/dashboard.controller.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ export class DashboardController {
6464
return apiResponse(this.service.redemptionDefault(id, FAssetType[fasset]), 200)
6565
}
6666

67+
@Get('/tracked-underlying-backing?')
68+
@ApiOperation({ summary: 'Total underlying assets tracked by the contracts' })
69+
getTrackedUnderlyingBacking(): Promise<ApiResponse<FAssetValueResult>>{
70+
return apiResponse(this.service.trackedUnderlyingBacking(), 200)
71+
}
72+
6773
//////////////////////////////////////////////////////////////////////
6874
// agents
6975

@@ -239,7 +245,7 @@ export class DashboardController {
239245
@Get('/timespan/tracked-underlying-backing-ratio?')
240246
@ApiOperation({ summary: 'Timespan of the ratio between issued FAssets and backed Assets' })
241247
@ApiQuery({ name: "timestamps", type: Number, isArray: true })
242-
getUTrackedUnderlyingBackingRatioTimespan(
248+
getTrackedUnderlyingBackingRatioTimespan(
243249
@Query('timestamps') timestamps: string | string[]
244250
): Promise<ApiResponse<FAssetTimespan<number>>>{
245251
const ts = this.parseTimestamps(timestamps)

0 commit comments

Comments
 (0)