@huma-finance/widgets 0.0.48-beta.200 → 0.0.48-beta.279

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 (91) hide show
  1. package/API.md +407 -0
  2. package/dist/cjs/index.cjs +6063 -3827
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/index.d.ts +248 -1
  5. package/dist/index.js +6056 -3829
  6. package/dist/index.js.map +1 -1
  7. package/package.json +5 -4
  8. package/src/components/ApproveAllowanceModal.tsx +3 -8
  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/index.tsx +4 -2
  16. package/src/components/CreditLine/borrowV2/1-ChooseAmount.tsx +79 -0
  17. package/src/components/CreditLine/borrowV2/2-ApproveAllowance.tsx +33 -0
  18. package/src/components/CreditLine/borrowV2/3-Transfer.tsx +50 -0
  19. package/src/components/CreditLine/borrowV2/4-Success.tsx +41 -0
  20. package/src/components/CreditLine/borrowV2/5-Notifications.tsx +10 -0
  21. package/src/components/CreditLine/borrowV2/index.tsx +140 -0
  22. package/src/components/CreditLine/payment/1-ChooseAmount.tsx +7 -2
  23. package/src/components/CreditLine/payment/index.tsx +4 -2
  24. package/src/components/CreditLine/paymentV2/1-ChooseAmount.tsx +86 -0
  25. package/src/components/CreditLine/paymentV2/2-ApproveAllowance.tsx +33 -0
  26. package/src/components/CreditLine/paymentV2/3-Transfer.tsx +55 -0
  27. package/src/components/CreditLine/paymentV2/4-Success.tsx +42 -0
  28. package/src/components/CreditLine/paymentV2/index.tsx +111 -0
  29. package/src/components/CreditLine/supplyFLC/1-ApproveAllowance.tsx +40 -0
  30. package/src/components/CreditLine/supplyFLC/2-Transfer.tsx +53 -0
  31. package/src/components/CreditLine/supplyFLC/3-Success.tsx +26 -0
  32. package/src/components/CreditLine/supplyFLC/index.tsx +121 -0
  33. package/src/components/Factoring/FactoredList.tsx +2 -1
  34. package/src/components/InvoiceFactoring/borrow/2-ChooseAmount.tsx +8 -1
  35. package/src/components/InvoiceFactoring/borrow/4-ApproveNFT.tsx +6 -2
  36. package/src/components/InvoiceFactoring/borrow/index.tsx +9 -3
  37. package/src/components/InvoiceFactoring/payment/1-ChooseAmount.tsx +7 -2
  38. package/src/components/InvoiceFactoring/payment/index.tsx +9 -3
  39. package/src/components/Lend/redeemV2/1-ChooseAction.tsx +236 -0
  40. package/src/components/Lend/redeemV2/2-ChooseAmount.tsx +162 -0
  41. package/src/components/Lend/redeemV2/3-Transfer.tsx +61 -0
  42. package/src/components/Lend/redeemV2/4-Done.tsx +33 -0
  43. package/src/components/Lend/redeemV2/index.tsx +207 -0
  44. package/src/components/Lend/supply/1-Evaluation/EvaluationKYC.tsx +19 -2
  45. package/src/components/Lend/supply/index.tsx +17 -3
  46. package/src/components/Lend/supplyV2/1-ChooseTranche.tsx +155 -0
  47. package/src/components/Lend/supplyV2/2-Evaluation.tsx +345 -0
  48. package/src/components/Lend/supplyV2/3-ChooseAmount.tsx +122 -0
  49. package/src/components/Lend/supplyV2/4-ApproveAllowance.tsx +33 -0
  50. package/src/components/Lend/supplyV2/5-Transfer.tsx +59 -0
  51. package/src/components/Lend/supplyV2/6-Success.tsx +79 -0
  52. package/src/components/Lend/supplyV2/7-Notifications.tsx +10 -0
  53. package/src/components/Lend/supplyV2/index.tsx +127 -0
  54. package/src/components/Lend/withdraw/1-CheckWithdrawble.tsx +5 -1
  55. package/src/components/Lend/withdraw/2-ChooseAmount.tsx +1 -7
  56. package/src/components/Lend/withdraw/index.tsx +8 -13
  57. package/src/components/Lend/withdrawV2/1-ChooseTranche.tsx +201 -0
  58. package/src/components/Lend/withdrawV2/2-Transfer.tsx +48 -0
  59. package/src/components/Lend/withdrawV2/3-Done.tsx +31 -0
  60. package/src/components/Lend/withdrawV2/index.tsx +129 -0
  61. package/src/components/Notifi/NotifiSubscriptionModal.tsx +29 -37
  62. package/src/components/NumericFormatCustom.tsx +31 -0
  63. package/src/components/ReceivableBackedCreditLine/borrow/1-ChooseAmount.tsx +101 -0
  64. package/src/components/ReceivableBackedCreditLine/borrow/2-ApproveAllowance.tsx +33 -0
  65. package/src/components/ReceivableBackedCreditLine/borrow/3-ApproveReceivable.tsx +64 -0
  66. package/src/components/ReceivableBackedCreditLine/borrow/4-Transfer.tsx +61 -0
  67. package/src/components/ReceivableBackedCreditLine/borrow/5-Success.tsx +41 -0
  68. package/src/components/ReceivableBackedCreditLine/borrow/6-Notifications.tsx +10 -0
  69. package/src/components/ReceivableBackedCreditLine/borrow/index.tsx +148 -0
  70. package/src/components/ReceivableBackedCreditLine/payment/1-ChoosePaymentType.tsx +115 -0
  71. package/src/components/ReceivableBackedCreditLine/payment/2-ChooseAmount.tsx +84 -0
  72. package/src/components/ReceivableBackedCreditLine/payment/3-ApproveAllowance.tsx +41 -0
  73. package/src/components/ReceivableBackedCreditLine/payment/4-CreateReceivable.tsx +107 -0
  74. package/src/components/ReceivableBackedCreditLine/payment/5-ApproveReceivable.tsx +64 -0
  75. package/src/components/ReceivableBackedCreditLine/payment/6-Transfer.tsx +107 -0
  76. package/src/components/ReceivableBackedCreditLine/payment/7-Success.tsx +49 -0
  77. package/src/components/ReceivableBackedCreditLine/payment/index.tsx +159 -0
  78. package/src/components/StreamFactoring/borrow/1-Evaluation.tsx +3 -4
  79. package/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx +23 -22
  80. package/src/components/StreamFactoring/borrow/3-ConfirmTransfer.tsx +8 -3
  81. package/src/components/StreamFactoring/borrow/5-Permit.tsx +35 -2
  82. package/src/components/StreamFactoring/borrow/6-Transfer.tsx +3 -1
  83. package/src/components/StreamFactoring/borrow/index.tsx +4 -3
  84. package/src/components/SuperfluidFactoring/SuperfluidFactoredList.tsx +2 -2
  85. package/src/components/SuperfluidFactoring/SuperfluidUpcomingList.tsx +1 -3
  86. package/src/components/TxDoneModal.tsx +1 -1
  87. package/src/components/TxSendModal.tsx +8 -2
  88. package/src/components/TxSendModalV2.tsx +51 -0
  89. package/src/index.tsx +239 -1
  90. package/src/store/widgets.reducers.ts +15 -0
  91. package/src/store/widgets.store.ts +6 -0
@@ -0,0 +1,121 @@
1
+ import {
2
+ FirstLossCoverIndex,
3
+ POOL_NAME,
4
+ useFirstLossCoverAllowanceV2,
5
+ useFirstLossCoverRequirement,
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] = useFirstLossCoverRequirement(
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
@@ -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) {
@@ -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,236 @@
1
+ import {
2
+ PoolInfoV2,
3
+ timestampToLL,
4
+ UnderlyingTokenInfo,
5
+ useLenderDepositRecordV2,
6
+ useLPConfigV2,
7
+ useNextEpochStartTimeV2,
8
+ } from '@huma-finance/shared'
9
+ import {
10
+ Box,
11
+ css,
12
+ FormControl,
13
+ FormControlLabel,
14
+ FormLabel,
15
+ Radio,
16
+ RadioGroup,
17
+ useTheme,
18
+ } from '@mui/material'
19
+ import { useWeb3React } from '@web3-react/core'
20
+ import { BigNumber, ethers } from 'ethers'
21
+ import React from 'react'
22
+
23
+ import { REDEMPTION_TYPE, RedemptionInfo } from '.'
24
+ import { useAppDispatch } from '../../../hooks/useRedux'
25
+ import { setError, setStep } from '../../../store/widgets.reducers'
26
+ import { WIDGET_STEP } from '../../../store/widgets.store'
27
+ import { BottomButton } from '../../BottomButton'
28
+ import { LoadingModal } from '../../LoadingModal'
29
+ import { WrapperModal } from '../../WrapperModal'
30
+
31
+ type Props = {
32
+ poolInfo: PoolInfoV2
33
+ poolUnderlyingToken: UnderlyingTokenInfo
34
+ seniorRedemptionInfo: RedemptionInfo | undefined
35
+ juniorRedemptionInfo: RedemptionInfo | undefined
36
+ redemptionType: REDEMPTION_TYPE | undefined
37
+ seniorPosition: BigNumber | undefined
38
+ juniorPosition: BigNumber | undefined
39
+ changeRedemptionType: (tranche: REDEMPTION_TYPE) => void
40
+ }
41
+
42
+ export function ChooseAction({
43
+ poolInfo,
44
+ poolUnderlyingToken,
45
+ seniorRedemptionInfo,
46
+ juniorRedemptionInfo,
47
+ redemptionType,
48
+ seniorPosition,
49
+ juniorPosition,
50
+ changeRedemptionType,
51
+ }: Props): React.ReactElement | null {
52
+ const theme = useTheme()
53
+ const dispatch = useAppDispatch()
54
+ const { symbol } = poolUnderlyingToken
55
+ const { account, provider } = useWeb3React()
56
+ const [seniorDepositRecord] = useLenderDepositRecordV2(
57
+ poolInfo.poolName,
58
+ 'senior',
59
+ account,
60
+ provider,
61
+ )
62
+ const [juniorDepositRecord] = useLenderDepositRecordV2(
63
+ poolInfo.poolName,
64
+ 'junior',
65
+ account,
66
+ provider,
67
+ )
68
+ const lpConfig = useLPConfigV2(poolInfo.poolName, provider)
69
+ const nextEpochStartTime = useNextEpochStartTimeV2(
70
+ poolInfo.poolName,
71
+ provider,
72
+ )
73
+
74
+ const isLoading =
75
+ seniorRedemptionInfo === undefined ||
76
+ juniorRedemptionInfo === undefined ||
77
+ seniorDepositRecord === undefined ||
78
+ juniorDepositRecord === undefined ||
79
+ lpConfig === undefined ||
80
+ nextEpochStartTime === undefined
81
+
82
+ const styles = {
83
+ subTitle: css`
84
+ color: ${theme.palette.text.primary} !important;
85
+ font-family: 'Uni-Neue-Regular';
86
+ font-size: 16px;
87
+ line-height: 150%;
88
+ letter-spacing: 0.15px;
89
+ margin-top: ${theme.spacing(5)};
90
+ margin-left: ${theme.spacing(2)};
91
+ `,
92
+ radioGroup: css`
93
+ margin-left: ${theme.spacing(3)};
94
+ margin-top: ${theme.spacing(3)};
95
+ `,
96
+ formControl: css`
97
+ margin-bottom: ${theme.spacing(1)};
98
+
99
+ .MuiFormControlLabel-label {
100
+ color: ${theme.palette.text.primary};
101
+ font-family: 'Uni-Neue-Regular';
102
+ font-size: 16px;
103
+ line-height: 150%;
104
+ letter-spacing: 0.15px;
105
+ }
106
+ `,
107
+ }
108
+
109
+ const handleNext = () => {
110
+ if (isLoading) {
111
+ return
112
+ }
113
+
114
+ const depositRecord =
115
+ redemptionType === REDEMPTION_TYPE.AddSeniorRedemption
116
+ ? seniorDepositRecord
117
+ : juniorDepositRecord
118
+
119
+ const SECONDS_IN_A_DAY = 24 * 60 * 60
120
+ if (
121
+ nextEpochStartTime <
122
+ depositRecord.lastDepositTime.toNumber() +
123
+ lpConfig.withdrawalLockoutPeriodInDays * SECONDS_IN_A_DAY
124
+ ) {
125
+ dispatch(setStep(WIDGET_STEP.Error))
126
+ dispatch(
127
+ setError({
128
+ errorReason: 'Redemption request too soon',
129
+ errorMessage: `Your last deposit was on ${timestampToLL(
130
+ depositRecord.lastDepositTime.toNumber(),
131
+ )}. Depositors need to wait ${
132
+ lpConfig.withdrawalLockoutPeriodInDays
133
+ } days before redemption request`,
134
+ }),
135
+ )
136
+ return
137
+ }
138
+ dispatch(setStep(WIDGET_STEP.ChooseAmount))
139
+ }
140
+
141
+ const formatAmount = (amount?: BigNumber) => {
142
+ if (!amount || amount.lte(0)) {
143
+ return undefined
144
+ }
145
+ return ethers.utils.formatUnits(amount, poolUnderlyingToken.decimals)
146
+ }
147
+
148
+ const items: {
149
+ label: string
150
+ value: REDEMPTION_TYPE
151
+ amount?: string
152
+ show: boolean
153
+ }[] = [
154
+ {
155
+ label: 'Request Senior Tranche Redemption',
156
+ value: REDEMPTION_TYPE.AddSeniorRedemption,
157
+ show: seniorPosition?.gt(0) ?? false,
158
+ },
159
+ {
160
+ label: 'Cancel Senior Tranche Redemption',
161
+ value: REDEMPTION_TYPE.CancelSeniorRedemption,
162
+ amount: formatAmount(seniorRedemptionInfo?.amount),
163
+ show: seniorRedemptionInfo?.amount.gt(0) ?? false,
164
+ },
165
+ {
166
+ label: 'Request Junior Tranche Redemption',
167
+ value: REDEMPTION_TYPE.AddJuniorRedemption,
168
+ show: juniorPosition?.gt(0) ?? false,
169
+ },
170
+ {
171
+ label: 'Cancel Junior Tranche Redemption',
172
+ value: REDEMPTION_TYPE.CancelJuniorRedemption,
173
+ amount: formatAmount(juniorRedemptionInfo?.amount),
174
+ show: juniorRedemptionInfo?.amount.gt(0) ?? false,
175
+ },
176
+ ]
177
+
178
+ if (isLoading) {
179
+ return <LoadingModal title={`Redeem ${symbol}`} />
180
+ }
181
+
182
+ return (
183
+ <WrapperModal title={`Redeem ${symbol}`}>
184
+ <FormControl>
185
+ <FormLabel css={styles.subTitle}>Select Redemption Type</FormLabel>
186
+ <RadioGroup
187
+ aria-labelledby='buttons-group-label'
188
+ name='radio-buttons-group'
189
+ css={styles.radioGroup}
190
+ onChange={(e) => changeRedemptionType(Number(e.target.value))}
191
+ >
192
+ {items
193
+ .filter((item) => item.show)
194
+ .map((item) => {
195
+ const { label } = item
196
+ let labelNode = <Box>{label}</Box>
197
+ if (item.amount) {
198
+ labelNode = (
199
+ <>
200
+ <Box>{label}</Box>
201
+ <Box>
202
+ ({item.amount} {symbol} available)
203
+ </Box>
204
+ </>
205
+ )
206
+ }
207
+ return (
208
+ <FormControlLabel
209
+ key={item.label}
210
+ value={item.value}
211
+ control={
212
+ <Radio
213
+ sx={{
214
+ '& .MuiSvgIcon-root': {
215
+ fontSize: 24,
216
+ },
217
+ }}
218
+ />
219
+ }
220
+ label={labelNode}
221
+ css={styles.formControl}
222
+ />
223
+ )
224
+ })}
225
+ </RadioGroup>
226
+ </FormControl>
227
+ <BottomButton
228
+ variant='contained'
229
+ disabled={redemptionType === undefined}
230
+ onClick={handleNext}
231
+ >
232
+ NEXT
233
+ </BottomButton>
234
+ </WrapperModal>
235
+ )
236
+ }
@@ -0,0 +1,162 @@
1
+ import {
2
+ formatMoney,
3
+ getTrancheVaultContractV2,
4
+ PoolInfoV2,
5
+ UnderlyingTokenInfo,
6
+ } from '@huma-finance/shared'
7
+ import { Box, css, Slider, useTheme } from '@mui/material'
8
+ import { useWeb3React } from '@web3-react/core'
9
+ import { BigNumber, ethers } from 'ethers'
10
+ import React, { useEffect, useState } from 'react'
11
+
12
+ import { REDEMPTION_TYPE, RedemptionActionInfo } from '.'
13
+ import { useAppDispatch } from '../../../hooks/useRedux'
14
+ import {
15
+ setRedeemAmount,
16
+ setRedeemShares,
17
+ setStep,
18
+ } from '../../../store/widgets.reducers'
19
+ import { WIDGET_STEP } from '../../../store/widgets.store'
20
+ import { BottomButton } from '../../BottomButton'
21
+ import { LoadingModal } from '../../LoadingModal'
22
+ import { WrapperModal } from '../../WrapperModal'
23
+
24
+ type Props = {
25
+ poolInfo: PoolInfoV2
26
+ poolUnderlyingToken: UnderlyingTokenInfo
27
+ redemptionType: REDEMPTION_TYPE
28
+ maxAmount: BigNumber
29
+ }
30
+
31
+ export function ChooseAmount({
32
+ poolInfo,
33
+ poolUnderlyingToken,
34
+ redemptionType,
35
+ maxAmount,
36
+ }: Props): React.ReactElement | null {
37
+ const theme = useTheme()
38
+ const dispatch = useAppDispatch()
39
+ const { provider } = useWeb3React()
40
+ const { symbol } = poolUnderlyingToken
41
+ const [sharePrice, setSharePrice] = useState(0)
42
+ const [currentAmount, setCurrentAmount] = useState<number>(0)
43
+ const [currentShares, setCurrentShares] = useState<number>(0)
44
+ const redemptionActionInfo = RedemptionActionInfo[redemptionType]
45
+ const maxAmountFormatted = ethers.utils.formatUnits(
46
+ maxAmount,
47
+ poolUnderlyingToken.decimals,
48
+ )
49
+
50
+ useEffect(() => {
51
+ if (maxAmount.gt(0)) {
52
+ const fetchData = async () => {
53
+ const vaultContract = await getTrancheVaultContractV2(
54
+ poolInfo.poolName,
55
+ redemptionActionInfo.tranche,
56
+ provider,
57
+ )
58
+ if (vaultContract) {
59
+ const shares = await vaultContract.convertToShares(maxAmount)
60
+ const price = maxAmount.div(shares)
61
+ setSharePrice(price.toNumber())
62
+ }
63
+ }
64
+ fetchData()
65
+ }
66
+ }, [maxAmount, poolInfo.poolName, provider, redemptionActionInfo.tranche])
67
+
68
+ const styles = {
69
+ sliderWrapper: css`
70
+ margin-bottom: ${theme.spacing(1)};
71
+ margin-top: ${theme.spacing(14)};
72
+ `,
73
+ currentAmount: css`
74
+ font-size: 32px;
75
+ font-family: 'Uni-Neue-Bold';
76
+ text-align: center;
77
+ background: linear-gradient(233deg, #b246ff 4.17%, #ff6a8a 178.69%);
78
+ background-clip: text;
79
+ -webkit-background-clip: text;
80
+ -webkit-text-fill-color: transparent;
81
+ `,
82
+ slider: css`
83
+ &.MuiSlider-root {
84
+ height: 8px !important;
85
+ color: #e9e9e9;
86
+ }
87
+ & .MuiSlider-track {
88
+ height: 8px !important;
89
+ background: linear-gradient(232.71deg, #a363f4 4.17%, #ff6a8a 178.69%);
90
+ border-radius: 8px;
91
+ }
92
+ & .MuiSlider-thumb::before {
93
+ background: #ffffff;
94
+ border: 1px solid #f9f9f9;
95
+ box-shadow: 1px 1px 12px 2px rgba(163, 100, 244, 0.6);
96
+ border-radius: 50px;
97
+ width: 24px;
98
+ height: 24px;
99
+ }
100
+ `,
101
+ shares: css`
102
+ color: ${theme.palette.text.primary};
103
+ font-family: 'Uni-Neue-Bold';
104
+ font-size: 20px;
105
+ line-height: 160%;
106
+ letter-spacing: 0.15px;
107
+ `,
108
+ }
109
+
110
+ const handleChangeAmount = (event: Event, newAmount: number | number[]) => {
111
+ const shares = Number(newAmount) / sharePrice
112
+ setCurrentShares(shares)
113
+ setCurrentAmount(Number(newAmount))
114
+ dispatch(setRedeemAmount(Number(newAmount)))
115
+ dispatch(setRedeemShares(shares))
116
+ }
117
+
118
+ const handleAction = () => {
119
+ dispatch(setStep(WIDGET_STEP.Transfer))
120
+ }
121
+
122
+ if (sharePrice === 0) {
123
+ return (
124
+ <LoadingModal
125
+ title={`${redemptionActionInfo.action} Redemption Request`}
126
+ />
127
+ )
128
+ }
129
+
130
+ return (
131
+ <WrapperModal
132
+ title={redemptionActionInfo.action}
133
+ subTitle={
134
+ redemptionActionInfo.action === 'Create'
135
+ ? `Select ${symbol} amount to redeem from ${redemptionActionInfo.tranche} tranche`
136
+ : `Cancel ${symbol} amount from ${redemptionActionInfo.tranche} tranche redemption request`
137
+ }
138
+ >
139
+ <Box css={styles.sliderWrapper}>
140
+ <Box css={styles.currentAmount}>
141
+ {formatMoney(currentAmount)} {poolUnderlyingToken.symbol}
142
+ </Box>
143
+ <Slider
144
+ max={Number(maxAmountFormatted)}
145
+ min={0}
146
+ css={styles.slider}
147
+ aria-label='Amount'
148
+ value={currentAmount}
149
+ onChange={handleChangeAmount}
150
+ />
151
+ <Box css={styles.shares}>{currentShares.toFixed(1)} Shares</Box>
152
+ </Box>
153
+ <BottomButton
154
+ variant='contained'
155
+ onClick={handleAction}
156
+ disabled={Number(currentAmount) <= 0}
157
+ >
158
+ SUBMIT
159
+ </BottomButton>
160
+ </WrapperModal>
161
+ )
162
+ }
@@ -0,0 +1,61 @@
1
+ import {
2
+ PoolInfoV2,
3
+ UnderlyingTokenInfo,
4
+ useTrancheVaultContractV2,
5
+ } from '@huma-finance/shared'
6
+ import { useWeb3React } from '@web3-react/core'
7
+ import React, { useCallback } from 'react'
8
+
9
+ import { ethers } from 'ethers'
10
+ import { REDEMPTION_TYPE, RedemptionActionInfo } from '.'
11
+ import { useAppDispatch, useAppSelector } from '../../../hooks/useRedux'
12
+ import { setStep } from '../../../store/widgets.reducers'
13
+ import { selectWidgetState } from '../../../store/widgets.selectors'
14
+ import { WIDGET_STEP } from '../../../store/widgets.store'
15
+ import { TxSendModalV2 } from '../../TxSendModalV2'
16
+
17
+ type Props = {
18
+ poolInfo: PoolInfoV2
19
+ poolUnderlyingToken: UnderlyingTokenInfo
20
+ redemptionType: REDEMPTION_TYPE
21
+ }
22
+
23
+ export function Transfer({
24
+ poolInfo,
25
+ poolUnderlyingToken,
26
+ redemptionType,
27
+ }: Props): React.ReactElement | null {
28
+ const dispatch = useAppDispatch()
29
+ const { decimals } = poolUnderlyingToken
30
+ const { account, provider } = useWeb3React()
31
+ const { redeemShares } = useAppSelector(selectWidgetState)
32
+ const redemptionActionInfo = RedemptionActionInfo[redemptionType]
33
+ const trancheVaultContract = useTrancheVaultContractV2(
34
+ poolInfo.poolName,
35
+ redemptionActionInfo.tranche,
36
+ provider,
37
+ account,
38
+ )
39
+ const redeemSharesBN = ethers.utils.parseUnits(String(redeemShares), decimals)
40
+ const method =
41
+ redemptionActionInfo.action === 'Create'
42
+ ? 'addRedemptionRequest'
43
+ : 'cancelRedemptionRequest'
44
+
45
+ const handleSuccess = useCallback(() => {
46
+ dispatch(setStep(WIDGET_STEP.Done))
47
+ }, [dispatch])
48
+
49
+ if (!trancheVaultContract || !account) {
50
+ return null
51
+ }
52
+
53
+ return (
54
+ <TxSendModalV2
55
+ contract={trancheVaultContract}
56
+ method={method}
57
+ params={[redeemSharesBN]}
58
+ handleSuccess={handleSuccess}
59
+ />
60
+ )
61
+ }