Skip to content

Commit

Permalink
Merge pull request #83 from 00labs/subgraph-poolstats
Browse files Browse the repository at this point in the history
Load in pool stats from Subgraph instead of calculating manually
  • Loading branch information
mliu authored Nov 15, 2023
2 parents 347bf1c + ff56ca0 commit a6fe4a6
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 9 deletions.
14 changes: 14 additions & 0 deletions packages/huma-sdk/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ in Huma's pools that can be drawn down by the borrower.</p>
* [.getCreditEventsForUser(userAddress, chainId, poolName, poolType, event)](#SubgraphService.getCreditEventsForUser) ⇒ <code>Promise.&lt;Array.&lt;CreditEventPayload&gt;&gt;</code>
* [.getLastFactorizedAmountFromPool(userAddress, chainId, poolName, poolType)](#SubgraphService.getLastFactorizedAmountFromPool) ⇒ <code>Promise.&lt;number&gt;</code>
* [.getRWReceivableInfo(userAddress, chainId, poolName, poolType, pagination)](#SubgraphService.getRWReceivableInfo) ⇒ <code>Promise.&lt;RealWorldReceivableInfoBase&gt;</code>
* [.getPoolStats(chainId, pool)](#SubgraphService.getPoolStats) ⇒ <code>Promise.&lt;{PoolStats}&gt;</code>

<a name="SubgraphService.getSubgraphUrlForChainId"></a>

Expand Down Expand Up @@ -534,6 +535,19 @@ in Huma's pools that can be drawn down by the borrower.</p>
| poolType | <code>POOL\_TYPE</code> | <p>The type of the pool.</p> |
| pagination | [<code>Pagination</code>](#Pagination) | <p>The pagination option.</p> |

<a name="SubgraphService.getPoolStats"></a>

### SubgraphService.getPoolStats(chainId, pool) ⇒ <code>Promise.&lt;{PoolStats}&gt;</code>
<p>Returns the pool's stats.</p>

**Kind**: static method of [<code>SubgraphService</code>](#SubgraphService)
**Returns**: <code>Promise.&lt;{PoolStats}&gt;</code> - <p>The pool's stats info.</p>

| Param | Type | Description |
| --- | --- | --- |
| chainId | <code>number</code> | <p>The ID of the chain.</p> |
| pool | <code>string</code> | <p>The address of the pool.</p> |

<a name="defaultWrapper"></a>

## defaultWrapper()
Expand Down
51 changes: 51 additions & 0 deletions packages/huma-sdk/src/services/SubgraphService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,56 @@ function getRWReceivableInfo(
})
}

type PoolStats = {
id: string
totalPoolAssets: number
amountCreditOriginated: number
amountCreditRepaid: number
amountCreditDefaulted: number
}

/**
* Returns the pool's stats.
*
* @memberof SubgraphService
* @param {number} chainId - The ID of the chain.
* @param {string} pool - The address of the pool.
* @returns {Promise<{PoolStats}>} The pool's stats info.
*/
function getPoolStats(
chainId: number,
pool: string,
): Promise<PoolStats | undefined> {
const url = PoolSubgraphMap[chainId]?.subgraph
if (!url) {
return Promise.resolve(undefined)
}

const PoolStatsQuery = `
query {
poolStat(id:"${pool?.toLowerCase()}") {
id
amountCreditOriginated
amountCreditRepaid
amountCreditDefaulted
totalPoolAssets
}
}`

return requestPost<{
errors?: unknown
data: { poolStat: PoolStats }
}>(url, JSON.stringify({ query: PoolStatsQuery }), {
withCredentials: false,
}).then((res) => {
if (res.errors) {
console.error(res.errors)
return undefined
}
return res.data.poolStat
})
}

/**
* An object that contains functions to interact with Huma's Subgraph storage.
* @namespace SubgraphService
Expand All @@ -205,4 +255,5 @@ export const SubgraphService = {
getCreditEventsForUser,
getLastFactorizedAmountFromPool,
getRWReceivableInfo,
getPoolStats,
}
44 changes: 44 additions & 0 deletions packages/huma-sdk/tests/services/SubgraphService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,47 @@ describe('getRWReceivableInfo', () => {
expect(result).toStrictEqual(rwreceivables)
})
})

describe('getPoolStats', () => {
beforeEach(() => {
jest.resetAllMocks()
})

it('should return undefined if no subgraph url is found', async () => {
const chainId = 12 // ChainId without receivables Subgraph url
const pool = '0xc866A11cf6A3D178624Ff46B8A49202206A7c51B'

const result = await SubgraphService.getPoolStats(chainId, pool)
expect(result).toStrictEqual(undefined)
})

it('should return undefined if requestPost returns error', async () => {
;(requestPost as jest.Mock).mockResolvedValue({ errors: 'errors' })

const chainId = ChainEnum.Goerli
const pool = '0xc866A11cf6A3D178624Ff46B8A49202206A7c51B'

const result = await SubgraphService.getPoolStats(chainId, pool)
expect(result).toStrictEqual(undefined)
})

it('should return pool stats', async () => {
const pool = '0xc866A11cf6A3D178624Ff46B8A49202206A7c51B'
const poolStat = {
id: pool,
amountCreditOriginated: 300,
amountCreditRepaid: 400,
amountCreditDefaulted: 500,
}
;(requestPost as jest.Mock).mockResolvedValue({
data: {
poolStat,
},
})

const chainId = ChainEnum.Goerli

const result = await SubgraphService.getPoolStats(chainId, pool)
expect(result).toStrictEqual(poolStat)
})
})
25 changes: 16 additions & 9 deletions packages/huma-shared/src/utils/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ import { BigNumber, ethers } from 'ethers'
import { isEmpty } from './common'
import { scientificToDecimal } from './scientificToDecimal'

const moneyFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
})

const numberFormatter = new Intl.NumberFormat('en-US')

export const formatMoney = (num: number | string | undefined) => {
export const formatMoney = (
num: number | string | undefined,
notation?: Intl.NumberFormatOptions['notation'],
) => {
if (isEmpty(num) || Number.isNaN(num)) {
return num
}
Expand All @@ -20,6 +17,14 @@ export const formatMoney = (num: number | string | undefined) => {
if (numCast > 1_000) {
numCast = Math.round(numCast)
}

const moneyFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
notation,
})

return moneyFormatter.format(numCast)
}

Expand Down Expand Up @@ -55,13 +60,15 @@ export const downScale = <T = string>(
}

export const upScale = <T = string>(
num: string | number,
num: string | number | BigNumber,
decimals?: number,
): T => {
if (isEmpty(num) || isEmpty(decimals)) {
return num as T
}
const result = Number(num) * 10 ** decimals!
const result = BigNumber.isBigNumber(num)
? num.mul(10 ** decimals!)
: Number(num) * 10 ** decimals!
if (typeof num === 'string') {
return String(result) as T
}
Expand Down

0 comments on commit a6fe4a6

Please sign in to comment.