From 0b8c2263cdfd5f8281e7539a13f69f5afadcb6b2 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Mon, 30 Oct 2023 10:21:50 -0400
Subject: [PATCH 01/11] Add ImpactMarket RWR
---
packages/huma-shared/src/utils/pool.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/packages/huma-shared/src/utils/pool.ts b/packages/huma-shared/src/utils/pool.ts
index c4e4d41c..a879296e 100644
--- a/packages/huma-shared/src/utils/pool.ts
+++ b/packages/huma-shared/src/utils/pool.ts
@@ -66,6 +66,7 @@ export type PoolInfoType = {
subgraph?: string
superTokens?: { id: string; symbol: string; decimals: number }[]
borrower?: string // For single borrower pools
+ rwrUploader?: string // For single borrower pools where receivables are uploaded by a different wallet
hidden?: boolean // For pools that shouldn't be displayed in the UI
order?: number // Ordering in the pool list. Null values are sorted last.
disableBorrow?: boolean
@@ -458,6 +459,7 @@ export const PoolContractMap: PoolContractMapType = {
disableBorrow: true,
detailsPage: true,
borrower: '0x10FB65dc26a7aCC7CFB4eA3b6E007c8C77591486',
+ rwrUploader: '0x4c6388346f2a3af2d64461339a5cdd3a3d63ccf5',
},
},
[POOL_NAME.ArfCreditPool1]: {
From be89942d96ad1cd3b22267a6008c966864408789 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Fri, 10 Nov 2023 11:32:06 -0500
Subject: [PATCH 02/11] Take min of pool balance or lender position for
withdraw
---
.../components/Lend/withdraw/2-ChooseAmount.tsx | 8 +++++++-
.../src/components/Lend/withdraw/index.tsx | 15 +++++++++++----
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/packages/huma-widget/src/components/Lend/withdraw/2-ChooseAmount.tsx b/packages/huma-widget/src/components/Lend/withdraw/2-ChooseAmount.tsx
index 1a7013b1..08270111 100644
--- a/packages/huma-widget/src/components/Lend/withdraw/2-ChooseAmount.tsx
+++ b/packages/huma-widget/src/components/Lend/withdraw/2-ChooseAmount.tsx
@@ -9,18 +9,24 @@ import { ChooseAmountModal } from '../../ChooseAmountModal'
type Props = {
lenderPosition: BigNumber
+ poolBalance: BigNumber
poolInfo: PoolInfoType
}
export function ChooseAmount({
lenderPosition,
+ poolBalance,
poolInfo,
}: Props): React.ReactElement | null {
const dispatch = useAppDispatch()
const { poolUnderlyingToken } = poolInfo
const { symbol, decimals } = poolUnderlyingToken
const [currentAmount, setCurrentAmount] = useState(0)
- const withdrawableAmount = downScale(lenderPosition, decimals)
+ // Take the minimum of the pool balance or the lender position
+ const withdrawableAmountBN = lenderPosition.lt(poolBalance)
+ ? lenderPosition
+ : poolBalance
+ const withdrawableAmount = downScale(withdrawableAmountBN, decimals)
const handleChangeAmount = useCallback(
(newAmount: number) => {
diff --git a/packages/huma-widget/src/components/Lend/withdraw/index.tsx b/packages/huma-widget/src/components/Lend/withdraw/index.tsx
index 983cf624..677381cf 100644
--- a/packages/huma-widget/src/components/Lend/withdraw/index.tsx
+++ b/packages/huma-widget/src/components/Lend/withdraw/index.tsx
@@ -3,6 +3,7 @@ import {
POOL_NAME,
POOL_TYPE,
useLenderPosition,
+ usePoolBalance,
usePoolInfo,
} from '@huma-finance/shared'
import React, { useCallback, useEffect } from 'react'
@@ -51,21 +52,23 @@ export function LendWithdraw({
poolType,
account,
)
+ const [poolBalance, refreshPoolBalance] = usePoolBalance(poolName, poolType)
useEffect(() => {
- if (!step && lenderPosition) {
+ if (!step && lenderPosition && poolBalance) {
dispatch(setStep(WIDGET_STEP.CheckWithdrawable))
}
- }, [dispatch, lenderPosition, step])
+ }, [dispatch, lenderPosition, poolBalance, step])
const handleWithdrawSuccess = useCallback(
(blockNumber: number) => {
refreshLenderPosition()
+ refreshPoolBalance()
if (handleSuccess) {
handleSuccess(blockNumber)
}
},
- [handleSuccess, refreshLenderPosition],
+ [handleSuccess, refreshLenderPosition, refreshPoolBalance],
)
if (!poolInfo) {
@@ -82,7 +85,11 @@ export function LendWithdraw({
)}
{step === WIDGET_STEP.ChooseAmount && (
-
+
)}
{step === WIDGET_STEP.Transfer && }
{step === WIDGET_STEP.Done && (
From db63d6b1ac418668949abc5a9902f2d9f823c890 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Mon, 13 Nov 2023 13:39:04 -0500
Subject: [PATCH 03/11] Cherry pick subgraph service pool stats logic
---
packages/huma-sdk/API.md | 14 ++++++
.../huma-sdk/src/services/SubgraphService.ts | 50 +++++++++++++++++++
.../tests/services/SubgraphService.test.ts | 44 ++++++++++++++++
packages/huma-shared/src/utils/number.ts | 19 ++++---
4 files changed, 120 insertions(+), 7 deletions(-)
diff --git a/packages/huma-sdk/API.md b/packages/huma-sdk/API.md
index f07efb6c..c9c05738 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 42a52e9c..20a01bfb 100644
--- a/packages/huma-sdk/src/services/SubgraphService.ts
+++ b/packages/huma-sdk/src/services/SubgraphService.ts
@@ -196,6 +196,55 @@ function getRWReceivableInfo(
})
}
+type PoolStats = {
+ id: string
+ 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
+ }
+ }
+`
+
+ 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 +254,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 0341fd50..5372c7d6 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 poolStats = {
+ id: pool,
+ amountCreditOriginated: 300,
+ amountCreditRepaid: 400,
+ amountCreditDefaulted: 500,
+ }
+ ;(requestPost as jest.Mock).mockResolvedValue({
+ data: {
+ poolStats,
+ },
+ })
+
+ const chainId = ChainEnum.Goerli
+
+ const result = await SubgraphService.getPoolStats(chainId, pool)
+ expect(result).toStrictEqual(poolStats)
+ })
+})
diff --git a/packages/huma-shared/src/utils/number.ts b/packages/huma-shared/src/utils/number.ts
index 829a7945..5c81e5a9 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)
}
From 1a8e32d3802b0ee39caca8e88c623e15f58ed3f2 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Mon, 13 Nov 2023 16:21:10 -0500
Subject: [PATCH 04/11] Fix upScale for BigNumber
---
packages/huma-shared/src/utils/number.ts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/packages/huma-shared/src/utils/number.ts b/packages/huma-shared/src/utils/number.ts
index 5c81e5a9..f7975da8 100644
--- a/packages/huma-shared/src/utils/number.ts
+++ b/packages/huma-shared/src/utils/number.ts
@@ -60,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
}
From a3d1570e2cd6f22cf949645f6afe647129eb69fb Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Mon, 13 Nov 2023 17:52:29 -0500
Subject: [PATCH 05/11] Fix test
---
.../huma-sdk/src/services/SubgraphService.ts | 18 +++++++++---------
.../tests/services/SubgraphService.test.ts | 6 +++---
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/packages/huma-sdk/src/services/SubgraphService.ts b/packages/huma-sdk/src/services/SubgraphService.ts
index 20a01bfb..67f65b4a 100644
--- a/packages/huma-sdk/src/services/SubgraphService.ts
+++ b/packages/huma-sdk/src/services/SubgraphService.ts
@@ -221,15 +221,15 @@ function getPoolStats(
}
const PoolStatsQuery = `
- query {
- poolStat(id:"${pool?.toLowerCase()}") {
- id
- amountCreditOriginated
- amountCreditRepaid
- amountCreditDefaulted
- }
- }
-`
+ query {
+ poolStat(id:"${pool?.toLowerCase()}") {
+ id
+ amountCreditOriginated
+ amountCreditRepaid
+ amountCreditDefaulted
+ }
+ }
+ `
return requestPost<{
errors?: unknown
diff --git a/packages/huma-sdk/tests/services/SubgraphService.test.ts b/packages/huma-sdk/tests/services/SubgraphService.test.ts
index 5372c7d6..3e862be3 100644
--- a/packages/huma-sdk/tests/services/SubgraphService.test.ts
+++ b/packages/huma-sdk/tests/services/SubgraphService.test.ts
@@ -218,7 +218,7 @@ describe('getPoolStats', () => {
it('should return pool stats', async () => {
const pool = '0xc866A11cf6A3D178624Ff46B8A49202206A7c51B'
- const poolStats = {
+ const poolStat = {
id: pool,
amountCreditOriginated: 300,
amountCreditRepaid: 400,
@@ -226,13 +226,13 @@ describe('getPoolStats', () => {
}
;(requestPost as jest.Mock).mockResolvedValue({
data: {
- poolStats,
+ poolStat,
},
})
const chainId = ChainEnum.Goerli
const result = await SubgraphService.getPoolStats(chainId, pool)
- expect(result).toStrictEqual(poolStats)
+ expect(result).toStrictEqual(poolStat)
})
})
From 347bf1c48c9d6a68b97d6f470c2cc7db26262769 Mon Sep 17 00:00:00 2001
From: shan-57blocks <115970472+shan-57blocks@users.noreply.github.com>
Date: Tue, 14 Nov 2023 13:50:04 +0800
Subject: [PATCH 06/11] Superfluid polygon supports (#68)
* add superfluid pool info
* update HDT address
* transform payer address to checksum address
* update superfluid polygon subgraph
* update superfluid drawdown for polygon
* fix tests issue
* fix superToken decimals issue
* fix approve allowance issue
---------
Co-authored-by: shan
---
packages/huma-shared/src/utils/pool.ts | 49 ++++++++++++++++---
packages/huma-shared/tests/utils/pool.test.ts | 11 +++--
.../src/components/ApproveAllowanceModal.tsx | 7 +++
.../StreamFactoring/borrow/1-Evaluation.tsx | 7 +--
.../StreamFactoring/borrow/2-ChooseAmount.tsx | 36 ++++++++------
.../borrow/3-ConfirmTransfer.tsx | 11 ++---
.../StreamFactoring/borrow/5-Permit.tsx | 37 +-------------
.../StreamFactoring/borrow/index.tsx | 5 +-
.../SuperfluidFactoredList.tsx | 4 +-
.../SuperfluidUpcomingList.tsx | 4 +-
packages/huma-widget/src/index.tsx | 15 ++++--
11 files changed, 103 insertions(+), 83 deletions(-)
diff --git a/packages/huma-shared/src/utils/pool.ts b/packages/huma-shared/src/utils/pool.ts
index fafadf99..0c209830 100644
--- a/packages/huma-shared/src/utils/pool.ts
+++ b/packages/huma-shared/src/utils/pool.ts
@@ -64,7 +64,7 @@ export type PoolInfoType = {
}
extra?: {
subgraph?: string
- superTokens?: { id: string; symbol: string; decimals: number }[]
+ superToken?: { id: string; symbol: string; decimals: number }
borrower?: string // For single borrower pools
rwrUploader?: string // For single borrower pools where receivables are uploaded by a different wallet
hidden?: boolean // For pools that shouldn't be displayed in the UI
@@ -314,6 +314,39 @@ export const PoolContractMap: PoolContractMapType = {
},
},
},
+ [POOL_TYPE.Stream]: {
+ [POOL_NAME.Superfluid]: {
+ basePoolConfig: '0x22C024496036A8e97F93E14efa0d8379192bb22c',
+ pool: '0xF713B5203Cb6f3223830De218c2ed89Ee654b94B',
+ poolProcessor: '0x6E2f33b6d3F1E2048d078984f7FFF847C0Ed3bEd',
+ poolFeeManager: '0xd5FD3F917cf8901BeB102d81504033C748c87F19',
+ poolUnderlyingToken: {
+ address: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174',
+ symbol: 'USDC',
+ decimals: 6,
+ icon: 'USDC',
+ },
+ assetAddress: '0xa8B0362cfE0c8e4fd1D74c3512348d6f48d71080',
+ poolName: POOL_NAME.Superfluid,
+ poolType: POOL_TYPE.Stream,
+ poolAbi: STEAM_FACTORING_POOL_ABI,
+ basePoolConfigAbi: BASE_POOL_CONFIG_ABI,
+ poolAssetAbi: TRADABLE_STREAM_ABI,
+ HDT: {
+ address: '0x30b1f6bca8c6c742ede0ccb4eceb22af4cba58ef',
+ abi: HDT_ABI,
+ },
+ extra: {
+ subgraph:
+ 'https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-matic',
+ superToken: {
+ id: '0xcaa7349cea390f89641fe306d93591f87595dc1f',
+ symbol: 'USDCx',
+ decimals: 18,
+ },
+ },
+ },
+ },
},
[ChainEnum.Goerli]: {
[POOL_TYPE.CreditLine]: {
@@ -513,13 +546,11 @@ export const PoolContractMap: PoolContractMapType = {
extra: {
subgraph:
'https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-mumbai',
- superTokens: [
- {
- id: '0x42bb40bf79730451b11f6de1cba222f17b87afd7',
- symbol: 'fUSDCx',
- decimals: 18,
- },
- ],
+ superToken: {
+ id: '0x42bb40bf79730451b11f6de1cba222f17b87afd7',
+ symbol: 'fUSDCx',
+ decimals: 18,
+ },
},
},
},
@@ -601,6 +632,8 @@ export const SupplementaryContractsMap: {
}
} = {
[ChainEnum.Polygon]: {
+ [SupplementaryContracts.MultiSend]:
+ '0xDa21D2Be30353EC6Aa5AcD37999806cCefaa4C6A',
[SupplementaryContracts.RealWorldReceivable]:
'0xCf67CcEaC38b5E1880d62b5DB531Ab1E77614E3D',
},
diff --git a/packages/huma-shared/tests/utils/pool.test.ts b/packages/huma-shared/tests/utils/pool.test.ts
index 7d72d34d..e7712e68 100644
--- a/packages/huma-shared/tests/utils/pool.test.ts
+++ b/packages/huma-shared/tests/utils/pool.test.ts
@@ -9,10 +9,13 @@ import {
} from '../../src/utils/pool'
describe('getPoolInfo', () => {
- it('returns null if chainId is undefined', () => {
- expect(
- getPoolInfo(undefined, POOL_TYPE.Stream, POOL_NAME.Superfluid),
- ).toBeNull()
+ it('returns default if chainId is undefined', () => {
+ const poolInfo = getPoolInfo(
+ undefined,
+ POOL_TYPE.Stream,
+ POOL_NAME.Superfluid,
+ )
+ expect(poolInfo?.pool).toBe('0xF713B5203Cb6f3223830De218c2ed89Ee654b94B')
})
it('returns null if poolType or poolName is not found', () => {
diff --git a/packages/huma-widget/src/components/ApproveAllowanceModal.tsx b/packages/huma-widget/src/components/ApproveAllowanceModal.tsx
index 76800b47..4c2b1bc9 100644
--- a/packages/huma-widget/src/components/ApproveAllowanceModal.tsx
+++ b/packages/huma-widget/src/components/ApproveAllowanceModal.tsx
@@ -85,6 +85,12 @@ export function ApproveAllowanceModal({
const amountToIncrease = BigNumber.from(targetAllowanceAmount).sub(
currentAllowance ?? 0,
)
+
+ if (amountToIncrease.lte(0)) {
+ handleSuccess()
+ return
+ }
+
send({
contract: poolUnderlyingTokenContract!,
method: 'increaseAllowance',
@@ -94,6 +100,7 @@ export function ApproveAllowanceModal({
}, [
account,
allowanceAmount,
+ handleSuccess,
poolInfo.pool,
poolUnderlyingTokenContract,
provider,
diff --git a/packages/huma-widget/src/components/StreamFactoring/borrow/1-Evaluation.tsx b/packages/huma-widget/src/components/StreamFactoring/borrow/1-Evaluation.tsx
index 3577dbb1..eb2ec8d8 100644
--- a/packages/huma-widget/src/components/StreamFactoring/borrow/1-Evaluation.tsx
+++ b/packages/huma-widget/src/components/StreamFactoring/borrow/1-Evaluation.tsx
@@ -1,10 +1,11 @@
-import { useWeb3React } from '@web3-react/core'
+import { getAddress } from '@ethersproject/address'
import { PoolInfoType } from '@huma-finance/shared'
+import { useWeb3React } from '@web3-react/core'
import React, { useEffect } from 'react'
import useEA from '../../../hooks/useEA'
-import { LoadingModal } from '../../LoadingModal'
import { WIDGET_STEP } from '../../../store/widgets.store'
+import { LoadingModal } from '../../LoadingModal'
import { SignIn } from '../../SignIn'
type Props = {
@@ -35,7 +36,7 @@ export function Evaluation({
receivable: {
address: poolInfo.assetAddress!,
},
- payerWalletAddress: payerAddress,
+ payerWalletAddress: getAddress(payerAddress),
superToken,
},
},
diff --git a/packages/huma-widget/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx b/packages/huma-widget/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx
index 826ff0e3..92258982 100644
--- a/packages/huma-widget/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx
+++ b/packages/huma-widget/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx
@@ -28,20 +28,24 @@ export function ChooseAmount({
const [chargedFees, setChargedFees] = useState(0)
const [currentAmount, setCurrentAmount] = useState(0)
const borrowPeriodInSeconds = approval!.terms.intervalInDays * 24 * 60 * 60
+ const superTokenDecimals = poolInfo.extra?.superToken?.decimals!
+ const underlyingTokenDecimals = poolInfo.poolUnderlyingToken.decimals!
+ // To ensure not to borrow all the available flowrate due to contract limitation
+ const borrowMaxAmount = Number(approval!.terms.creditLimitFormatted) - 0.01
const getBorrowFlowrateAndAmount = useCallback(
(borrowAmount: number) => {
const currentFlowRateBN = toBigNumber(currentFlowRate)
- const borrowAmountBN = toBigNumber(
- upScale(borrowAmount, approval!.token.decimal),
+ const borrowAmountSuperTokenBN = toBigNumber(
+ upScale(borrowAmount, superTokenDecimals),
)
- const totalAmountInBorrowPeriod = currentFlowRateBN.mul(
+ const totalAmountSuperTokenInBorrowPeriod = currentFlowRateBN.mul(
borrowPeriodInSeconds,
)
- let borrowFlowrate = borrowAmountBN
+ let borrowFlowrate = borrowAmountSuperTokenBN
.mul(currentFlowRateBN)
- .div(totalAmountInBorrowPeriod)
+ .div(totalAmountSuperTokenInBorrowPeriod)
// To ensure enough flowRate due to round down when convert to string
.add(1)
@@ -49,26 +53,28 @@ export function ChooseAmount({
if (borrowFlowrate.gte(currentFlowRateBN)) {
borrowFlowrate = currentFlowRateBN.sub(1)
}
- if (borrowAmountBN.gte(approval!.terms.creditLimit)) {
- borrowFlowrate = borrowFlowrate.sub(1)
- }
// As borrowFlowrate adds 1, need to calculate the new accurate borrow amount
const newBorrowAmountBN = borrowFlowrate
- .mul(totalAmountInBorrowPeriod)
+ .mul(totalAmountSuperTokenInBorrowPeriod)
.div(currentFlowRateBN)
- const newBorrowAmount = downScale(
- newBorrowAmountBN,
- approval!.token.decimal,
+ const newBorrowAmount = downScale(newBorrowAmountBN, superTokenDecimals)
+ const newBorrowAmountUnderlyingTokenBN = toBigNumber(
+ upScale(newBorrowAmount, underlyingTokenDecimals),
)
return {
borrowFlowrate: borrowFlowrate.toString(),
borrowAmount: Number(newBorrowAmount),
- borrowAmountBN: newBorrowAmountBN,
+ borrowAmountBN: newBorrowAmountUnderlyingTokenBN,
}
},
- [approval, borrowPeriodInSeconds, currentFlowRate],
+ [
+ borrowPeriodInSeconds,
+ currentFlowRate,
+ superTokenDecimals,
+ underlyingTokenDecimals,
+ ],
)
const handleChangeAmount = useCallback(
@@ -114,7 +120,7 @@ export function ChooseAmount({
{
- const step = CHAINS[chainId!].isTestnet
- ? WIDGET_STEP.ApproveAllowance
- : WIDGET_STEP.Permit
- dispatch(setStep(step))
- }, [chainId, dispatch])
+ dispatch(setStep(WIDGET_STEP.ApproveAllowance))
+ }, [dispatch])
if (isEmpty(borrowAmount) || isEmpty(approval)) {
return null
diff --git a/packages/huma-widget/src/components/StreamFactoring/borrow/5-Permit.tsx b/packages/huma-widget/src/components/StreamFactoring/borrow/5-Permit.tsx
index 2c941601..733bd02a 100644
--- a/packages/huma-widget/src/components/StreamFactoring/borrow/5-Permit.tsx
+++ b/packages/huma-widget/src/components/StreamFactoring/borrow/5-Permit.tsx
@@ -1,12 +1,9 @@
import {
- CHAINS,
- Erc2612,
PoolInfoType,
SuperfluidPoolProcessor,
+ SuperfluidPoolProcessor_ABI,
useERC2612Permit,
useMount,
- ERC2612_ABI,
- SuperfluidPoolProcessor_ABI,
} from '@huma-finance/shared'
import { BigNumber, Contract, ethers } from 'ethers'
import React from 'react'
@@ -25,7 +22,6 @@ import { LoadingModal } from '../../LoadingModal'
type Props = {
poolInfo: PoolInfoType
payerAddress: string
- chainId: number
borrower: string
superToken: string
}
@@ -33,36 +29,15 @@ type Props = {
export function Permit({
poolInfo,
payerAddress,
- chainId,
borrower,
superToken,
}: Props): React.ReactElement | null {
const dispatch = useDispatch()
- const { address: tokenAddress } = poolInfo.poolUnderlyingToken
const { borrowAmountBN: borrowAmountBNJson, stream } =
useAppSelector(selectWidgetState)
- const { getERC2612PermitMessage, getTradableStreamPermitMessage } =
- useERC2612Permit()
+ const { getTradableStreamPermitMessage } = useERC2612Permit()
const borrowAmountBN = BigNumber.from(borrowAmountBNJson)
- const getApproveAllowanceCallData = async () => {
- const erc2612PermitResult = await getERC2612PermitMessage(
- tokenAddress,
- poolInfo.poolProcessor!,
- borrowAmountBN.toString()!,
- )
- const tokenContract = new Contract(tokenAddress, ERC2612_ABI) as Erc2612
- return tokenContract.interface.encodeFunctionData('permit', [
- poolInfo.poolProcessor!,
- borrowAmountBN.toString()!,
- erc2612PermitResult.nonce,
- erc2612PermitResult.deadline,
- erc2612PermitResult.v,
- erc2612PermitResult.r,
- erc2612PermitResult.s,
- ])
- }
-
const getDrawdownCallData = async () => {
const NFTPermitResult = await getTradableStreamPermitMessage(
poolInfo.assetAddress!,
@@ -113,14 +88,6 @@ export function Permit({
try {
const callData = []
const addresses: string[] = []
-
- // The token in Goerli hasn't integrated ERC-2612
- if (!CHAINS[chainId].isTestnet) {
- const approveAllowanceCallData = await getApproveAllowanceCallData()
- addresses.push(tokenAddress)
- callData.push(approveAllowanceCallData)
- }
-
const drawdownCalldata = await getDrawdownCallData()
addresses.push(poolInfo.poolProcessor!)
callData.push(drawdownCalldata)
diff --git a/packages/huma-widget/src/components/StreamFactoring/borrow/index.tsx b/packages/huma-widget/src/components/StreamFactoring/borrow/index.tsx
index f756bf95..04947f41 100644
--- a/packages/huma-widget/src/components/StreamFactoring/borrow/index.tsx
+++ b/packages/huma-widget/src/components/StreamFactoring/borrow/index.tsx
@@ -39,7 +39,7 @@ export function StreamFactoringBorrow({
handleSuccess,
}: StreamFactoringBorrowProps): React.ReactElement | null {
const dispatch = useDispatch()
- const { account, chainId } = useWeb3React()
+ const { account } = useWeb3React()
const poolInfo = usePoolInfo(poolName, poolType)
const { step, errorMessage } = useAppSelector(selectWidgetState)
@@ -71,11 +71,10 @@ export function StreamFactoringBorrow({
{step === WIDGET_STEP.ApproveAllowance && (
)}
- {step === WIDGET_STEP.Permit && account && chainId && (
+ {step === WIDGET_STEP.Permit && account && (
diff --git a/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidFactoredList.tsx b/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidFactoredList.tsx
index 386adc6c..4806ae47 100644
--- a/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidFactoredList.tsx
+++ b/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidFactoredList.tsx
@@ -50,9 +50,9 @@ export function SuperfluidFactoredList({
const setItem = useCallback(
() =>
Promise.resolve({
- name: poolInfo?.extra?.superTokens?.[0].symbol ?? '',
+ name: poolInfo?.extra?.superToken?.symbol ?? '',
}),
- [poolInfo?.extra?.superTokens],
+ [poolInfo?.extra?.superToken],
)
return (
diff --git a/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidUpcomingList.tsx b/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidUpcomingList.tsx
index 6c014d08..1ed91c76 100644
--- a/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidUpcomingList.tsx
+++ b/packages/huma-widget/src/components/SuperfluidFactoring/SuperfluidUpcomingList.tsx
@@ -106,7 +106,9 @@ export function SuperfluidUpcomingList({
const { data } = useQuery<{ streams: Stream[] }>(GET_RECEIVED_STREAMS, {
variables: {
receiver: account ? account.toLowerCase() : undefined,
- tokenIds: poolInfo?.extra?.superTokens?.map((item) => item.id) ?? [],
+ tokenIds: poolInfo?.extra?.superToken
+ ? [poolInfo.extra.superToken.id]
+ : [],
},
})
diff --git a/packages/huma-widget/src/index.tsx b/packages/huma-widget/src/index.tsx
index 9194c246..c80a17ff 100644
--- a/packages/huma-widget/src/index.tsx
+++ b/packages/huma-widget/src/index.tsx
@@ -10,6 +10,7 @@ import { Provider as Eip1193Provider } from '@web3-react/types'
import { Provider as AtomProvider } from 'jotai'
import { Provider as ReduxProvider } from 'react-redux'
+import { useEffect, useState } from 'react'
import { ChainSupportProvider } from './components/ChainSupportProvider'
import {
CreditLineApprove,
@@ -63,11 +64,17 @@ type WidgetProps = {
function Widget(props: WCProps) {
const { children, provider } = props
+ const [chainId, setChainId] = useState(undefined)
- let chainId
- if (provider instanceof JsonRpcProvider) {
- chainId = provider.network.chainId
- }
+ useEffect(() => {
+ const getChainId = async () => {
+ if (provider instanceof JsonRpcProvider) {
+ const network = await provider.getNetwork()
+ setChainId(network?.chainId)
+ }
+ }
+ getChainId()
+ }, [provider])
return (
From a4c68cc023c9005ee9fa70ebed3fd0bce1d3790d Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Wed, 15 Nov 2023 14:45:27 -0500
Subject: [PATCH 07/11] Add totalPoolAssets
---
.../huma-sdk/src/services/SubgraphService.ts | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/packages/huma-sdk/src/services/SubgraphService.ts b/packages/huma-sdk/src/services/SubgraphService.ts
index 67f65b4a..5e3f822a 100644
--- a/packages/huma-sdk/src/services/SubgraphService.ts
+++ b/packages/huma-sdk/src/services/SubgraphService.ts
@@ -198,6 +198,7 @@ function getRWReceivableInfo(
type PoolStats = {
id: string
+ totalPoolAssets: number
amountCreditOriginated: number
amountCreditRepaid: number
amountCreditDefaulted: number
@@ -222,14 +223,14 @@ function getPoolStats(
const PoolStatsQuery = `
query {
- poolStat(id:"${pool?.toLowerCase()}") {
- id
- amountCreditOriginated
- amountCreditRepaid
- amountCreditDefaulted
- }
- }
- `
+ poolStat(id:"${pool?.toLowerCase()}") {
+ id
+ amountCreditOriginated
+ amountCreditRepaid
+ amountCreditDefaulted
+ totalPoolAssets
+ }
+ }`
return requestPost<{
errors?: unknown
From 50e88d14d795663eda410f4e010a3c14b96b4a23 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Tue, 21 Nov 2023 12:09:18 -0500
Subject: [PATCH 08/11] Fix upscale for overflow
---
packages/huma-shared/src/utils/number.ts | 2 +-
packages/huma-shared/src/utils/pool.ts | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/packages/huma-shared/src/utils/number.ts b/packages/huma-shared/src/utils/number.ts
index f7975da8..2c897137 100644
--- a/packages/huma-shared/src/utils/number.ts
+++ b/packages/huma-shared/src/utils/number.ts
@@ -67,7 +67,7 @@ export const upScale = (
return num as T
}
const result = BigNumber.isBigNumber(num)
- ? num.mul(10 ** decimals!)
+ ? num.mul(BigNumber.from(10).pow(decimals!))
: Number(num) * 10 ** decimals!
if (typeof num === 'string') {
return String(result) as T
diff --git a/packages/huma-shared/src/utils/pool.ts b/packages/huma-shared/src/utils/pool.ts
index 0c209830..fba9a7e6 100644
--- a/packages/huma-shared/src/utils/pool.ts
+++ b/packages/huma-shared/src/utils/pool.ts
@@ -514,6 +514,8 @@ export const PoolContractMap: PoolContractMapType = {
abi: HDT_ABI,
},
extra: {
+ borrower: '0xea57a8a51377752ffddaa3db4d13ce8f97677f2d',
+ rwrUploader: '0xea57a8a51377752ffddaa3db4d13ce8f97677f2d',
disableBorrow: true,
detailsPage: true,
},
From 8485c51b0262799b2c6b7405548c24375d123416 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Tue, 21 Nov 2023 12:12:25 -0500
Subject: [PATCH 09/11] Add test
---
packages/huma-shared/tests/utils/number.test.ts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/packages/huma-shared/tests/utils/number.test.ts b/packages/huma-shared/tests/utils/number.test.ts
index 41662cd4..ad245d99 100644
--- a/packages/huma-shared/tests/utils/number.test.ts
+++ b/packages/huma-shared/tests/utils/number.test.ts
@@ -63,6 +63,14 @@ describe('upScale', () => {
expect(upScale('123.45', 2)).toBe('12345')
expect(upScale(123.45, 2)).toBe(12345)
})
+
+ it('returns the upscaled number if the input is a valid number and decimals would cause overflow', () => {
+ expect(
+ upScale(BigNumber.from(10), 18).eq(
+ BigNumber.from('10000000000000000000'),
+ ),
+ ).toBe(true)
+ })
})
describe('toBigNumber', () => {
From 13746d4e79e8d7c241c719694bfe65f935196eb6 Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Mon, 27 Nov 2023 12:26:30 -0500
Subject: [PATCH 10/11] Add raincards test pool
---
packages/huma-shared/src/utils/pool.ts | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/packages/huma-shared/src/utils/pool.ts b/packages/huma-shared/src/utils/pool.ts
index fba9a7e6..2e9f119f 100644
--- a/packages/huma-shared/src/utils/pool.ts
+++ b/packages/huma-shared/src/utils/pool.ts
@@ -17,6 +17,7 @@ export enum POOL_NAME {
BSOS = 'BSOS',
ImpactMarket = 'ImpactMarket',
Symplifi = 'Symplifi',
+ Raincards = 'Raincards',
}
export enum POOL_TYPE {
@@ -139,6 +140,14 @@ export const PoolMap: PoolMapType = {
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
estAPY: '20%',
},
+ [POOL_NAME.Raincards]: {
+ name: 'Raincards Pool',
+ borrowDesc:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ lendDesc:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ estAPY: '20%',
+ },
},
[POOL_TYPE.Invoice]: {
[POOL_NAME.RequestNetwork]: {
@@ -557,22 +566,22 @@ export const PoolContractMap: PoolContractMapType = {
},
},
[POOL_TYPE.CreditLine]: {
- [POOL_NAME.ArfUSDCMigrationTest]: {
- basePoolConfig: '0xe8338a5e3e58b425249f82594c82b42c2df4c5e9',
- pool: '0xbb1b50e1ec5835b3c58944e820e7a5e136141ddc',
- poolFeeManager: '0x9f667f613C16542aC8b1e502F4D796774F623D86',
+ [POOL_NAME.Raincards]: {
+ basePoolConfig: '0x10b7CBe54178eB6C81b2D84Ac073747BcA744F6C',
+ pool: '0xf8065dA82cC990325059c436939c6a90C322E9Dd',
+ poolFeeManager: '0x87534B96FD15EbD6Aa0456F45045B541e5E8889a',
poolUnderlyingToken: {
- address: '0x9999f7fea5938fd3b1e26a12c3f2fb024e194f97',
+ address: '0xb961c37ABDDA55929327fa9d20eBDE6BB8B1348E',
symbol: 'USDC',
decimals: 6,
icon: 'USDC',
},
- poolName: POOL_NAME.ArfUSDCMigrationTest,
+ poolName: POOL_NAME.Raincards,
poolType: POOL_TYPE.CreditLine,
poolAbi: BASE_CREDIT_POOL_ABI,
basePoolConfigAbi: BASE_POOL_CONFIG_ABI,
HDT: {
- address: '0x8bce02521622222Ee13D1Ce2c5E4CCab52ce24Bb',
+ address: '0x8Ec8f8AFE179032e2929C49eF4f8Ea2d18245B9a',
abi: HDT_ABI,
},
},
From 4bf85a26aff0a1a9ac251f6b703277291aade0bf Mon Sep 17 00:00:00 2001
From: Michael Liu
Date: Fri, 1 Dec 2023 12:21:13 -0500
Subject: [PATCH 11/11] Fix dep conflict
---
packages/huma-shared/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/huma-shared/package.json b/packages/huma-shared/package.json
index b596f764..f7ec1dca 100644
--- a/packages/huma-shared/package.json
+++ b/packages/huma-shared/package.json
@@ -38,7 +38,7 @@
"@mui/system": "^5.0.6",
"@mui/x-date-pickers": "^5.0.7",
"@reduxjs/toolkit": "^1.8.6",
- "@requestnetwork/multi-format": "^0.15.10",
+ "@requestnetwork/multi-format": "0.15.10",
"@types/utf8": "^3.0.1",
"@walletconnect/ethereum-provider": "1.8.0",
"@walletconnect/jsonrpc-http-connection": "^1.0.3",