Skip to content

Commit 4b71c74

Browse files
authored
Merge pull request #206 from blend-capital/add-non-collat-withdraw
feat: add support for withdrawing non-collateralized supply
2 parents 7c6ea42 + 5d1e7b2 commit 4b71c74

File tree

5 files changed

+108
-16
lines changed

5 files changed

+108
-16
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "blend-ui",
3-
"version": "2.0.6",
3+
"version": "2.0.7",
44
"private": true,
55
"type": "module",
66
"scripts": {

src/components/common/Section.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export enum SectionSize {
66
FULL = 'calc(100% - 12px)',
77
TILE = 'calc(50% - 12px)',
88
THIRD = 'calc(33.33% - 12px)',
9+
TWO_THIRD = 'calc(66.67% - 12px)',
910
EIGHTY = 'calc(80% - 12px)',
1011
TWENTY = 'calc(20% - 12px)',
1112
}

src/components/withdraw/WithdrawAnvil.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import { Box, Typography, useTheme } from '@mui/material';
1111
import { rpc } from '@stellar/stellar-sdk';
1212
import Image from 'next/image';
13-
import { useMemo, useState } from 'react';
13+
import { useEffect, useMemo, useState } from 'react';
1414
import { useSettings, ViewType } from '../../contexts';
1515
import { TxStatus, TxType, useWallet } from '../../contexts/wallet';
1616
import {
@@ -40,7 +40,11 @@ import { toUSDBalance } from '../common/USDBalance';
4040
import { Value } from '../common/Value';
4141
import { ValueChange } from '../common/ValueChange';
4242

43-
export const WithdrawAnvil: React.FC<ReserveComponentProps> = ({ poolId, assetId }) => {
43+
export interface WithdrawAnvilProps extends ReserveComponentProps {
44+
isCollateral: boolean;
45+
}
46+
47+
export const WithdrawAnvil: React.FC<WithdrawAnvilProps> = ({ poolId, assetId, isCollateral }) => {
4448
const theme = useTheme();
4549
const { viewType } = useSettings();
4650

@@ -85,7 +89,7 @@ export const WithdrawAnvil: React.FC<ReserveComponentProps> = ({ poolId, assetId
8589
requests: [
8690
{
8791
amount: scaleInputToBigInt(toWithdrawSubmit, decimals),
88-
request_type: RequestType.WithdrawCollateral,
92+
request_type: isCollateral ? RequestType.WithdrawCollateral : RequestType.Withdraw,
8993
address: reserve.assetId,
9094
},
9195
],
@@ -107,6 +111,10 @@ export const WithdrawAnvil: React.FC<ReserveComponentProps> = ({ poolId, assetId
107111
setLoadingEstimate(false);
108112
});
109113

114+
useEffect(() => {
115+
setToWithdraw('');
116+
}, [isCollateral]);
117+
110118
async function handleAddAssetTrustline() {
111119
if (connected && tokenMetadata?.asset) {
112120
const reserveAsset = tokenMetadata?.asset;
@@ -171,7 +179,9 @@ export const WithdrawAnvil: React.FC<ReserveComponentProps> = ({ poolId, assetId
171179

172180
const handleWithdrawAmountChange = (withdrawInput: string) => {
173181
if (reserve && poolUser) {
174-
let curSupplied = poolUser.getCollateralFloat(reserve);
182+
let curSupplied = isCollateral
183+
? poolUser.getCollateralFloat(reserve)
184+
: poolUser.getSupplyFloat(reserve);
175185
let realWithdraw = withdrawInput;
176186
let num_withdraw = Number(withdrawInput);
177187
if (num_withdraw > curSupplied) {
@@ -188,8 +198,10 @@ export const WithdrawAnvil: React.FC<ReserveComponentProps> = ({ poolId, assetId
188198

189199
const handleWithdrawMax = () => {
190200
if (reserve && poolUser) {
191-
let curSupplied = poolUser.getCollateralFloat(reserve);
192-
if (poolUser.positions.liabilities.size === 0) {
201+
let curSupplied = isCollateral
202+
? poolUser.getCollateralFloat(reserve)
203+
: poolUser.getSupplyFloat(reserve);
204+
if (poolUser.positions.liabilities.size === 0 || isCollateral === false) {
193205
handleWithdrawAmountChange((curSupplied * 1.005).toFixed(decimals));
194206
} else if (curPositionsEstimate && assetToBase) {
195207
let to_bounded_hf =
@@ -303,8 +315,16 @@ export const WithdrawAnvil: React.FC<ReserveComponentProps> = ({ poolId, assetId
303315
/>
304316
<ValueChange
305317
title="Your total supplied"
306-
curValue={`${toBalance(poolUser?.getCollateralFloat(reserve))} ${symbol}`}
307-
newValue={`${toBalance(newPoolUser?.getCollateralFloat(reserve))} ${symbol}`}
318+
curValue={`${toBalance(
319+
isCollateral
320+
? poolUser?.getCollateralFloat(reserve)
321+
: poolUser?.getSupplyFloat(reserve)
322+
)} ${symbol}`}
323+
newValue={`${toBalance(
324+
isCollateral
325+
? newPoolUser?.getCollateralFloat(reserve)
326+
: newPoolUser?.getSupplyFloat(reserve)
327+
)} ${symbol}`}
308328
/>
309329
<ValueChange
310330
title="Borrow capacity"

src/pages/withdraw.tsx

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { Box, Typography, useTheme } from '@mui/material';
22
import type { NextPage } from 'next';
33
import { useRouter } from 'next/router';
4+
import { useState } from 'react';
45
import { GoBackHeader } from '../components/common/GoBackHeader';
56
import { RateDisplay } from '../components/common/RateDisplay';
67
import { ReserveDetailsBar } from '../components/common/ReserveDetailsBar';
78
import { Row } from '../components/common/Row';
89
import { Section, SectionSize } from '../components/common/Section';
910
import { StackedText } from '../components/common/StackedText';
11+
import { ToggleButton } from '../components/common/ToggleButton';
12+
import { TooltipText } from '../components/common/TooltipText';
1013
import { NotPoolBar } from '../components/pool/NotPoolBar';
1114
import { WithdrawAnvil } from '../components/withdraw/WithdrawAnvil';
15+
import { useSettings, ViewType } from '../contexts';
1216
import {
1317
useBackstop,
1418
usePool,
@@ -23,6 +27,7 @@ import { estimateEmissionsApr } from '../utils/math';
2327

2428
const Withdraw: NextPage = () => {
2529
const theme = useTheme();
30+
const { viewType } = useSettings();
2631

2732
const router = useRouter();
2833
const { poolId, assetId } = router.query;
@@ -38,7 +43,10 @@ const Withdraw: NextPage = () => {
3843
const reserve = pool?.reserves.get(safeAssetId);
3944
const tokenSymbol = tokenMetadata?.symbol ?? toCompactAddress(safeAssetId);
4045

41-
const currentDeposit = reserve && poolUser ? poolUser.getCollateralFloat(reserve) : undefined;
46+
const [showCollateral, setShowCollateral] = useState(true);
47+
48+
const currentCollateral = reserve && poolUser ? poolUser.getCollateralFloat(reserve) : undefined;
49+
const currentSupply = reserve && poolUser ? poolUser.getSupplyFloat(reserve) : undefined;
4250
const emissionsPerAsset =
4351
reserve && reserve.supplyEmissions !== undefined
4452
? reserve.supplyEmissions.emissionsPerYearPerToken(
@@ -52,19 +60,79 @@ const Withdraw: NextPage = () => {
5260
? estimateEmissionsApr(emissionsPerAsset, backstop.backstopToken, oraclePrice)
5361
: undefined;
5462

63+
const hasSupplyBalance = currentSupply !== undefined && currentSupply > 0;
64+
5565
if (poolError?.message === NOT_BLEND_POOL_ERROR_MESSAGE) {
5666
return <NotPoolBar poolId={safePoolId} />;
5767
}
5868

69+
const handleCollateralClick = () => {
70+
if (!showCollateral) {
71+
setShowCollateral(true);
72+
}
73+
};
74+
75+
const handleNonCollateralClick = () => {
76+
if (showCollateral) {
77+
setShowCollateral(false);
78+
}
79+
};
80+
5981
return (
6082
<>
6183
<Row>
6284
<GoBackHeader poolId={safePoolId} />
6385
</Row>
6486
<ReserveDetailsBar action="withdraw" poolId={safePoolId} activeReserveId={safeAssetId} />
6587

66-
<Row>
67-
<Section width={SectionSize.FULL} sx={{ padding: '12px' }}>
88+
<Row sx={{ flexDirection: viewType === ViewType.REGULAR ? 'row' : 'column' }}>
89+
{hasSupplyBalance && (
90+
<Section
91+
width={viewType === ViewType.REGULAR ? SectionSize.TILE : SectionSize.FULL}
92+
sx={{
93+
display: 'flex',
94+
flexDirection: 'row',
95+
justifyContent: 'space-between',
96+
alignItems: 'center',
97+
padding: '12px',
98+
}}
99+
>
100+
<TooltipText
101+
tooltip={
102+
'Supplied funds can be collateralized. A position with collateral enabled is separate from a position with collateral disabled and must be withdrawn separately.'
103+
}
104+
width="auto"
105+
textVariant="body2"
106+
textColor={'text.secondary'}
107+
>
108+
{'Collateral'}
109+
</TooltipText>
110+
<Box sx={{ display: 'flex', flexDirection: 'row' }}>
111+
<ToggleButton
112+
active={showCollateral}
113+
palette={theme.palette.lend}
114+
sx={{ width: '50%', padding: '6px' }}
115+
onClick={handleCollateralClick}
116+
>
117+
Enabled
118+
</ToggleButton>
119+
<ToggleButton
120+
active={!showCollateral}
121+
palette={theme.palette.lend}
122+
sx={{ width: '50%', padding: '6px' }}
123+
onClick={handleNonCollateralClick}
124+
>
125+
Disabled
126+
</ToggleButton>
127+
</Box>
128+
</Section>
129+
)}
130+
<Section
131+
width={
132+
hasSupplyBalance && viewType === ViewType.REGULAR ? SectionSize.TILE : SectionSize.FULL
133+
}
134+
sx={{ padding: '12px' }}
135+
>
68136
<Box
69137
sx={{
70138
width: '100%',
@@ -79,7 +147,10 @@ const Withdraw: NextPage = () => {
79147
Available
80148
</Typography>
81149
<Typography variant="h4" sx={{ color: theme.palette.lend.main }}>
82-
{toBalance(currentDeposit)}
150+
{toBalance(
151+
showCollateral ? currentCollateral : currentSupply,
152+
reserve?.config.decimals
153+
)}
83154
</Typography>
84155
</Box>
85156
<Box>
@@ -129,7 +200,7 @@ const Withdraw: NextPage = () => {
129200
</Section>
130201
</Row>
131202
<Row>
132-
<WithdrawAnvil poolId={safePoolId} assetId={safeAssetId} />
203+
<WithdrawAnvil poolId={safePoolId} assetId={safeAssetId} isCollateral={showCollateral} />
133204
</Row>
134205
</>
135206
);

0 commit comments

Comments
 (0)