diff --git a/packages/huma-sdk/API.md b/packages/huma-sdk/API.md index f07efb6..c9c0573 100644 --- a/packages/huma-sdk/API.md +++ b/packages/huma-sdk/API.md @@ -474,6 +474,7 @@ in Huma's pools that can be drawn down by the borrower.

* [.getCreditEventsForUser(userAddress, chainId, poolName, poolType, event)](#SubgraphService.getCreditEventsForUser) ⇒ Promise.<Array.<CreditEventPayload>> * [.getLastFactorizedAmountFromPool(userAddress, chainId, poolName, poolType)](#SubgraphService.getLastFactorizedAmountFromPool) ⇒ Promise.<number> * [.getRWReceivableInfo(userAddress, chainId, poolName, poolType, pagination)](#SubgraphService.getRWReceivableInfo) ⇒ Promise.<RealWorldReceivableInfoBase> + * [.getPoolStats(chainId, pool)](#SubgraphService.getPoolStats) ⇒ Promise.<{PoolStats}> @@ -534,6 +535,19 @@ in Huma's pools that can be drawn down by the borrower.

| poolType | POOL\_TYPE |

The type of the pool.

| | pagination | [Pagination](#Pagination) |

The pagination option.

| + + +### SubgraphService.getPoolStats(chainId, pool) ⇒ Promise.<{PoolStats}> +

Returns the pool's stats.

+ +**Kind**: static method of [SubgraphService](#SubgraphService) +**Returns**: Promise.<{PoolStats}> -

The pool's stats info.

+ +| Param | Type | Description | +| --- | --- | --- | +| chainId | number |

The ID of the chain.

| +| pool | string |

The address of the pool.

| + ## defaultWrapper() diff --git a/packages/huma-sdk/src/services/SubgraphService.ts b/packages/huma-sdk/src/services/SubgraphService.ts index 42a52e9..5e3f822 100644 --- a/packages/huma-sdk/src/services/SubgraphService.ts +++ b/packages/huma-sdk/src/services/SubgraphService.ts @@ -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 { + 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 @@ -205,4 +255,5 @@ export const SubgraphService = { getCreditEventsForUser, getLastFactorizedAmountFromPool, getRWReceivableInfo, + getPoolStats, } diff --git a/packages/huma-sdk/tests/services/SubgraphService.test.ts b/packages/huma-sdk/tests/services/SubgraphService.test.ts index 0341fd5..3e862be 100644 --- a/packages/huma-sdk/tests/services/SubgraphService.test.ts +++ b/packages/huma-sdk/tests/services/SubgraphService.test.ts @@ -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) + }) +}) diff --git a/packages/huma-shared/src/utils/number.ts b/packages/huma-shared/src/utils/number.ts index 829a794..f7975da 100644 --- a/packages/huma-shared/src/utils/number.ts +++ b/packages/huma-shared/src/utils/number.ts @@ -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 } @@ -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) } @@ -55,13 +60,15 @@ export const downScale = ( } export const upScale = ( - 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 }