@huma-finance/widgets 0.0.78-beta.1034 → 0.0.78-beta.1044
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/dist/index.js +12133 -10900
- package/dist/src/components/Lend/solanaWithdraw/1-Option.d.ts +12 -0
- package/dist/src/components/Lend/solanaWithdraw/2-WithdrawAndDepositConfirm.d.ts +15 -0
- package/dist/src/components/Lend/solanaWithdraw/{1-ConfirmTransfer.d.ts → 3-WithdrawOnlyConfirm.d.ts} +1 -1
- package/dist/src/components/Lend/solanaWithdraw/4-TransferAndDeposit.d.ts +13 -0
- package/dist/src/components/Lend/solanaWithdraw/{3-Done.d.ts → 6-Done.d.ts} +3 -1
- package/dist/src/components/Lend/solanaWithdraw/components/Apy.d.ts +7 -0
- package/dist/src/components/Lend/solanaWithdraw/components/Benefit.d.ts +2 -0
- package/dist/src/components/Lend/solanaWithdraw/components/CommitSwitcher.d.ts +12 -0
- package/dist/src/components/Lend/solanaWithdraw/components/ModeSelector.d.ts +12 -0
- package/dist/src/components/Lend/solanaWithdraw/components/SelectModeTitle.d.ts +2 -0
- package/dist/src/components/Lend/solanaWithdraw/index.d.ts +10 -0
- package/dist/src/components/TxDoneModal.d.ts +1 -1
- package/dist/src/components/WidgetWrapper.d.ts +2 -1
- package/dist/src/components/icons/index.d.ts +7 -0
- package/dist/src/store/widgets.store.d.ts +3 -0
- package/package.json +5 -5
- package/src/components/Lend/solanaWithdraw/1-Option.tsx +180 -0
- package/src/components/Lend/solanaWithdraw/2-WithdrawAndDepositConfirm.tsx +208 -0
- package/src/components/Lend/solanaWithdraw/{1-ConfirmTransfer.tsx → 3-WithdrawOnlyConfirm.tsx} +2 -2
- package/src/components/Lend/solanaWithdraw/4-TransferAndDeposit.tsx +274 -0
- package/src/components/Lend/solanaWithdraw/{3-Done.tsx → 6-Done.tsx} +27 -3
- package/src/components/Lend/solanaWithdraw/components/Apy.tsx +126 -0
- package/src/components/Lend/solanaWithdraw/components/Benefit.tsx +63 -0
- package/src/components/Lend/solanaWithdraw/components/CommitSwitcher.tsx +198 -0
- package/src/components/Lend/solanaWithdraw/components/ModeSelector.tsx +148 -0
- package/src/components/Lend/solanaWithdraw/components/SelectModeTitle.tsx +61 -0
- package/src/components/Lend/solanaWithdraw/index.tsx +102 -12
- package/src/components/TxDoneModal.tsx +3 -3
- package/src/components/WidgetWrapper.tsx +3 -1
- package/src/components/icons/huma-no-empty-space.svg +15 -0
- package/src/components/icons/index.tsx +49 -14
- package/src/components/icons/minus-sign-inactive.svg +4 -0
- package/src/components/icons/minus-sign.svg +14 -0
- package/src/components/icons/mode-classic.svg +3 -0
- package/src/components/icons/mode-maxi.svg +3 -0
- package/src/components/icons/plus-sign-inactive.svg +4 -0
- package/src/components/icons/plus-sign.svg +14 -0
- package/src/hooks/useLogOnFirstMount.ts +1 -1
- package/src/store/widgets.store.ts +3 -0
- /package/dist/src/components/Lend/solanaWithdraw/{2-Transfer.d.ts → 5-Transfer.d.ts} +0 -0
- /package/src/components/Lend/solanaWithdraw/{2-Transfer.tsx → 5-Transfer.tsx} +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { css, SerializedStyles } from '@emotion/react'
|
|
2
|
+
import {
|
|
3
|
+
PermissionlessDepositCommitment,
|
|
4
|
+
PermissionlessDepositCommitOptions,
|
|
5
|
+
toPercentage,
|
|
6
|
+
} from '@huma-finance/shared'
|
|
7
|
+
import { useMQ } from '@huma-finance/web-shared'
|
|
8
|
+
import { alpha, Box, Typography, useTheme } from '@mui/material'
|
|
9
|
+
import { ReactElement } from 'react'
|
|
10
|
+
import {
|
|
11
|
+
MinusSignIcon,
|
|
12
|
+
MinusSignInactiveIcon,
|
|
13
|
+
PlusSignIcon,
|
|
14
|
+
PlusSignInactiveIcon,
|
|
15
|
+
} from '../../../icons'
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
selectedCommitment: PermissionlessDepositCommitment
|
|
19
|
+
commitments: PermissionlessDepositCommitment[]
|
|
20
|
+
totalApy: number | undefined
|
|
21
|
+
styles?: SerializedStyles
|
|
22
|
+
onCommitmentChange: (commitment: PermissionlessDepositCommitment) => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function CommitSwitcher({
|
|
26
|
+
selectedCommitment,
|
|
27
|
+
commitments,
|
|
28
|
+
totalApy,
|
|
29
|
+
styles: extraStyles,
|
|
30
|
+
onCommitmentChange,
|
|
31
|
+
}: Props): ReactElement {
|
|
32
|
+
const theme = useTheme()
|
|
33
|
+
const { isXsSize } = useMQ()
|
|
34
|
+
|
|
35
|
+
const activeIndex = commitments.indexOf(selectedCommitment)
|
|
36
|
+
const isFirstItem = selectedCommitment === commitments[0]
|
|
37
|
+
const isLastItem = selectedCommitment === commitments[commitments.length - 1]
|
|
38
|
+
|
|
39
|
+
const getPreviousCommitment = () => {
|
|
40
|
+
if (isFirstItem) return null
|
|
41
|
+
return commitments[activeIndex - 1]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const getNextCommitment = () => {
|
|
45
|
+
if (isLastItem) return null
|
|
46
|
+
return commitments[activeIndex + 1]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const handlePrevious = () => {
|
|
50
|
+
const previousCommitment = getPreviousCommitment()
|
|
51
|
+
if (previousCommitment) {
|
|
52
|
+
onCommitmentChange(previousCommitment)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const handleNext = () => {
|
|
57
|
+
const nextCommitment = getNextCommitment()
|
|
58
|
+
if (nextCommitment) {
|
|
59
|
+
onCommitmentChange(nextCommitment)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const itemHeight = isXsSize ? 76 : 88
|
|
64
|
+
|
|
65
|
+
const styles = {
|
|
66
|
+
container: css`
|
|
67
|
+
width: 100%;
|
|
68
|
+
display: flex;
|
|
69
|
+
justify-content: space-between;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: ${theme.spacing(2)};
|
|
72
|
+
`,
|
|
73
|
+
button: css`
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
user-select: none;
|
|
76
|
+
-webkit-user-select: none;
|
|
77
|
+
-moz-user-select: none;
|
|
78
|
+
-ms-user-select: none;
|
|
79
|
+
> svg {
|
|
80
|
+
width: ${isXsSize ? '48px' : '60px'};
|
|
81
|
+
height: auto;
|
|
82
|
+
}
|
|
83
|
+
`,
|
|
84
|
+
buttonDisabled: css`
|
|
85
|
+
cursor: not-allowed;
|
|
86
|
+
`,
|
|
87
|
+
carouselContainer: css`
|
|
88
|
+
position: relative;
|
|
89
|
+
flex: 1;
|
|
90
|
+
height: ${itemHeight}px;
|
|
91
|
+
overflow: hidden;
|
|
92
|
+
border-radius: ${theme.shape.borderRadius}px;
|
|
93
|
+
`,
|
|
94
|
+
carouselContent: css`
|
|
95
|
+
position: absolute;
|
|
96
|
+
top: ${activeIndex * -itemHeight}px;
|
|
97
|
+
transition: top 0.3s;
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
justify-content: flex-start;
|
|
101
|
+
align-items: center;
|
|
102
|
+
width: 100%;
|
|
103
|
+
`,
|
|
104
|
+
item: css`
|
|
105
|
+
display: flex;
|
|
106
|
+
justify-content: space-between;
|
|
107
|
+
align-items: center;
|
|
108
|
+
padding: ${theme.spacing(isXsSize ? 1 : 2, 2)};
|
|
109
|
+
background: ${alpha('#FFFFFF', 0.05)};
|
|
110
|
+
height: ${itemHeight}px;
|
|
111
|
+
width: 100%;
|
|
112
|
+
`,
|
|
113
|
+
info: css`
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
justify-content: center;
|
|
117
|
+
align-items: center;
|
|
118
|
+
gap: ${theme.spacing(0.5)};
|
|
119
|
+
`,
|
|
120
|
+
minusSignIcon: css`
|
|
121
|
+
&:hover {
|
|
122
|
+
> path {
|
|
123
|
+
fill: url(#paint1_linear_11507_28492);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
`,
|
|
127
|
+
plusSignIcon: css`
|
|
128
|
+
&:hover {
|
|
129
|
+
> path {
|
|
130
|
+
fill: url(#paint1_linear_11507_28493);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
`,
|
|
134
|
+
apySkeleton: css`
|
|
135
|
+
width: 80px;
|
|
136
|
+
height: 32px;
|
|
137
|
+
`,
|
|
138
|
+
title: css`
|
|
139
|
+
color: #ececec;
|
|
140
|
+
font-weight: 700;
|
|
141
|
+
`,
|
|
142
|
+
apy: css`
|
|
143
|
+
color: #ececec;
|
|
144
|
+
font-weight: 700;
|
|
145
|
+
`,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const renderCommitmentOption = (
|
|
149
|
+
commitment: PermissionlessDepositCommitment,
|
|
150
|
+
) => {
|
|
151
|
+
const option = PermissionlessDepositCommitOptions[commitment]
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<Box key={commitment} css={styles.item}>
|
|
155
|
+
<Box css={styles.info}>
|
|
156
|
+
<Typography variant={isXsSize ? 'body2' : 'h6'} css={styles.title}>
|
|
157
|
+
{option.title}
|
|
158
|
+
</Typography>
|
|
159
|
+
</Box>
|
|
160
|
+
<Typography variant={isXsSize ? 'body2' : 'h6'} css={styles.apy}>
|
|
161
|
+
{toPercentage(totalApy!, 1)}
|
|
162
|
+
</Typography>
|
|
163
|
+
</Box>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<Box css={[styles.container, extraStyles]}>
|
|
169
|
+
<Box
|
|
170
|
+
css={[styles.button, isFirstItem && styles.buttonDisabled]}
|
|
171
|
+
onClick={handlePrevious}
|
|
172
|
+
>
|
|
173
|
+
{isFirstItem ? (
|
|
174
|
+
<MinusSignInactiveIcon />
|
|
175
|
+
) : (
|
|
176
|
+
<MinusSignIcon css={styles.minusSignIcon} />
|
|
177
|
+
)}
|
|
178
|
+
</Box>
|
|
179
|
+
|
|
180
|
+
<Box css={styles.carouselContainer}>
|
|
181
|
+
<Box css={styles.carouselContent}>
|
|
182
|
+
{commitments.map(renderCommitmentOption)}
|
|
183
|
+
</Box>
|
|
184
|
+
</Box>
|
|
185
|
+
|
|
186
|
+
<Box
|
|
187
|
+
css={[styles.button, isLastItem && styles.buttonDisabled]}
|
|
188
|
+
onClick={handleNext}
|
|
189
|
+
>
|
|
190
|
+
{isLastItem ? (
|
|
191
|
+
<PlusSignInactiveIcon />
|
|
192
|
+
) : (
|
|
193
|
+
<PlusSignIcon css={styles.plusSignIcon} />
|
|
194
|
+
)}
|
|
195
|
+
</Box>
|
|
196
|
+
</Box>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { PermissionlessDepositMode, toPercentage } from '@huma-finance/shared'
|
|
2
|
+
import { Box, css, useTheme } from '@mui/material'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { ModeClassicIcon, ModeMaxiIcon } from '../../../icons'
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
classicModeTargetApy: number | undefined
|
|
8
|
+
maxiModeTargetApy: number | undefined
|
|
9
|
+
classicHumaRewardsApy: number | undefined
|
|
10
|
+
maxiHumaRewardsApy: number | undefined
|
|
11
|
+
selectedDepositMode: PermissionlessDepositMode
|
|
12
|
+
setSelectedDepositMode: (mode: PermissionlessDepositMode) => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function ModeSelector({
|
|
16
|
+
classicModeTargetApy,
|
|
17
|
+
maxiModeTargetApy,
|
|
18
|
+
classicHumaRewardsApy,
|
|
19
|
+
maxiHumaRewardsApy,
|
|
20
|
+
selectedDepositMode,
|
|
21
|
+
setSelectedDepositMode,
|
|
22
|
+
}: Props): React.ReactElement {
|
|
23
|
+
const theme = useTheme()
|
|
24
|
+
|
|
25
|
+
const styles = {
|
|
26
|
+
modes: css`
|
|
27
|
+
display: flex;
|
|
28
|
+
justify-content: space-between;
|
|
29
|
+
align-items: center;
|
|
30
|
+
margin-top: ${theme.spacing(1)};
|
|
31
|
+
gap: ${theme.spacing(1)};
|
|
32
|
+
`,
|
|
33
|
+
modeContainer: css`
|
|
34
|
+
padding: ${theme.spacing(0.125)};
|
|
35
|
+
width: 100%;
|
|
36
|
+
`,
|
|
37
|
+
modeContainerSelected: css`
|
|
38
|
+
border-radius: 8px;
|
|
39
|
+
background: linear-gradient(190deg, #d157ff 4.58%, #74deff 100%);
|
|
40
|
+
box-shadow: 2px 2px 24px 1px #272727;
|
|
41
|
+
`,
|
|
42
|
+
mode: css`
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: ${theme.spacing(1)};
|
|
46
|
+
padding: ${theme.spacing(2, 3)};
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
background: #1b1b1b;
|
|
49
|
+
border-radius: 8px;
|
|
50
|
+
`,
|
|
51
|
+
modeSelected: css`
|
|
52
|
+
color: #ececec;
|
|
53
|
+
`,
|
|
54
|
+
modeTitle: css`
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: flex-start;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: ${theme.spacing(1)};
|
|
59
|
+
font-size: 16px;
|
|
60
|
+
font-weight: 500;
|
|
61
|
+
`,
|
|
62
|
+
modeTitleClassic: css`
|
|
63
|
+
color: #74deff;
|
|
64
|
+
`,
|
|
65
|
+
modeTitleMaxi: css`
|
|
66
|
+
color: #c677ff;
|
|
67
|
+
`,
|
|
68
|
+
modeApy: css`
|
|
69
|
+
font-size: 16px;
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
color: #848484;
|
|
72
|
+
margin-top: ${theme.spacing(1)};
|
|
73
|
+
`,
|
|
74
|
+
modeHumaRewardsApy: css`
|
|
75
|
+
font-size: 16px;
|
|
76
|
+
font-weight: 500;
|
|
77
|
+
color: #848484;
|
|
78
|
+
margin-top: ${theme.spacing(-1)};
|
|
79
|
+
`,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const getMode = (mode: PermissionlessDepositMode) => {
|
|
83
|
+
const modeInfos = {
|
|
84
|
+
[PermissionlessDepositMode.CLASSIC]: {
|
|
85
|
+
icon: <ModeClassicIcon />,
|
|
86
|
+
title: 'Classic',
|
|
87
|
+
apy: classicModeTargetApy,
|
|
88
|
+
humaRewardsApy: classicHumaRewardsApy,
|
|
89
|
+
},
|
|
90
|
+
[PermissionlessDepositMode.MAXI]: {
|
|
91
|
+
icon: <ModeMaxiIcon />,
|
|
92
|
+
title: 'Maxi',
|
|
93
|
+
apy: maxiModeTargetApy,
|
|
94
|
+
humaRewardsApy: maxiHumaRewardsApy,
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const modeInfo = modeInfos[mode]
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Box
|
|
102
|
+
css={[
|
|
103
|
+
styles.modeContainer,
|
|
104
|
+
selectedDepositMode === mode && styles.modeContainerSelected,
|
|
105
|
+
]}
|
|
106
|
+
onClick={() => setSelectedDepositMode(mode)}
|
|
107
|
+
>
|
|
108
|
+
<Box css={styles.mode}>
|
|
109
|
+
<Box css={styles.modeTitle}>
|
|
110
|
+
{modeInfo.icon}
|
|
111
|
+
<Box
|
|
112
|
+
css={
|
|
113
|
+
mode === PermissionlessDepositMode.CLASSIC
|
|
114
|
+
? styles.modeTitleClassic
|
|
115
|
+
: styles.modeTitleMaxi
|
|
116
|
+
}
|
|
117
|
+
>
|
|
118
|
+
{modeInfo.title}
|
|
119
|
+
</Box>
|
|
120
|
+
</Box>
|
|
121
|
+
<Box
|
|
122
|
+
css={[
|
|
123
|
+
styles.modeApy,
|
|
124
|
+
selectedDepositMode === mode && styles.modeSelected,
|
|
125
|
+
]}
|
|
126
|
+
>
|
|
127
|
+
{toPercentage(modeInfo.apy, 1)} USDC APY
|
|
128
|
+
</Box>
|
|
129
|
+
<Box
|
|
130
|
+
css={[
|
|
131
|
+
styles.modeHumaRewardsApy,
|
|
132
|
+
selectedDepositMode === mode && styles.modeSelected,
|
|
133
|
+
]}
|
|
134
|
+
>
|
|
135
|
+
{toPercentage(modeInfo.humaRewardsApy, 1)} Est. $HUMA
|
|
136
|
+
</Box>
|
|
137
|
+
</Box>
|
|
138
|
+
</Box>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<Box css={styles.modes}>
|
|
144
|
+
{getMode(PermissionlessDepositMode.CLASSIC)}
|
|
145
|
+
{getMode(PermissionlessDepositMode.MAXI)}
|
|
146
|
+
</Box>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import InfoOutlineIcon from '@mui/icons-material/InfoOutlined'
|
|
2
|
+
import { Box, css, Tooltip, useTheme } from '@mui/material'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
|
|
5
|
+
export function SelectModeTitle(): React.ReactElement {
|
|
6
|
+
const theme = useTheme()
|
|
7
|
+
|
|
8
|
+
const styles = {
|
|
9
|
+
selectDepositMode: css`
|
|
10
|
+
display: flex;
|
|
11
|
+
justify-content: flex-start;
|
|
12
|
+
align-items: center;
|
|
13
|
+
margin-top: ${theme.spacing(2)};
|
|
14
|
+
gap: ${theme.spacing(0.5)};
|
|
15
|
+
`,
|
|
16
|
+
selectDepositModeTitle: css`
|
|
17
|
+
font-weight: 700;
|
|
18
|
+
font-size: 16px;
|
|
19
|
+
color: #b8b8b8;
|
|
20
|
+
`,
|
|
21
|
+
infoIcon: css`
|
|
22
|
+
width: 16px;
|
|
23
|
+
height: 16px;
|
|
24
|
+
color: #686868;
|
|
25
|
+
`,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Box css={styles.selectDepositMode}>
|
|
30
|
+
<Box css={styles.selectDepositModeTitle}>Select deposit mode</Box>
|
|
31
|
+
<Tooltip
|
|
32
|
+
title={
|
|
33
|
+
<Box>
|
|
34
|
+
<Box>
|
|
35
|
+
Huma Permissionless offers two modes to match different LP
|
|
36
|
+
strategies. You can switch between them anytime, as often as you
|
|
37
|
+
like.
|
|
38
|
+
</Box>
|
|
39
|
+
<ul>
|
|
40
|
+
<li>
|
|
41
|
+
<strong>Classic Mode:</strong> Provides stable yield with
|
|
42
|
+
moderate Huma rewards. The current APY is 10%, updated monthly
|
|
43
|
+
based on market conditions. This mode is ideal for LPs who
|
|
44
|
+
prioritize consistent income.
|
|
45
|
+
</li>
|
|
46
|
+
<li>
|
|
47
|
+
<strong>Maxi Mode:</strong> Offers maximum Huma rewards by
|
|
48
|
+
trading away stable yield. LPs in this mode earn only Huma
|
|
49
|
+
rewards, making it the go-to choice for Huma-maximizing
|
|
50
|
+
believers—aka the Huma maxis.
|
|
51
|
+
</li>
|
|
52
|
+
</ul>
|
|
53
|
+
</Box>
|
|
54
|
+
}
|
|
55
|
+
placement='top'
|
|
56
|
+
>
|
|
57
|
+
<InfoOutlineIcon css={styles.infoIcon} />
|
|
58
|
+
</Tooltip>
|
|
59
|
+
</Box>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
formatNumberFixed,
|
|
3
|
+
PermissionlessDepositCommitment,
|
|
4
|
+
PermissionlessDepositMode,
|
|
3
5
|
SolanaPoolInfo,
|
|
4
6
|
SolanaTokenUtils,
|
|
5
7
|
TrancheType,
|
|
@@ -24,9 +26,43 @@ import {
|
|
|
24
26
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
25
27
|
import { ErrorModal } from '../../ErrorModal'
|
|
26
28
|
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
29
|
+
import { Option } from './1-Option'
|
|
30
|
+
import { WithdrawAndDepositConfirm } from './2-WithdrawAndDepositConfirm'
|
|
31
|
+
import { WithdrawOnlyConfirm } from './3-WithdrawOnlyConfirm'
|
|
32
|
+
import { TransferAndDeposit } from './4-TransferAndDeposit'
|
|
33
|
+
import { Transfer } from './5-Transfer'
|
|
34
|
+
import { Done } from './6-Done'
|
|
35
|
+
|
|
36
|
+
export enum WithdrawOption {
|
|
37
|
+
WITHDRAW_AND_REDEPOSIT = 'withdraw-and-redeposit',
|
|
38
|
+
WITHDRAW_ONLY = 'withdraw-only',
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type ClaimAndStakeOption = {
|
|
42
|
+
label: string
|
|
43
|
+
description?: string[]
|
|
44
|
+
id: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const ClaimAndStakeOptions: ClaimAndStakeOption[] = [
|
|
48
|
+
{
|
|
49
|
+
label: 'Withdraw and redeposit to Permissionless',
|
|
50
|
+
description: [
|
|
51
|
+
'Keep your OG status and unlock boosted yield forever',
|
|
52
|
+
'Choose your own investment lockup periods',
|
|
53
|
+
'Earn incentives for longer commitments',
|
|
54
|
+
'Earn Vanguard status',
|
|
55
|
+
],
|
|
56
|
+
id: WithdrawOption.WITHDRAW_AND_REDEPOSIT,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: `Withdraw only`,
|
|
60
|
+
id: WithdrawOption.WITHDRAW_ONLY,
|
|
61
|
+
description: [
|
|
62
|
+
'You need to have at least $100 USDC in Permissionless to keep your OG status',
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
]
|
|
30
66
|
|
|
31
67
|
/**
|
|
32
68
|
* Solana lend pool withdraw props
|
|
@@ -73,6 +109,13 @@ export function SolanaLendWithdraw({
|
|
|
73
109
|
)
|
|
74
110
|
const [withdrawnAmount, setWithdrawnAmount] = useState<BN>()
|
|
75
111
|
const loggingHelper = useAppSelector(selectWidgetLoggingContext)
|
|
112
|
+
const [selectedOption, setSelectedOption] = useState(ClaimAndStakeOptions[0])
|
|
113
|
+
const [selectedDepositMode, setSelectedDepositMode] = useState(
|
|
114
|
+
PermissionlessDepositMode.CLASSIC,
|
|
115
|
+
)
|
|
116
|
+
const [selectedDepositCommitment, setSelectedDepositCommitment] = useState(
|
|
117
|
+
PermissionlessDepositCommitment.INITIAL_COMMITMENT_SIX_MONTHS,
|
|
118
|
+
)
|
|
76
119
|
|
|
77
120
|
const handleCloseFlow = () => {
|
|
78
121
|
loggingHelper.logAction('ExitFlow', {})
|
|
@@ -102,7 +145,7 @@ export function SolanaLendWithdraw({
|
|
|
102
145
|
loggingHelperInit.logAction('StartFlow', {})
|
|
103
146
|
dispatch(setLoggingContext(context))
|
|
104
147
|
|
|
105
|
-
dispatch(setStep(WIDGET_STEP.
|
|
148
|
+
dispatch(setStep(WIDGET_STEP.Option))
|
|
106
149
|
}
|
|
107
150
|
}, [dispatch, poolInfo.chainId, poolInfo.poolName, poolInfo.poolType, step])
|
|
108
151
|
|
|
@@ -128,6 +171,18 @@ export function SolanaLendWithdraw({
|
|
|
128
171
|
trancheType,
|
|
129
172
|
])
|
|
130
173
|
|
|
174
|
+
const handleConfirmOption = useCallback(() => {
|
|
175
|
+
if (selectedOption.id === WithdrawOption.WITHDRAW_AND_REDEPOSIT) {
|
|
176
|
+
dispatch(setStep(WIDGET_STEP.ConfirmWithdrawAndDeposit))
|
|
177
|
+
} else {
|
|
178
|
+
dispatch(setStep(WIDGET_STEP.ConfirmWithdrawOnly))
|
|
179
|
+
}
|
|
180
|
+
}, [dispatch, selectedOption.id])
|
|
181
|
+
|
|
182
|
+
const withdrawAndDeposit = useCallback(() => {
|
|
183
|
+
dispatch(setStep(WIDGET_STEP.Transfer))
|
|
184
|
+
}, [dispatch])
|
|
185
|
+
|
|
131
186
|
const handleWithdrawSuccess = useCallback(
|
|
132
187
|
(blockNumber: number) => {
|
|
133
188
|
if (handleSuccess) {
|
|
@@ -140,28 +195,63 @@ export function SolanaLendWithdraw({
|
|
|
140
195
|
return (
|
|
141
196
|
<WidgetWrapper
|
|
142
197
|
isOpen
|
|
198
|
+
width={step === WIDGET_STEP.ConfirmWithdrawAndDeposit ? '520px' : '480px'}
|
|
143
199
|
loadingTitle={title}
|
|
144
200
|
handleClose={handleCloseFlow}
|
|
145
201
|
handleSuccess={handleWithdrawSuccess}
|
|
146
202
|
>
|
|
147
|
-
{step === WIDGET_STEP.
|
|
148
|
-
<
|
|
203
|
+
{step === WIDGET_STEP.Option && (
|
|
204
|
+
<Option
|
|
149
205
|
poolUnderlyingToken={poolInfo.underlyingMint}
|
|
150
206
|
withdrawableAmountFormatted={withdrawableAmountFormatted ?? '--'}
|
|
151
|
-
|
|
207
|
+
selectedOption={selectedOption}
|
|
208
|
+
setSelectedOption={setSelectedOption}
|
|
209
|
+
handleConfirmOption={handleConfirmOption}
|
|
210
|
+
/>
|
|
211
|
+
)}
|
|
212
|
+
{step === WIDGET_STEP.ConfirmWithdrawAndDeposit && (
|
|
213
|
+
<WithdrawAndDepositConfirm
|
|
214
|
+
withdrawableAmount={withdrawableAmount}
|
|
215
|
+
withdrawableAmountFormatted={withdrawableAmountFormatted ?? '--'}
|
|
216
|
+
chainId={poolInfo.chainId}
|
|
217
|
+
selectedDepositMode={selectedDepositMode}
|
|
218
|
+
setSelectedDepositMode={setSelectedDepositMode}
|
|
219
|
+
selectedDepositCommitment={selectedDepositCommitment}
|
|
220
|
+
setSelectedDepositCommitment={setSelectedDepositCommitment}
|
|
221
|
+
withdrawAndDeposit={withdrawAndDeposit}
|
|
152
222
|
/>
|
|
153
223
|
)}
|
|
154
|
-
{step === WIDGET_STEP.
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
224
|
+
{step === WIDGET_STEP.ConfirmWithdrawOnly && (
|
|
225
|
+
<WithdrawOnlyConfirm
|
|
226
|
+
poolUnderlyingToken={poolInfo.underlyingMint}
|
|
227
|
+
withdrawableAmountFormatted={withdrawableAmountFormatted ?? '--'}
|
|
228
|
+
sharePrice={sharePrice}
|
|
159
229
|
/>
|
|
160
230
|
)}
|
|
231
|
+
{step === WIDGET_STEP.Transfer &&
|
|
232
|
+
selectedOption.id === WithdrawOption.WITHDRAW_AND_REDEPOSIT && (
|
|
233
|
+
<TransferAndDeposit
|
|
234
|
+
poolInfo={poolInfo}
|
|
235
|
+
selectedTranche={trancheType}
|
|
236
|
+
poolIsClosed={poolIsClosed}
|
|
237
|
+
permissionlessMode={selectedDepositMode}
|
|
238
|
+
withdrawableAmount={withdrawableAmount}
|
|
239
|
+
depositCommitment={selectedDepositCommitment}
|
|
240
|
+
/>
|
|
241
|
+
)}
|
|
242
|
+
{step === WIDGET_STEP.Transfer &&
|
|
243
|
+
selectedOption.id === WithdrawOption.WITHDRAW_ONLY && (
|
|
244
|
+
<Transfer
|
|
245
|
+
poolInfo={poolInfo}
|
|
246
|
+
selectedTranche={trancheType}
|
|
247
|
+
poolIsClosed={poolIsClosed}
|
|
248
|
+
/>
|
|
249
|
+
)}
|
|
161
250
|
{step === WIDGET_STEP.Done && withdrawnAmount && (
|
|
162
251
|
<Done
|
|
163
252
|
poolUnderlyingToken={poolInfo.underlyingMint}
|
|
164
253
|
withdrawAmount={withdrawnAmount}
|
|
254
|
+
option={selectedOption}
|
|
165
255
|
handleAction={handleCloseFlow}
|
|
166
256
|
/>
|
|
167
257
|
)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Box, Button, css, Typography, useTheme } from '@mui/material'
|
|
2
1
|
import { txAtom } from '@huma-finance/web-shared'
|
|
2
|
+
import { Box, Button, css, Typography, useTheme } from '@mui/material'
|
|
3
3
|
import { useResetAtom } from 'jotai/utils'
|
|
4
4
|
import React, { useCallback } from 'react'
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ import { resetState } from '../store/widgets.reducers'
|
|
|
8
8
|
import { CheckIcon } from './icons'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
|
-
content: string[]
|
|
11
|
+
content: (string | React.ReactNode)[]
|
|
12
12
|
subContent?: string[]
|
|
13
13
|
buttonText?: string
|
|
14
14
|
handleAction: () => void
|
|
@@ -77,7 +77,7 @@ export function TxDoneModal({
|
|
|
77
77
|
</Box>
|
|
78
78
|
<Box css={styles.content}>
|
|
79
79
|
{content.map((item) => (
|
|
80
|
-
<Box sx={{ marginTop: theme.spacing(1) }} key={item}>
|
|
80
|
+
<Box sx={{ marginTop: theme.spacing(1) }} key={item?.toString()}>
|
|
81
81
|
{item}
|
|
82
82
|
</Box>
|
|
83
83
|
))}
|
|
@@ -17,6 +17,7 @@ type Props = {
|
|
|
17
17
|
isOpen: boolean
|
|
18
18
|
isLoading?: boolean
|
|
19
19
|
loadingTitle?: string
|
|
20
|
+
width?: string
|
|
20
21
|
handleClose: () => void
|
|
21
22
|
handleSuccess?: (blockNumber: number) => void
|
|
22
23
|
}
|
|
@@ -25,6 +26,7 @@ export function WidgetWrapper({
|
|
|
25
26
|
isOpen,
|
|
26
27
|
isLoading = false,
|
|
27
28
|
loadingTitle = '',
|
|
29
|
+
width = '480px',
|
|
28
30
|
handleClose,
|
|
29
31
|
handleSuccess,
|
|
30
32
|
children,
|
|
@@ -67,7 +69,7 @@ export function WidgetWrapper({
|
|
|
67
69
|
isOpen={isOpen}
|
|
68
70
|
overflowY='auto'
|
|
69
71
|
onClose={handleCloseModal}
|
|
70
|
-
width=
|
|
72
|
+
width={width}
|
|
71
73
|
padding={theme.spacing(4, 5)}
|
|
72
74
|
disableBackdropClick
|
|
73
75
|
>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg viewBox="2.5 4.3 27 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect x="11.2676" y="14.5305" width="11.2329" height="3.7961" fill="#B246FF"/>
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5496 4.36143C13.8705 2.70849 7.6775 5.39263 5.09814 10.9144C2.51877 16.4362 4.43722 22.9028 9.35286 26.1903L15.2227 13.6244L19.5496 4.36143Z" fill="url(#paint0_linear_623_5197)"/>
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.7575 5.80971C27.6731 9.09723 29.5916 15.5638 27.0122 21.0856C24.4328 26.6074 18.2399 29.2915 12.5607 27.6386L18.4305 15.0727L22.7575 5.80971Z" fill="url(#paint1_linear_623_5197)"/>
|
|
5
|
+
<defs>
|
|
6
|
+
<linearGradient id="paint0_linear_623_5197" x1="18.5668" y1="6.46542" x2="-11.3801" y2="2.80595" gradientUnits="userSpaceOnUse">
|
|
7
|
+
<stop stop-color="#B246FF"/>
|
|
8
|
+
<stop offset="1" stop-color="#FF6A8A"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<linearGradient id="paint1_linear_623_5197" x1="21.7747" y1="7.9137" x2="43.7938" y2="28.5207" gradientUnits="userSpaceOnUse">
|
|
11
|
+
<stop stop-color="#B246FF"/>
|
|
12
|
+
<stop offset="1" stop-color="#FF6A8A"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
</defs>
|
|
15
|
+
</svg>
|