@huma-finance/widgets 0.0.51-beta.227 → 0.0.51-beta.347

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/API.md +454 -0
  2. package/dist/cjs/index.cjs +6097 -3790
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/index.d.ts +280 -2
  5. package/dist/index.js +6089 -3792
  6. package/dist/index.js.map +1 -1
  7. package/package.json +5 -4
  8. package/src/components/ApproveAllowanceModal.tsx +3 -1
  9. package/src/components/ApproveAllowanceModalV2.tsx +141 -0
  10. package/src/components/CreditLine/approve/index.tsx +9 -3
  11. package/src/components/CreditLine/autoPaybackV2/1-ApproveAllowance.tsx +33 -0
  12. package/src/components/CreditLine/autoPaybackV2/2-Success.tsx +13 -0
  13. package/src/components/CreditLine/autoPaybackV2/index.tsx +87 -0
  14. package/src/components/CreditLine/borrow/2-ChooseAmount.tsx +12 -3
  15. package/src/components/CreditLine/borrow/5-Success.tsx +7 -2
  16. package/src/components/CreditLine/borrow/index.tsx +4 -2
  17. package/src/components/CreditLine/borrowV2/1-ChooseAmount.tsx +81 -0
  18. package/src/components/CreditLine/borrowV2/2-ApproveAllowance.tsx +33 -0
  19. package/src/components/CreditLine/borrowV2/3-Transfer.tsx +50 -0
  20. package/src/components/CreditLine/borrowV2/4-Success.tsx +42 -0
  21. package/src/components/CreditLine/borrowV2/5-Notifications.tsx +10 -0
  22. package/src/components/CreditLine/borrowV2/index.tsx +140 -0
  23. package/src/components/CreditLine/payment/1-ChooseAmount.tsx +9 -5
  24. package/src/components/CreditLine/payment/3-Transfer.tsx +1 -5
  25. package/src/components/CreditLine/payment/4-Success.tsx +2 -2
  26. package/src/components/CreditLine/payment/index.tsx +4 -2
  27. package/src/components/CreditLine/paymentV2/1-ChooseAmount.tsx +96 -0
  28. package/src/components/CreditLine/paymentV2/2-ApproveAllowance.tsx +33 -0
  29. package/src/components/CreditLine/paymentV2/3-Transfer.tsx +55 -0
  30. package/src/components/CreditLine/paymentV2/4-Success.tsx +42 -0
  31. package/src/components/CreditLine/paymentV2/index.tsx +111 -0
  32. package/src/components/CreditLine/supplyFLC/1-ApproveAllowance.tsx +40 -0
  33. package/src/components/CreditLine/supplyFLC/2-Transfer.tsx +53 -0
  34. package/src/components/CreditLine/supplyFLC/3-Success.tsx +26 -0
  35. package/src/components/CreditLine/supplyFLC/index.tsx +121 -0
  36. package/src/components/Factoring/FactoredList.tsx +2 -1
  37. package/src/components/InputAmountModal.tsx +156 -0
  38. package/src/components/InvoiceFactoring/borrow/2-ChooseAmount.tsx +8 -1
  39. package/src/components/InvoiceFactoring/borrow/4-ApproveNFT.tsx +6 -2
  40. package/src/components/InvoiceFactoring/borrow/6-Success.tsx +5 -1
  41. package/src/components/InvoiceFactoring/borrow/index.tsx +9 -3
  42. package/src/components/InvoiceFactoring/payment/1-ChooseAmount.tsx +7 -2
  43. package/src/components/InvoiceFactoring/payment/index.tsx +9 -3
  44. package/src/components/Lend/addRedemptionV2/1-ChooseTranche.tsx +114 -0
  45. package/src/components/Lend/addRedemptionV2/2-ChooseAmount.tsx +114 -0
  46. package/src/components/Lend/addRedemptionV2/3-Transfer.tsx +56 -0
  47. package/src/components/Lend/addRedemptionV2/4-Done.tsx +20 -0
  48. package/src/components/Lend/addRedemptionV2/index.tsx +173 -0
  49. package/src/components/Lend/cancelRedemptionV2 /1-Transfer.tsx +51 -0
  50. package/src/components/Lend/cancelRedemptionV2 /2-Done.tsx +29 -0
  51. package/src/components/Lend/cancelRedemptionV2 /index.tsx +120 -0
  52. package/src/components/Lend/supply/1-Evaluation/EvaluationKYC.tsx +19 -2
  53. package/src/components/Lend/supply/2-ChooseAmount.tsx +1 -0
  54. package/src/components/Lend/supply/index.tsx +17 -3
  55. package/src/components/Lend/supplyV2/1-ChooseTranche.tsx +116 -0
  56. package/src/components/Lend/supplyV2/2-Evaluation.tsx +345 -0
  57. package/src/components/Lend/supplyV2/3-ChooseAmount.tsx +87 -0
  58. package/src/components/Lend/supplyV2/4-ApproveAllowance.tsx +33 -0
  59. package/src/components/Lend/supplyV2/5-Transfer.tsx +59 -0
  60. package/src/components/Lend/supplyV2/6-Success.tsx +79 -0
  61. package/src/components/Lend/supplyV2/7-Notifications.tsx +10 -0
  62. package/src/components/Lend/supplyV2/index.tsx +175 -0
  63. package/src/components/Lend/withdraw/1-CheckWithdrawble.tsx +5 -1
  64. package/src/components/Lend/withdraw/index.tsx +10 -3
  65. package/src/components/Lend/withdrawV2/1-ConfirmTransfer.tsx +135 -0
  66. package/src/components/Lend/withdrawV2/2-Transfer.tsx +50 -0
  67. package/src/components/Lend/withdrawV2/3-Done.tsx +31 -0
  68. package/src/components/Lend/withdrawV2/index.tsx +177 -0
  69. package/src/components/Notifi/NotifiSubscriptionModal.tsx +26 -38
  70. package/src/components/NumericFormatCustom.tsx +33 -0
  71. package/src/components/ReceivableBackedCreditLine/borrow/1-ChooseAmount.tsx +101 -0
  72. package/src/components/ReceivableBackedCreditLine/borrow/2-ApproveAllowance.tsx +33 -0
  73. package/src/components/ReceivableBackedCreditLine/borrow/3-ApproveReceivable.tsx +64 -0
  74. package/src/components/ReceivableBackedCreditLine/borrow/4-Transfer.tsx +61 -0
  75. package/src/components/ReceivableBackedCreditLine/borrow/5-Success.tsx +42 -0
  76. package/src/components/ReceivableBackedCreditLine/borrow/6-Notifications.tsx +10 -0
  77. package/src/components/ReceivableBackedCreditLine/borrow/index.tsx +148 -0
  78. package/src/components/ReceivableBackedCreditLine/payment/1-ChoosePaymentType.tsx +115 -0
  79. package/src/components/ReceivableBackedCreditLine/payment/2-ChooseAmount.tsx +84 -0
  80. package/src/components/ReceivableBackedCreditLine/payment/3-ApproveAllowance.tsx +41 -0
  81. package/src/components/ReceivableBackedCreditLine/payment/4-CreateReceivable.tsx +107 -0
  82. package/src/components/ReceivableBackedCreditLine/payment/5-ApproveReceivable.tsx +64 -0
  83. package/src/components/ReceivableBackedCreditLine/payment/6-Transfer.tsx +107 -0
  84. package/src/components/ReceivableBackedCreditLine/payment/7-Success.tsx +49 -0
  85. package/src/components/ReceivableBackedCreditLine/payment/index.tsx +159 -0
  86. package/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx +8 -1
  87. package/src/components/StreamFactoring/borrow/6-Transfer.tsx +3 -1
  88. package/src/components/StreamFactoring/borrow/7-Success.tsx +3 -1
  89. package/src/components/StreamFactoring/borrow/index.tsx +2 -2
  90. package/src/components/TxDoneModal.tsx +1 -1
  91. package/src/components/TxSendModal.tsx +8 -2
  92. package/src/components/TxSendModalV2.tsx +51 -0
  93. package/src/hooks/useNotifi.ts +4 -6
  94. package/src/index.tsx +268 -1
  95. package/src/store/widgets.reducers.ts +15 -0
  96. package/src/store/widgets.store.ts +6 -0
@@ -0,0 +1,26 @@
1
+ import { UnderlyingTokenInfo, formatMoney } from '@huma-finance/shared'
2
+ import { BigNumber, ethers } from 'ethers'
3
+ import React from 'react'
4
+
5
+ import { TxDoneModal } from '../../TxDoneModal'
6
+
7
+ type Props = {
8
+ amountToDeposit: BigNumber
9
+ poolUnderlyingToken: UnderlyingTokenInfo
10
+ handleAction: () => void
11
+ }
12
+
13
+ export function Success({
14
+ amountToDeposit,
15
+ poolUnderlyingToken,
16
+ handleAction,
17
+ }: Props): React.ReactElement {
18
+ const { symbol, decimals } = poolUnderlyingToken
19
+ const amountFormatted = ethers.utils.formatUnits(amountToDeposit, decimals)
20
+
21
+ const content = [
22
+ `You have supplied ${formatMoney(amountFormatted)} ${symbol}.`,
23
+ ]
24
+
25
+ return <TxDoneModal handleAction={handleAction} content={content} />
26
+ }
@@ -0,0 +1,121 @@
1
+ import {
2
+ FirstLossCoverIndex,
3
+ POOL_NAME,
4
+ useFirstLossCoverAllowanceV2,
5
+ useFirstLossCoverRequirementV2,
6
+ usePoolInfoV2,
7
+ usePoolUnderlyingTokenInfoV2,
8
+ } from '@huma-finance/shared'
9
+ import { useWeb3React } from '@web3-react/core'
10
+ import React, { useEffect } from 'react'
11
+ import { useDispatch } from 'react-redux'
12
+
13
+ import { useAppSelector } from '../../../hooks/useRedux'
14
+ import { setStep } from '../../../store/widgets.reducers'
15
+ import { selectWidgetState } from '../../../store/widgets.selectors'
16
+ import { WIDGET_STEP } from '../../../store/widgets.store'
17
+ import { ErrorModal } from '../../ErrorModal'
18
+ import { WidgetWrapper } from '../../WidgetWrapper'
19
+ import { ApproveAllowance } from './1-ApproveAllowance'
20
+ import { Success } from './3-Success'
21
+ import { Transfer } from './2-Transfer'
22
+
23
+ /**
24
+ * Supply first loss cover props
25
+ * @typedef {Object} SupplyFirstLossCoverProps
26
+ * @property {POOL_NAME} poolName The name of the pool.
27
+ * @property {function():void} handleClose Function to notify to close the widget modal when user clicks the 'x' close button.
28
+ * @property {function((number|undefined)):void|undefined} handleSuccess Optional function to notify that the credit line pool borrow action is successful.
29
+ */
30
+ export interface SupplyFirstLossCoverProps {
31
+ poolName: keyof typeof POOL_NAME
32
+ handleClose: () => void
33
+ handleSuccess?: (blockNumber?: number) => void
34
+ }
35
+
36
+ export function SupplyFirstLossCover({
37
+ poolName: poolNameStr,
38
+ handleClose,
39
+ handleSuccess,
40
+ }: SupplyFirstLossCoverProps): React.ReactElement | null {
41
+ const dispatch = useDispatch()
42
+ const poolName = POOL_NAME[poolNameStr]
43
+ const { account, chainId, provider } = useWeb3React()
44
+ const poolInfo = usePoolInfoV2(poolName, chainId)
45
+ const poolUnderlyingToken = usePoolUnderlyingTokenInfoV2(poolName, provider)
46
+ const { step, errorMessage } = useAppSelector(selectWidgetState)
47
+ const [requirement] = useFirstLossCoverRequirementV2(
48
+ poolName,
49
+ FirstLossCoverIndex.borrower,
50
+ account,
51
+ provider,
52
+ )
53
+ const [allowance] = useFirstLossCoverAllowanceV2(
54
+ poolName,
55
+ FirstLossCoverIndex.borrower,
56
+ account,
57
+ provider,
58
+ )
59
+ const { minAmountToDeposit } = requirement || {}
60
+ const title = 'Deposit First Loss Cover'
61
+
62
+ useEffect(() => {
63
+ if (!step && minAmountToDeposit && allowance) {
64
+ if (minAmountToDeposit.gt(allowance!)) {
65
+ dispatch(setStep(WIDGET_STEP.ApproveAllowance))
66
+ } else {
67
+ dispatch(setStep(WIDGET_STEP.Transfer))
68
+ }
69
+ }
70
+ }, [allowance, dispatch, minAmountToDeposit, step])
71
+
72
+ if (!poolInfo || !poolUnderlyingToken || !minAmountToDeposit || !allowance) {
73
+ return (
74
+ <WidgetWrapper
75
+ isOpen
76
+ isLoading
77
+ loadingTitle={title}
78
+ handleClose={handleClose}
79
+ handleSuccess={handleSuccess}
80
+ />
81
+ )
82
+ }
83
+
84
+ return (
85
+ <WidgetWrapper
86
+ isOpen
87
+ loadingTitle={title}
88
+ handleClose={handleClose}
89
+ handleSuccess={handleSuccess}
90
+ >
91
+ {step === WIDGET_STEP.ApproveAllowance && (
92
+ <ApproveAllowance
93
+ poolInfo={poolInfo}
94
+ poolUnderlyingToken={poolUnderlyingToken}
95
+ amountToDeposit={minAmountToDeposit}
96
+ />
97
+ )}
98
+ {step === WIDGET_STEP.Transfer && (
99
+ <Transfer
100
+ poolInfo={poolInfo}
101
+ amountToDeposit={minAmountToDeposit}
102
+ title={title}
103
+ />
104
+ )}
105
+ {step === WIDGET_STEP.Done && (
106
+ <Success
107
+ poolUnderlyingToken={poolUnderlyingToken}
108
+ handleAction={handleClose}
109
+ amountToDeposit={minAmountToDeposit}
110
+ />
111
+ )}
112
+ {step === WIDGET_STEP.Error && (
113
+ <ErrorModal
114
+ title={title}
115
+ errorMessage={errorMessage}
116
+ handleOk={handleClose}
117
+ />
118
+ )}
119
+ </WidgetWrapper>
120
+ )
121
+ }
@@ -39,10 +39,11 @@ export function FactoredList<T>({
39
39
  }: Props<T>): React.ReactElement {
40
40
  const theme = useTheme()
41
41
  const { isMdSize } = useMQ()
42
- const { isActive } = useWeb3React()
42
+ const { isActive, chainId } = useWeb3React()
43
43
  const { decimals } = usePoolUnderlyingToken(
44
44
  poolInfo.poolName,
45
45
  poolInfo.poolType,
46
+ chainId,
46
47
  )
47
48
  const [factoredItem, setFactoredItem] = useState<Partial<T>>()
48
49
  const { creditRecord, receivableInfo } = accountStats
@@ -0,0 +1,156 @@
1
+ import { Box, Button, css, TextField, useTheme } from '@mui/material'
2
+ import React, { useState } from 'react'
3
+ import { NumericFormat } from 'react-number-format'
4
+
5
+ import { BottomButton } from './BottomButton'
6
+ import { WrapperModal } from './WrapperModal'
7
+
8
+ type Props = {
9
+ title: string
10
+ subTitle: string
11
+ actionText: string
12
+ tokenSymbol: string
13
+ suffix?: string
14
+ currentAmount: number | string
15
+ maxAmount: number | string
16
+ maxAmountText?: string
17
+ maxAmountTitle?: string
18
+ info?: string
19
+ handleChangeAmount: (amount: number) => void
20
+ handleAction: () => void
21
+ }
22
+
23
+ export function InputAmountModal({
24
+ title,
25
+ subTitle,
26
+ actionText,
27
+ tokenSymbol,
28
+ suffix: defaultSuffix,
29
+ currentAmount,
30
+ maxAmount,
31
+ maxAmountText = 'MAX',
32
+ maxAmountTitle,
33
+ info,
34
+ handleChangeAmount,
35
+ handleAction,
36
+ }: Props): React.ReactElement | null {
37
+ const theme = useTheme()
38
+ const [inputTouched, setInputTouched] = useState(false)
39
+ const suffix = ` ${defaultSuffix ?? tokenSymbol}`
40
+
41
+ const styles = {
42
+ inputAmountWrapper: css`
43
+ margin-bottom: ${theme.spacing(1)};
44
+ margin-top: ${theme.spacing(16)};
45
+ `,
46
+ inputAmount: css`
47
+ ${theme.cssMixins.rowSpaceBetweened};
48
+ `,
49
+ inputField: css`
50
+ input {
51
+ width: 100%;
52
+ color: ${theme.palette.text.primary};
53
+ font-family: 'Uni-Neue-Black';
54
+ font-size: 40px;
55
+ line-height: 133.4%;
56
+ }
57
+ `,
58
+ maxWrapper: css`
59
+ position: relative;
60
+ display: flex;
61
+ justify-content: flex-end;
62
+ `,
63
+ maxTitle: css`
64
+ position: absolute;
65
+ color: ${theme.palette.text.primary};
66
+ font-family: 'Uni-Neue-Regular';
67
+ font-size: 12px;
68
+ line-height: 166%;
69
+ letter-spacing: 0.4px;
70
+ top: ${theme.spacing(-3)};
71
+ width: 200px;
72
+ text-align: right;
73
+ `,
74
+ max: css`
75
+ display: flex;
76
+ min-width: fit-content;
77
+ justify-content: center;
78
+ align-items: center;
79
+ border-radius: 32px;
80
+ background: #f7f1ff;
81
+ padding: 4px 10px;
82
+ gap: 8px;
83
+ color: #b246ff;
84
+ font-family: 'Uni-Neue-Bold';
85
+ font-size: 13px;
86
+ line-height: 22px;
87
+ letter-spacing: 0.46px;
88
+ `,
89
+ info: css`
90
+ color: ${theme.palette.text.primary};
91
+ font-family: 'Uni-Neue-Bold';
92
+ font-size: 20px;
93
+ line-height: 160%;
94
+ letter-spacing: 0.15px;
95
+ `,
96
+ }
97
+
98
+ const onChange = (
99
+ event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
100
+ ) => {
101
+ setInputTouched(true)
102
+ handleChangeAmount(
103
+ Number(event.target.value.replace(suffix, '').replaceAll(',', '')),
104
+ )
105
+ }
106
+
107
+ const setMaxAmount = () => {
108
+ handleChangeAmount(Number(maxAmount))
109
+ }
110
+
111
+ return (
112
+ <WrapperModal title={title} subTitle={subTitle}>
113
+ <Box css={styles.inputAmountWrapper}>
114
+ <Box css={styles.inputAmount}>
115
+ <NumericFormat
116
+ css={styles.inputField}
117
+ decimalScale={0}
118
+ onChange={onChange}
119
+ value={
120
+ !inputTouched && Number(currentAmount) === 0 ? '' : currentAmount
121
+ }
122
+ suffix={suffix}
123
+ thousandSeparator
124
+ customInput={TextField}
125
+ placeholder={`0${suffix}`}
126
+ variant='standard'
127
+ InputProps={{
128
+ endAdornment: maxAmountTitle ? (
129
+ <Box css={styles.maxWrapper}>
130
+ <Box css={styles.maxTitle}>{maxAmountTitle}</Box>
131
+ <Button css={styles.max} onClick={setMaxAmount}>
132
+ {maxAmountText}
133
+ </Button>
134
+ </Box>
135
+ ) : (
136
+ <Button css={styles.max} onClick={setMaxAmount}>
137
+ {maxAmountText}
138
+ </Button>
139
+ ),
140
+ }}
141
+ />
142
+ </Box>
143
+ </Box>
144
+
145
+ {info && <Box css={styles.info}>{info}</Box>}
146
+
147
+ <BottomButton
148
+ variant='contained'
149
+ onClick={handleAction}
150
+ disabled={Number(currentAmount) <= 0}
151
+ >
152
+ {actionText}
153
+ </BottomButton>
154
+ </WrapperModal>
155
+ )
156
+ }
@@ -2,6 +2,7 @@ import { AccountStats, PoolInfoType, useFeeManager } from '@huma-finance/shared'
2
2
  import React, { useCallback, useState } from 'react'
3
3
  import { ethers } from 'ethers'
4
4
 
5
+ import { useWeb3React } from '@web3-react/core'
5
6
  import { useAppDispatch, useAppSelector } from '../../../hooks/useRedux'
6
7
  import { setBorrowInfo } from '../../../store/widgets.reducers'
7
8
  import { selectWidgetState } from '../../../store/widgets.selectors'
@@ -19,10 +20,16 @@ export function ChooseAmount({
19
20
  }: Props): React.ReactElement | null {
20
21
  const dispatch = useAppDispatch()
21
22
  const { creditRecord } = accountStats
23
+ const { chainId, provider } = useWeb3React()
22
24
  const [chargedFees, setChargedFees] = useState(0)
23
25
  const [currentAmount, setCurrentAmount] = useState(0)
24
26
  const { approval } = useAppSelector(selectWidgetState)
25
- const { getFeesCharged } = useFeeManager(poolInfo.poolName, poolInfo.poolType)
27
+ const { getFeesCharged } = useFeeManager(
28
+ poolInfo.poolName,
29
+ poolInfo.poolType,
30
+ chainId,
31
+ provider,
32
+ )
26
33
  const [remainder, setRemainder] = useState<string | number | undefined>(
27
34
  approval!.receivable?.amountFormatted,
28
35
  )
@@ -23,10 +23,14 @@ type Props = {
23
23
 
24
24
  export function ApproveNFT({ poolInfo, tokenId }: Props): React.ReactElement {
25
25
  const dispatch = useAppDispatch()
26
- const { provider } = useWeb3React()
26
+ const { chainId, provider } = useWeb3React()
27
27
  const [{ state, txHash }, send] = useAtom(sendTxAtom)
28
28
  const reset = useResetAtom(txAtom)
29
- const invoiceNFTContract = useInvoiceNFTContract(poolInfo.poolName)
29
+ const invoiceNFTContract = useInvoiceNFTContract(
30
+ poolInfo.poolName,
31
+ chainId,
32
+ provider,
33
+ )
30
34
 
31
35
  useEffect(() => {
32
36
  if (state === TxStateType.Success) {
@@ -1,4 +1,6 @@
1
+ import { formatNumber } from '@huma-finance/shared'
1
2
  import React from 'react'
3
+
2
4
  import { useAppSelector } from '../../../hooks/useRedux'
3
5
  import { selectWidgetState } from '../../../store/widgets.selectors'
4
6
  import { TxDoneModal } from '../../TxDoneModal'
@@ -12,7 +14,9 @@ export function Success({ handleAction }: Props): React.ReactElement {
12
14
  useAppSelector(selectWidgetState)
13
15
 
14
16
  const content = [
15
- `${borrowAmountNet} ${approval?.token.symbol} is now in your wallet.`,
17
+ `${formatNumber(borrowAmountNet)} ${
18
+ approval?.token.symbol
19
+ } is now in your wallet.`,
16
20
  `The remaining ${remainder} ${approval?.token.symbol} will be sent to your wallet when the invoice is paid.`,
17
21
  ]
18
22
 
@@ -47,12 +47,18 @@ export function InvoiceFactoringBorrow({
47
47
  handleSuccess,
48
48
  }: InvoiceFactoringBorrowProps): React.ReactElement | null {
49
49
  const dispatch = useDispatch()
50
- const { account } = useWeb3React()
50
+ const { account, chainId, provider } = useWeb3React()
51
51
  const poolName = POOL_NAME[poolNameStr]
52
52
  const poolType = POOL_TYPE[poolTypeStr]
53
- const poolInfo = usePoolInfo(poolName, poolType)
53
+ const poolInfo = usePoolInfo(poolName, poolType, chainId)
54
54
  const { step, errorMessage } = useAppSelector(selectWidgetState)
55
- const [accountStats] = useAccountStats(poolName, poolType, account)
55
+ const [accountStats] = useAccountStats(
56
+ poolName,
57
+ poolType,
58
+ chainId,
59
+ account,
60
+ provider,
61
+ )
56
62
 
57
63
  useEffect(() => {
58
64
  dispatch(setStep(WIDGET_STEP.Evaluation))
@@ -23,10 +23,15 @@ export function ChooseAmount({
23
23
  poolInfo,
24
24
  }: Props): React.ReactElement | null {
25
25
  const dispatch = useAppDispatch()
26
- const { account } = useWeb3React()
26
+ const { account, chainId, provider } = useWeb3React()
27
27
  const { symbol, decimals } = poolInfo.poolUnderlyingToken
28
28
  const totalDue = downScale<number>(creditRecord.totalDue.toNumber(), decimals)
29
- const { allowance } = useRFPoolAllowance(poolInfo.poolName, account)
29
+ const { allowance } = useRFPoolAllowance(
30
+ poolInfo.poolName,
31
+ chainId,
32
+ account,
33
+ provider,
34
+ )
30
35
  const [remainingDue, setRemainingDue] = useState(totalDue)
31
36
  const [currentAmount, setCurrentAmount] = useState(0)
32
37
 
@@ -41,12 +41,18 @@ export function InvoiceFactoringPayment({
41
41
  handleSuccess,
42
42
  }: InvoiceFactoringPaymentProps): React.ReactElement | null {
43
43
  const dispatch = useDispatch()
44
- const { account } = useWeb3React()
44
+ const { account, chainId, provider } = useWeb3React()
45
45
  const poolName = POOL_NAME[poolNameStr]
46
46
  const poolType = POOL_TYPE[poolTypeStr]
47
- const poolInfo = usePoolInfo(poolName, poolType)
47
+ const poolInfo = usePoolInfo(poolName, poolType, chainId)
48
48
  const { step, errorMessage } = useAppSelector(selectWidgetState)
49
- const [{ creditRecord }] = useAccountStats(poolName, poolType, account)
49
+ const [{ creditRecord }] = useAccountStats(
50
+ poolName,
51
+ poolType,
52
+ chainId,
53
+ account,
54
+ provider,
55
+ )
50
56
 
51
57
  useEffect(() => {
52
58
  dispatch(setStep(WIDGET_STEP.ChooseAmount))
@@ -0,0 +1,114 @@
1
+ import { TrancheType } from '@huma-finance/shared'
2
+ import {
3
+ css,
4
+ FormControl,
5
+ FormControlLabel,
6
+ FormLabel,
7
+ Radio,
8
+ RadioGroup,
9
+ useTheme,
10
+ } from '@mui/material'
11
+ import React from 'react'
12
+
13
+ import { useAppDispatch } from '../../../hooks/useRedux'
14
+ import { setStep } from '../../../store/widgets.reducers'
15
+ import { WIDGET_STEP } from '../../../store/widgets.store'
16
+ import { BottomButton } from '../../BottomButton'
17
+ import { WrapperModal } from '../../WrapperModal'
18
+
19
+ type Props = {
20
+ selectedTranche: TrancheType | undefined
21
+ changeTranche: (tranche: TrancheType) => void
22
+ }
23
+
24
+ export function ChooseTranche({
25
+ selectedTranche,
26
+ changeTranche,
27
+ }: Props): React.ReactElement | null {
28
+ const theme = useTheme()
29
+ const dispatch = useAppDispatch()
30
+
31
+ const styles = {
32
+ subTitle: css`
33
+ color: ${theme.palette.text.primary} !important;
34
+ font-family: 'Uni-Neue-Regular';
35
+ font-size: 16px;
36
+ line-height: 150%;
37
+ letter-spacing: 0.15px;
38
+ margin-top: ${theme.spacing(5)};
39
+ margin-left: ${theme.spacing(2)};
40
+ `,
41
+ radioGroup: css`
42
+ margin-left: ${theme.spacing(3)};
43
+ margin-top: ${theme.spacing(3)};
44
+ `,
45
+ formControl: css`
46
+ margin-bottom: ${theme.spacing(1)};
47
+
48
+ .MuiFormControlLabel-label {
49
+ color: ${theme.palette.text.primary};
50
+ font-family: 'Uni-Neue-Regular';
51
+ font-size: 16px;
52
+ line-height: 150%;
53
+ letter-spacing: 0.15px;
54
+ }
55
+ `,
56
+ }
57
+
58
+ const handleNext = () => {
59
+ dispatch(setStep(WIDGET_STEP.ChooseAmount))
60
+ }
61
+
62
+ const items: {
63
+ label: string
64
+ value: TrancheType
65
+ }[] = [
66
+ {
67
+ label: 'Senior',
68
+ value: 'senior',
69
+ },
70
+ {
71
+ label: 'Junior',
72
+ value: 'junior',
73
+ },
74
+ ]
75
+
76
+ return (
77
+ <WrapperModal title='Redemption'>
78
+ <FormControl>
79
+ <FormLabel css={styles.subTitle}>Select Tranche Type</FormLabel>
80
+ <RadioGroup
81
+ aria-labelledby='buttons-group-label'
82
+ name='radio-buttons-group'
83
+ css={styles.radioGroup}
84
+ onChange={(e) => changeTranche(e.target.value as TrancheType)}
85
+ >
86
+ {items.map((item) => (
87
+ <FormControlLabel
88
+ key={item.label}
89
+ value={item.value}
90
+ control={
91
+ <Radio
92
+ sx={{
93
+ '& .MuiSvgIcon-root': {
94
+ fontSize: 24,
95
+ },
96
+ }}
97
+ />
98
+ }
99
+ label={item.label}
100
+ css={styles.formControl}
101
+ />
102
+ ))}
103
+ </RadioGroup>
104
+ </FormControl>
105
+ <BottomButton
106
+ variant='contained'
107
+ disabled={!selectedTranche}
108
+ onClick={handleNext}
109
+ >
110
+ NEXT
111
+ </BottomButton>
112
+ </WrapperModal>
113
+ )
114
+ }
@@ -0,0 +1,114 @@
1
+ import {
2
+ formatNumber,
3
+ PoolInfoV2,
4
+ timestampToLL,
5
+ UnderlyingTokenInfo,
6
+ useLenderDepositRecordV2,
7
+ useLPConfigV2,
8
+ useNextEpochStartTimeV2,
9
+ } from '@huma-finance/shared'
10
+ import { ethers } from 'ethers'
11
+ import React, { useEffect, useState } from 'react'
12
+
13
+ import { useWeb3React } from '@web3-react/core'
14
+ import { TrancheInfo } from '.'
15
+ import { useAppDispatch } from '../../../hooks/useRedux'
16
+ import {
17
+ setError,
18
+ setRedeemAmount,
19
+ setRedeemShares,
20
+ setStep,
21
+ } from '../../../store/widgets.reducers'
22
+ import { WIDGET_STEP } from '../../../store/widgets.store'
23
+ import { InputAmountModal } from '../../InputAmountModal'
24
+ import { LoadingModal } from '../../LoadingModal'
25
+
26
+ type Props = {
27
+ poolInfo: PoolInfoV2
28
+ poolUnderlyingToken: UnderlyingTokenInfo
29
+ trancheInfo: TrancheInfo
30
+ }
31
+
32
+ export function ChooseAmount({
33
+ poolInfo,
34
+ poolUnderlyingToken,
35
+ trancheInfo,
36
+ }: Props): React.ReactElement | null {
37
+ const dispatch = useAppDispatch()
38
+ const { symbol } = poolUnderlyingToken
39
+ const { account, provider } = useWeb3React()
40
+ const [currentAmount, setCurrentAmount] = useState<number>(0)
41
+ const [currentShares, setCurrentShares] = useState<number>(0)
42
+ const maxSharesFormatted = ethers.utils.formatUnits(
43
+ trancheInfo.shares,
44
+ poolUnderlyingToken.decimals,
45
+ )
46
+ const sharePrice =
47
+ trancheInfo.assets.toNumber() / trancheInfo.shares.toNumber()
48
+ const [depositRecord] = useLenderDepositRecordV2(
49
+ poolInfo.poolName,
50
+ trancheInfo.tranche,
51
+ account,
52
+ provider,
53
+ )
54
+ const lpConfig = useLPConfigV2(poolInfo.poolName, provider)
55
+ const nextEpochStartTime = useNextEpochStartTimeV2(
56
+ poolInfo.poolName,
57
+ provider,
58
+ )
59
+
60
+ useEffect(() => {
61
+ if (depositRecord && lpConfig && nextEpochStartTime) {
62
+ const SECONDS_IN_A_DAY = 24 * 60 * 60
63
+ if (
64
+ nextEpochStartTime <
65
+ depositRecord.lastDepositTime.toNumber() +
66
+ lpConfig.withdrawalLockoutPeriodInDays * SECONDS_IN_A_DAY
67
+ ) {
68
+ dispatch(setStep(WIDGET_STEP.Error))
69
+ dispatch(
70
+ setError({
71
+ errorReason: 'Redemption too soon',
72
+ errorMessage: `Your last deposit was on ${timestampToLL(
73
+ depositRecord!.lastDepositTime.toNumber(),
74
+ )}. Depositors need to wait ${
75
+ lpConfig!.withdrawalLockoutPeriodInDays
76
+ } days before redemption`,
77
+ }),
78
+ )
79
+ }
80
+ }
81
+ }, [depositRecord, dispatch, lpConfig, nextEpochStartTime])
82
+
83
+ const handleChangeShares = (newShares: number) => {
84
+ const amount = Number(newShares) * sharePrice
85
+ setCurrentShares(Number(newShares))
86
+ setCurrentAmount(amount)
87
+ dispatch(setRedeemShares(Number(newShares)))
88
+ dispatch(setRedeemAmount(amount))
89
+ }
90
+
91
+ const handleAction = () => {
92
+ dispatch(setStep(WIDGET_STEP.Transfer))
93
+ }
94
+
95
+ if (!depositRecord || !lpConfig || !nextEpochStartTime) {
96
+ return <LoadingModal title='Redemption' />
97
+ }
98
+
99
+ return (
100
+ <InputAmountModal
101
+ title='Redemption'
102
+ subTitle={`Enter number of shares to redeem from ${trancheInfo.tranche} tranche`}
103
+ tokenSymbol={symbol}
104
+ currentAmount={currentShares}
105
+ handleChangeAmount={handleChangeShares}
106
+ maxAmount={maxSharesFormatted}
107
+ info={`${String(formatNumber(currentAmount))} ${symbol}`}
108
+ maxAmountTitle={`${formatNumber(maxSharesFormatted)} Shares`}
109
+ suffix='Shares'
110
+ handleAction={handleAction}
111
+ actionText='REQUEST'
112
+ />
113
+ )
114
+ }