@huma-finance/widgets 0.0.62-beta.719 → 0.0.62-beta.721
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.
- package/API.md +41 -3
- package/dist/cjs/index.cjs +777 -316
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.d.ts +37 -11
- package/dist/index.js +780 -320
- package/dist/index.js.map +1 -1
- package/package.json +7 -9
- package/src/components/Lend/solanaEnableAutoRedemption/1-ApproveAllowance.tsx +6 -8
- package/src/components/Lend/solanaSupply/3-ChooseAmount.tsx +1 -1
- package/src/components/Lend/solanaSupply/4-Transfer.tsx +12 -13
- package/src/components/Lend/stellarSupply/1-Evaluation.tsx +9 -0
- package/src/components/Lend/stellarSupply/2-ChooseTranche.tsx +116 -0
- package/src/components/Lend/stellarSupply/3-ChooseAmount.tsx +129 -0
- package/src/components/Lend/stellarSupply/4-Transfer.tsx +69 -0
- package/src/components/Lend/stellarSupply/5-Success.tsx +61 -0
- package/src/components/Lend/stellarSupply/index.tsx +159 -0
- package/src/components/Lend/supplyV2/3-ChooseAmount.tsx +1 -1
- package/src/components/StellarTxDoneModal.tsx +119 -0
- package/src/components/StellarTxSendModal.tsx +43 -0
- package/src/components/StellarViewOnExplorer.tsx +29 -0
- package/src/index.tsx +44 -21
- package/src/store/widgets.reducers.ts +5 -0
- package/src/store/widgets.store.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huma-finance/widgets",
|
|
3
|
-
"version": "0.0.62-beta.
|
|
3
|
+
"version": "0.0.62-beta.721+2f8c02b",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -29,13 +29,9 @@
|
|
|
29
29
|
"@ethersproject/experimental": "^5.7.0",
|
|
30
30
|
"@ethersproject/providers": "^5.6.0",
|
|
31
31
|
"@ethersproject/units": "^5.6.0",
|
|
32
|
-
"@huma-finance/sdk": "^0.0.
|
|
33
|
-
"@huma-finance/shared": "^0.0.
|
|
34
|
-
"@huma-finance/web-shared": "^0.0.62-beta.
|
|
35
|
-
"@mui/icons-material": "^5.3.0",
|
|
36
|
-
"@mui/material": "^5.0.6",
|
|
37
|
-
"@mui/styles": "^5.0.2",
|
|
38
|
-
"@mui/system": "^5.0.6",
|
|
32
|
+
"@huma-finance/sdk": "^0.0.62-beta.721+2f8c02b",
|
|
33
|
+
"@huma-finance/shared": "^0.0.62-beta.721+2f8c02b",
|
|
34
|
+
"@huma-finance/web-shared": "^0.0.62-beta.721+2f8c02b",
|
|
39
35
|
"@mui/x-date-pickers": "^5.0.7",
|
|
40
36
|
"@notifi-network/notifi-frontend-client": "^1.1.2",
|
|
41
37
|
"@notifi-network/notifi-react": "^1.1.2",
|
|
@@ -185,6 +181,7 @@
|
|
|
185
181
|
"@coral-xyz/anchor": "^0.30.1",
|
|
186
182
|
"@emotion/react": "^11.5.0",
|
|
187
183
|
"@emotion/styled": "^11.3.0",
|
|
184
|
+
"@huma-finance/soroban-tranche-vault": "0.0.15",
|
|
188
185
|
"@mui/icons-material": "^5.3.0",
|
|
189
186
|
"@mui/material": "^5.0.6",
|
|
190
187
|
"@mui/styles": "^5.0.2",
|
|
@@ -194,6 +191,7 @@
|
|
|
194
191
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
195
192
|
"@solana/wallet-adapter-react": "^0.15.35",
|
|
196
193
|
"@solana/web3.js": "^1.95.3",
|
|
194
|
+
"@soroban-react/core": "^9.3.0",
|
|
197
195
|
"ethers": "^5.6.1",
|
|
198
196
|
"react": ">=16.8.0",
|
|
199
197
|
"react-dom": ">=16.8.0",
|
|
@@ -203,5 +201,5 @@
|
|
|
203
201
|
"optionalDependencies": {
|
|
204
202
|
"encoding": "^0.1.13"
|
|
205
203
|
},
|
|
206
|
-
"gitHead": "
|
|
204
|
+
"gitHead": "2f8c02b7b55e44fd3175096a22a04121e3510ae4"
|
|
207
205
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { timeUtil } from '@huma-finance/shared'
|
|
2
|
-
import { SolanaPoolState } from '@huma-finance/web-shared'
|
|
3
|
-
import dayjs from 'dayjs'
|
|
2
|
+
import { getLenderLockupDates, SolanaPoolState } from '@huma-finance/web-shared'
|
|
4
3
|
import React, { useCallback } from 'react'
|
|
5
4
|
import { Box, css, useTheme } from '@mui/material'
|
|
6
5
|
import { useAppDispatch } from '../../../hooks/useRedux'
|
|
@@ -38,10 +37,9 @@ export function ApproveAllowance({ poolState }: Props): React.ReactElement {
|
|
|
38
37
|
`,
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const withdrawTime = lockupEndTime.add(1, 'month')
|
|
40
|
+
const { lockupEndTimeUnix, withdrawTimeUnix } = getLenderLockupDates(
|
|
41
|
+
poolState.withdrawalLockupPeriodDays ?? 0,
|
|
42
|
+
)
|
|
45
43
|
|
|
46
44
|
return (
|
|
47
45
|
<WrapperModal title='Auto-Redemption'>
|
|
@@ -51,9 +49,9 @@ export function ApproveAllowance({ poolState }: Props): React.ReactElement {
|
|
|
51
49
|
<Box css={styles.description}>
|
|
52
50
|
This allowance transaction will enable auto-redemption for your existing
|
|
53
51
|
tranche shares. Redemption requests will be automatically submitted on{' '}
|
|
54
|
-
{timeUtil.timestampToLL(
|
|
52
|
+
{timeUtil.timestampToLL(lockupEndTimeUnix)}. Your deposit can be
|
|
55
53
|
redeemed and yield rewards will stop on{' '}
|
|
56
|
-
{timeUtil.timestampToLL(
|
|
54
|
+
{timeUtil.timestampToLL(withdrawTimeUnix)}.
|
|
57
55
|
</Box>
|
|
58
56
|
<BottomButton variant='contained' onClick={handleNext}>
|
|
59
57
|
APPROVE ALLOWANCE
|
|
@@ -113,7 +113,7 @@ export function ChooseAmount({
|
|
|
113
113
|
<InputAmountModal
|
|
114
114
|
title='Enter Amount'
|
|
115
115
|
subTitle={`Depositing to ${
|
|
116
|
-
isUniTranche ? 'uni
|
|
116
|
+
isUniTranche ? 'uni' : selectedTranche
|
|
117
117
|
} tranche`}
|
|
118
118
|
tokenSymbol={symbol}
|
|
119
119
|
currentAmount={currentAmount}
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
} from '@solana/spl-token'
|
|
23
23
|
import { useWallet } from '@solana/wallet-adapter-react'
|
|
24
24
|
import { PublicKey, Transaction } from '@solana/web3.js'
|
|
25
|
-
import { BN } from '@coral-xyz/anchor'
|
|
26
25
|
import { useAppDispatch, useAppSelector } from '../../../hooks/useRedux'
|
|
27
26
|
import { setPointsAccumulated, setStep } from '../../../store/widgets.reducers'
|
|
28
27
|
import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
@@ -167,23 +166,23 @@ export function Transfer({
|
|
|
167
166
|
// Approve automatic redemptions
|
|
168
167
|
const sharesAmount = convertToShares(
|
|
169
168
|
selectedTranche === 'senior'
|
|
170
|
-
?
|
|
171
|
-
:
|
|
169
|
+
? BigInt(poolState.seniorTrancheAssets ?? 0)
|
|
170
|
+
: BigInt(poolState.juniorTrancheAssets ?? 0),
|
|
172
171
|
selectedTranche === 'senior'
|
|
173
|
-
? seniorTrancheMintSupply ??
|
|
174
|
-
: juniorTrancheMintSupply ??
|
|
175
|
-
supplyBigNumber,
|
|
172
|
+
? BigInt(seniorTrancheMintSupply?.toString() ?? 0)
|
|
173
|
+
: BigInt(juniorTrancheMintSupply?.toString() ?? 0),
|
|
174
|
+
BigInt(supplyBigNumber.toString()),
|
|
176
175
|
)
|
|
177
176
|
const existingShares = convertToShares(
|
|
178
177
|
selectedTranche === 'senior'
|
|
179
|
-
?
|
|
180
|
-
:
|
|
178
|
+
? BigInt(poolState.seniorTrancheAssets ?? 0)
|
|
179
|
+
: BigInt(poolState.juniorTrancheAssets ?? 0),
|
|
181
180
|
selectedTranche === 'senior'
|
|
182
|
-
? seniorTrancheMintSupply ??
|
|
183
|
-
: juniorTrancheMintSupply ??
|
|
181
|
+
? BigInt(seniorTrancheMintSupply?.toString() ?? 0)
|
|
182
|
+
: BigInt(juniorTrancheMintSupply?.toString() ?? 0),
|
|
184
183
|
selectedTranche === 'senior'
|
|
185
|
-
?
|
|
186
|
-
:
|
|
184
|
+
? BigInt(seniorTokenAccount?.amount.toString() ?? '0')
|
|
185
|
+
: BigInt(juniorTokenAccount?.amount.toString() ?? '0'),
|
|
187
186
|
)
|
|
188
187
|
tx.add(
|
|
189
188
|
createApproveCheckedInstruction(
|
|
@@ -195,7 +194,7 @@ export function Transfer({
|
|
|
195
194
|
),
|
|
196
195
|
new PublicKey(poolInfo.poolAuthority), // delegate
|
|
197
196
|
publicKey, // owner of the wallet
|
|
198
|
-
|
|
197
|
+
(sharesAmount * BigInt(11)) / BigInt(10) + existingShares, // amount
|
|
199
198
|
poolInfo.trancheDecimals,
|
|
200
199
|
undefined, // multiSigners
|
|
201
200
|
TOKEN_2022_PROGRAM_ID,
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { TrancheType, UnderlyingTokenInfo } 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
|
+
poolUnderlyingToken: UnderlyingTokenInfo
|
|
21
|
+
selectedTranche: TrancheType | undefined
|
|
22
|
+
changeTranche: (tranche: TrancheType) => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function ChooseTranche({
|
|
26
|
+
poolUnderlyingToken,
|
|
27
|
+
selectedTranche,
|
|
28
|
+
changeTranche,
|
|
29
|
+
}: Props): React.ReactElement | null {
|
|
30
|
+
const theme = useTheme()
|
|
31
|
+
const dispatch = useAppDispatch()
|
|
32
|
+
|
|
33
|
+
const styles = {
|
|
34
|
+
subTitle: css`
|
|
35
|
+
color: ${theme.palette.text.primary} !important;
|
|
36
|
+
font-weight: 400;
|
|
37
|
+
font-size: 16px;
|
|
38
|
+
line-height: 150%;
|
|
39
|
+
letter-spacing: 0.15px;
|
|
40
|
+
margin-top: ${theme.spacing(5)};
|
|
41
|
+
margin-left: ${theme.spacing(2)};
|
|
42
|
+
`,
|
|
43
|
+
radioGroup: css`
|
|
44
|
+
margin-left: ${theme.spacing(3)};
|
|
45
|
+
margin-top: ${theme.spacing(3)};
|
|
46
|
+
`,
|
|
47
|
+
formControl: css`
|
|
48
|
+
margin-bottom: ${theme.spacing(1)};
|
|
49
|
+
|
|
50
|
+
.MuiFormControlLabel-label {
|
|
51
|
+
color: ${theme.palette.text.primary};
|
|
52
|
+
font-weight: 400;
|
|
53
|
+
font-size: 16px;
|
|
54
|
+
line-height: 150%;
|
|
55
|
+
letter-spacing: 0.15px;
|
|
56
|
+
}
|
|
57
|
+
`,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const handleNext = () => {
|
|
61
|
+
dispatch(setStep(WIDGET_STEP.ChooseAmount))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const items: {
|
|
65
|
+
label: string
|
|
66
|
+
value: TrancheType
|
|
67
|
+
}[] = [
|
|
68
|
+
{
|
|
69
|
+
label: 'Senior',
|
|
70
|
+
value: 'senior',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: 'Junior',
|
|
74
|
+
value: 'junior',
|
|
75
|
+
},
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<WrapperModal title={`Supply ${poolUnderlyingToken.symbol}`}>
|
|
80
|
+
<FormControl>
|
|
81
|
+
<FormLabel css={styles.subTitle}>Select Tranche Type</FormLabel>
|
|
82
|
+
<RadioGroup
|
|
83
|
+
aria-labelledby='buttons-group-label'
|
|
84
|
+
name='radio-buttons-group'
|
|
85
|
+
css={styles.radioGroup}
|
|
86
|
+
onChange={(e) => changeTranche(e.target.value as TrancheType)}
|
|
87
|
+
>
|
|
88
|
+
{items.map((item) => (
|
|
89
|
+
<FormControlLabel
|
|
90
|
+
key={item.label}
|
|
91
|
+
value={item.value}
|
|
92
|
+
control={
|
|
93
|
+
<Radio
|
|
94
|
+
sx={{
|
|
95
|
+
'& .MuiSvgIcon-root': {
|
|
96
|
+
fontSize: 24,
|
|
97
|
+
},
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
}
|
|
101
|
+
label={item.label}
|
|
102
|
+
css={styles.formControl}
|
|
103
|
+
/>
|
|
104
|
+
))}
|
|
105
|
+
</RadioGroup>
|
|
106
|
+
</FormControl>
|
|
107
|
+
<BottomButton
|
|
108
|
+
variant='contained'
|
|
109
|
+
disabled={!selectedTranche}
|
|
110
|
+
onClick={handleNext}
|
|
111
|
+
>
|
|
112
|
+
NEXT
|
|
113
|
+
</BottomButton>
|
|
114
|
+
</WrapperModal>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatNumber,
|
|
3
|
+
StellarPoolInfo,
|
|
4
|
+
tokenDecimalUtils,
|
|
5
|
+
TrancheType,
|
|
6
|
+
} from '@huma-finance/shared'
|
|
7
|
+
import { StellarPoolState } from '@huma-finance/web-shared'
|
|
8
|
+
import React, { useMemo, useState } from 'react'
|
|
9
|
+
import { useAppDispatch } from '../../../hooks/useRedux'
|
|
10
|
+
import { setStep, setSupplyAmount } from '../../../store/widgets.reducers'
|
|
11
|
+
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
12
|
+
import { InputAmountModal } from '../../InputAmountModal'
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
poolInfo: StellarPoolInfo
|
|
16
|
+
poolState: StellarPoolState
|
|
17
|
+
tokenBalance: number | null
|
|
18
|
+
selectedTranche: TrancheType | undefined
|
|
19
|
+
isUniTranche?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function ChooseAmount({
|
|
23
|
+
poolInfo,
|
|
24
|
+
poolState,
|
|
25
|
+
tokenBalance,
|
|
26
|
+
selectedTranche,
|
|
27
|
+
isUniTranche,
|
|
28
|
+
}: Props): React.ReactElement | null {
|
|
29
|
+
const dispatch = useAppDispatch()
|
|
30
|
+
const { symbol, decimals } = poolInfo.underlyingToken
|
|
31
|
+
const [currentAmount, setCurrentAmount] = useState<number | string>(0)
|
|
32
|
+
const balance = tokenBalance ? BigInt(tokenBalance) : BigInt(0)
|
|
33
|
+
|
|
34
|
+
const { juniorAvailableCapBN, seniorAvailableCapBN } = useMemo(() => {
|
|
35
|
+
const {
|
|
36
|
+
maxSeniorJuniorRatio,
|
|
37
|
+
liquidityCap,
|
|
38
|
+
seniorTrancheAssets,
|
|
39
|
+
juniorTrancheAssets,
|
|
40
|
+
} = poolState
|
|
41
|
+
const juniorTrancheAssetsBN = BigInt(juniorTrancheAssets ?? 0)
|
|
42
|
+
const seniorTrancheAssetsBN = BigInt(seniorTrancheAssets ?? 0)
|
|
43
|
+
const totalDeployedBN = seniorTrancheAssetsBN + juniorTrancheAssetsBN
|
|
44
|
+
const totalAvailableCapBN = BigInt(liquidityCap ?? 0) - totalDeployedBN
|
|
45
|
+
const maxSeniorAssetsBN =
|
|
46
|
+
juniorTrancheAssetsBN * BigInt(maxSeniorJuniorRatio ?? 0)
|
|
47
|
+
let seniorAvailableCapBN = maxSeniorAssetsBN - seniorTrancheAssetsBN
|
|
48
|
+
seniorAvailableCapBN =
|
|
49
|
+
seniorAvailableCapBN > totalAvailableCapBN
|
|
50
|
+
? totalAvailableCapBN
|
|
51
|
+
: seniorAvailableCapBN
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
juniorAvailableCapBN: totalAvailableCapBN - seniorAvailableCapBN,
|
|
55
|
+
seniorAvailableCapBN,
|
|
56
|
+
}
|
|
57
|
+
}, [poolState])
|
|
58
|
+
|
|
59
|
+
const handleChangeAmount = (newAmount: number) => {
|
|
60
|
+
setCurrentAmount(newAmount)
|
|
61
|
+
dispatch(setSupplyAmount(Number(newAmount)))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const handleAction = () => {
|
|
65
|
+
dispatch(setStep(WIDGET_STEP.Transfer))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const getTrancheCap = () => {
|
|
69
|
+
if (selectedTranche === 'junior') {
|
|
70
|
+
return juniorAvailableCapBN
|
|
71
|
+
}
|
|
72
|
+
return seniorAvailableCapBN
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const getMinAmount = (): number => {
|
|
76
|
+
const minAmount = poolState.minDepositAmount
|
|
77
|
+
? tokenDecimalUtils.formatUnits(
|
|
78
|
+
BigInt(poolState.minDepositAmount),
|
|
79
|
+
decimals,
|
|
80
|
+
)
|
|
81
|
+
: 0
|
|
82
|
+
return Math.max(0, Math.ceil(Number(minAmount)))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const getMaxAmount = (): bigint => {
|
|
86
|
+
const trancheCap = getTrancheCap()
|
|
87
|
+
return balance > trancheCap ? trancheCap : balance
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const getInfos = () => {
|
|
91
|
+
const trancheCap = getTrancheCap()
|
|
92
|
+
const currentAmountBN = tokenDecimalUtils.parseUnits(
|
|
93
|
+
String(currentAmount),
|
|
94
|
+
decimals,
|
|
95
|
+
)
|
|
96
|
+
const remainingCap = trancheCap - currentAmountBN
|
|
97
|
+
|
|
98
|
+
if (remainingCap <= BigInt(0)) {
|
|
99
|
+
return ['0 remaining capacity']
|
|
100
|
+
}
|
|
101
|
+
return [
|
|
102
|
+
`${formatNumber(
|
|
103
|
+
tokenDecimalUtils.formatUnits(remainingCap, decimals),
|
|
104
|
+
)} remaining capacity`,
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<InputAmountModal
|
|
110
|
+
title='Enter Amount'
|
|
111
|
+
subTitle={`Depositing to ${
|
|
112
|
+
isUniTranche ? 'uni' : selectedTranche
|
|
113
|
+
} tranche`}
|
|
114
|
+
tokenSymbol={symbol}
|
|
115
|
+
currentAmount={currentAmount}
|
|
116
|
+
handleChangeAmount={handleChangeAmount}
|
|
117
|
+
minimumAmount={getMinAmount()}
|
|
118
|
+
maxAmount={Number(
|
|
119
|
+
tokenDecimalUtils.formatUnits(getMaxAmount(), decimals),
|
|
120
|
+
)}
|
|
121
|
+
maxAmountTitle={`${formatNumber(
|
|
122
|
+
tokenDecimalUtils.formatUnits(balance, decimals),
|
|
123
|
+
)} balance`}
|
|
124
|
+
infos={getInfos()}
|
|
125
|
+
handleAction={handleAction}
|
|
126
|
+
actionText='SUPPLY'
|
|
127
|
+
/>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
STELLAR_CHAINS_INFO,
|
|
3
|
+
StellarPoolInfo,
|
|
4
|
+
tokenDecimalUtils,
|
|
5
|
+
TrancheType,
|
|
6
|
+
} from '@huma-finance/shared'
|
|
7
|
+
import AssembledTransaction from '@stellar/stellar-sdk'
|
|
8
|
+
import { Client as TrancheVaultClient } from '@huma-finance/soroban-tranche-vault'
|
|
9
|
+
import React, { useCallback, useContext, useEffect, useState } from 'react'
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
getClientCommonParams,
|
|
13
|
+
StellarConnectionContext,
|
|
14
|
+
} from '@huma-finance/web-shared'
|
|
15
|
+
import { useAppDispatch, useAppSelector } from '../../../hooks/useRedux'
|
|
16
|
+
import { setStep } from '../../../store/widgets.reducers'
|
|
17
|
+
import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
18
|
+
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
19
|
+
import { StellarTxSendModal } from '../../StellarTxSendModal'
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
poolInfo: StellarPoolInfo
|
|
23
|
+
selectedTranche: TrancheType
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function Transfer({
|
|
27
|
+
poolInfo,
|
|
28
|
+
selectedTranche,
|
|
29
|
+
}: Props): React.ReactElement | null {
|
|
30
|
+
const dispatch = useAppDispatch()
|
|
31
|
+
const [tx, setTx] = useState<typeof AssembledTransaction | null>(null)
|
|
32
|
+
const { address: stellarAddress } = useContext(StellarConnectionContext)
|
|
33
|
+
const { supplyAmount } = useAppSelector(selectWidgetState)
|
|
34
|
+
const { decimals } = poolInfo.underlyingToken
|
|
35
|
+
const supplyBigNumber = tokenDecimalUtils.parseUnits(
|
|
36
|
+
String(supplyAmount),
|
|
37
|
+
decimals,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const handleSuccess = useCallback(async () => {
|
|
41
|
+
dispatch(setStep(WIDGET_STEP.Done))
|
|
42
|
+
}, [dispatch])
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
async function getTx() {
|
|
46
|
+
if (!stellarAddress) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const chainMetadata = STELLAR_CHAINS_INFO[poolInfo.chainId]
|
|
51
|
+
const trancheVaultClient = new TrancheVaultClient({
|
|
52
|
+
publicKey: stellarAddress,
|
|
53
|
+
contractId:
|
|
54
|
+
selectedTranche === 'senior'
|
|
55
|
+
? poolInfo.seniorTranche!
|
|
56
|
+
: poolInfo.juniorTranche,
|
|
57
|
+
...getClientCommonParams(chainMetadata),
|
|
58
|
+
})
|
|
59
|
+
const tx = await trancheVaultClient.deposit({
|
|
60
|
+
lender: stellarAddress,
|
|
61
|
+
assets: supplyBigNumber,
|
|
62
|
+
})
|
|
63
|
+
setTx(tx)
|
|
64
|
+
}
|
|
65
|
+
getTx()
|
|
66
|
+
}, [poolInfo, selectedTranche, stellarAddress, supplyBigNumber])
|
|
67
|
+
|
|
68
|
+
return <StellarTxSendModal tx={tx} handleSuccess={handleSuccess} />
|
|
69
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloseModalOptions,
|
|
3
|
+
formatMoney,
|
|
4
|
+
StellarPoolInfo,
|
|
5
|
+
timeUtil,
|
|
6
|
+
} from '@huma-finance/shared'
|
|
7
|
+
import React, { useCallback } from 'react'
|
|
8
|
+
import {
|
|
9
|
+
getLenderLockupDates,
|
|
10
|
+
StellarPoolState,
|
|
11
|
+
} from '@huma-finance/web-shared'
|
|
12
|
+
import { useAppSelector } from '../../../hooks/useRedux'
|
|
13
|
+
import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
14
|
+
import { StellarTxDoneModal } from '../../StellarTxDoneModal'
|
|
15
|
+
|
|
16
|
+
type Props = {
|
|
17
|
+
poolInfo: StellarPoolInfo
|
|
18
|
+
poolState: StellarPoolState
|
|
19
|
+
handleAction: (options?: CloseModalOptions) => void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Success({
|
|
23
|
+
poolInfo,
|
|
24
|
+
poolState,
|
|
25
|
+
handleAction,
|
|
26
|
+
}: Props): React.ReactElement {
|
|
27
|
+
const { supplyAmount, txHash } = useAppSelector(selectWidgetState)
|
|
28
|
+
const { symbol } = poolInfo.underlyingToken
|
|
29
|
+
|
|
30
|
+
const content = [
|
|
31
|
+
`You successfully supplied ${formatMoney(supplyAmount)} ${symbol}.`,
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const getSubContent = () => {
|
|
35
|
+
const { lockupEndTimeUnix, withdrawTimeUnix } = getLenderLockupDates(
|
|
36
|
+
poolState.withdrawalLockupPeriodDays ?? 0,
|
|
37
|
+
)
|
|
38
|
+
return [
|
|
39
|
+
`You can begin submitting redemption requests on ${timeUtil.timestampToLL(
|
|
40
|
+
lockupEndTimeUnix,
|
|
41
|
+
)}, which can be redeemed starting ${timeUtil.timestampToLL(
|
|
42
|
+
withdrawTimeUnix,
|
|
43
|
+
)}.`,
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const handleUserAction = useCallback(() => {
|
|
48
|
+
handleAction({ isSuccess: true })
|
|
49
|
+
}, [handleAction])
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<StellarTxDoneModal
|
|
53
|
+
chainId={poolInfo.chainId}
|
|
54
|
+
handleAction={handleUserAction}
|
|
55
|
+
content={content}
|
|
56
|
+
subContent={getSubContent()}
|
|
57
|
+
txHash={txHash}
|
|
58
|
+
buttonText='DONE'
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloseModalOptions,
|
|
3
|
+
STELLAR_CHAINS_INFO,
|
|
4
|
+
StellarPoolInfo,
|
|
5
|
+
TrancheType,
|
|
6
|
+
} from '@huma-finance/shared'
|
|
7
|
+
import {
|
|
8
|
+
StellarConnectionContext,
|
|
9
|
+
StellarPoolState,
|
|
10
|
+
useStellarLender,
|
|
11
|
+
useStellarTokenBalance,
|
|
12
|
+
} from '@huma-finance/web-shared'
|
|
13
|
+
import React, { useContext, useEffect, useState } from 'react'
|
|
14
|
+
import { useDispatch } from 'react-redux'
|
|
15
|
+
|
|
16
|
+
import { useAppSelector } from '../../../hooks/useRedux'
|
|
17
|
+
import { setStep } from '../../../store/widgets.reducers'
|
|
18
|
+
import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
19
|
+
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
20
|
+
import { ErrorModal } from '../../ErrorModal'
|
|
21
|
+
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
22
|
+
import { ChooseTranche } from './2-ChooseTranche'
|
|
23
|
+
import { ChooseAmount } from './3-ChooseAmount'
|
|
24
|
+
import { Transfer } from './4-Transfer'
|
|
25
|
+
import { Success } from './5-Success'
|
|
26
|
+
|
|
27
|
+
export interface Campaign {
|
|
28
|
+
id: string
|
|
29
|
+
campaignGroupId: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Lend pool supply props
|
|
34
|
+
* @typedef {Object} StellarLendSupplyProps
|
|
35
|
+
* @property {StellarPoolInfo} poolInfo The metadata of the pool.
|
|
36
|
+
* @property {StellarPoolState} poolState The current state config of the pool.
|
|
37
|
+
* @property {function((CloseModalOptions|undefined)):void} handleClose Function to notify to close the widget modal when user clicks the 'x' close button.
|
|
38
|
+
* @property {function():void|undefined} handleSuccess Optional function to notify that the lending pool supply action is successful.
|
|
39
|
+
*/
|
|
40
|
+
export interface StellarLendSupplyProps {
|
|
41
|
+
poolInfo: StellarPoolInfo
|
|
42
|
+
poolState: StellarPoolState
|
|
43
|
+
handleClose: (options?: CloseModalOptions) => void
|
|
44
|
+
handleSuccess?: () => void
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function StellarLendSupply({
|
|
48
|
+
poolInfo,
|
|
49
|
+
poolState,
|
|
50
|
+
handleClose,
|
|
51
|
+
handleSuccess,
|
|
52
|
+
}: StellarLendSupplyProps): React.ReactElement | null {
|
|
53
|
+
const dispatch = useDispatch()
|
|
54
|
+
const { isUniTranche } = poolState
|
|
55
|
+
const { address: stellarAddress } = useContext(StellarConnectionContext)
|
|
56
|
+
const {
|
|
57
|
+
isLoadingStellarLender,
|
|
58
|
+
isJuniorApprovedLender,
|
|
59
|
+
isSeniorApprovedLender,
|
|
60
|
+
} = useStellarLender(stellarAddress, poolInfo)
|
|
61
|
+
const chainMetadata = STELLAR_CHAINS_INFO[poolInfo.chainId]
|
|
62
|
+
const { tokenBalance, isLoadingTokenBalance } = useStellarTokenBalance(
|
|
63
|
+
chainMetadata,
|
|
64
|
+
poolInfo.underlyingToken.address,
|
|
65
|
+
stellarAddress,
|
|
66
|
+
)
|
|
67
|
+
const { step, errorMessage } = useAppSelector(selectWidgetState)
|
|
68
|
+
const [selectedTranche, setSelectedTranche] = useState<TrancheType>()
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!step && !isLoadingStellarLender && !isLoadingTokenBalance) {
|
|
72
|
+
// if (!isJuniorApprovedLender && !isSeniorApprovedLender) {
|
|
73
|
+
// dispatch(setStep(WIDGET_STEP.Evaluation))
|
|
74
|
+
// return
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
if (isJuniorApprovedLender && !isSeniorApprovedLender) {
|
|
78
|
+
setSelectedTranche('junior')
|
|
79
|
+
dispatch(setStep(WIDGET_STEP.ChooseAmount))
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (isSeniorApprovedLender && !isJuniorApprovedLender) {
|
|
84
|
+
setSelectedTranche('senior')
|
|
85
|
+
dispatch(setStep(WIDGET_STEP.ChooseAmount))
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isJuniorApprovedLender && isSeniorApprovedLender) {
|
|
90
|
+
dispatch(setStep(WIDGET_STEP.ChooseTranche))
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}, [
|
|
94
|
+
dispatch,
|
|
95
|
+
handleClose,
|
|
96
|
+
poolInfo,
|
|
97
|
+
step,
|
|
98
|
+
isLoadingStellarLender,
|
|
99
|
+
isJuniorApprovedLender,
|
|
100
|
+
isSeniorApprovedLender,
|
|
101
|
+
isLoadingTokenBalance,
|
|
102
|
+
])
|
|
103
|
+
|
|
104
|
+
if (isLoadingStellarLender || isLoadingTokenBalance) {
|
|
105
|
+
return (
|
|
106
|
+
<WidgetWrapper
|
|
107
|
+
isOpen
|
|
108
|
+
isLoading
|
|
109
|
+
loadingTitle='Supply'
|
|
110
|
+
handleClose={handleClose}
|
|
111
|
+
handleSuccess={handleSuccess}
|
|
112
|
+
/>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<WidgetWrapper
|
|
118
|
+
isOpen
|
|
119
|
+
loadingTitle={`Supply ${poolInfo.underlyingToken.symbol}`}
|
|
120
|
+
handleClose={handleClose}
|
|
121
|
+
handleSuccess={handleSuccess}
|
|
122
|
+
>
|
|
123
|
+
{step === WIDGET_STEP.ChooseTranche && (
|
|
124
|
+
<ChooseTranche
|
|
125
|
+
poolUnderlyingToken={poolInfo.underlyingToken}
|
|
126
|
+
selectedTranche={selectedTranche}
|
|
127
|
+
changeTranche={setSelectedTranche}
|
|
128
|
+
/>
|
|
129
|
+
)}
|
|
130
|
+
{step === WIDGET_STEP.ChooseAmount && (
|
|
131
|
+
<ChooseAmount
|
|
132
|
+
poolInfo={poolInfo}
|
|
133
|
+
poolState={poolState}
|
|
134
|
+
tokenBalance={tokenBalance}
|
|
135
|
+
selectedTranche={selectedTranche}
|
|
136
|
+
isUniTranche={isUniTranche}
|
|
137
|
+
/>
|
|
138
|
+
)}
|
|
139
|
+
{step === WIDGET_STEP.Transfer && selectedTranche && (
|
|
140
|
+
<Transfer poolInfo={poolInfo} selectedTranche={selectedTranche} />
|
|
141
|
+
)}
|
|
142
|
+
{step === WIDGET_STEP.Done && (
|
|
143
|
+
<Success
|
|
144
|
+
poolInfo={poolInfo}
|
|
145
|
+
poolState={poolState}
|
|
146
|
+
handleAction={handleClose}
|
|
147
|
+
/>
|
|
148
|
+
)}
|
|
149
|
+
{step === WIDGET_STEP.Error && (
|
|
150
|
+
<ErrorModal
|
|
151
|
+
title='Supply'
|
|
152
|
+
errorReason='Sorry there was an error'
|
|
153
|
+
errorMessage={errorMessage}
|
|
154
|
+
handleOk={handleClose}
|
|
155
|
+
/>
|
|
156
|
+
)}
|
|
157
|
+
</WidgetWrapper>
|
|
158
|
+
)
|
|
159
|
+
}
|