Skip to content

Commit ef9fd55

Browse files
SOV-4179: Repositioning out of range, add single sided liquidity (#932)
* chore: remove deprecated props * chore: fix UI bug (change precs from 9 to 6) * chore: update bob mm context * chore: update onComplete func to reset all values * chore: add single-asset deposit only * Create three-oranges-hear.md * chore: updates from comments * chore: update unbalanced price change * chore: fix partial withdraw * chore: update prices * chore: update price renderer * chore: update prices renderer * chore: repositioning out of range * Create hot-dancers-knock.md * chore: update prices + partial withdraw * chore: updates from comments * rebuild * Revert "rebuild" This reverts commit 0b24033. * chore: fix balance issue * chore: fix failed transactions * chore: fix authentication needed: password or unlock error * fix: balance change on ambient history table * trigger rebuild --------- Co-authored-by: Rick <peymannaderi3@gmail.com>
1 parent 11f153b commit ef9fd55

36 files changed

Lines changed: 1170 additions & 354 deletions

File tree

.changeset/hot-dancers-knock.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"frontend": patch
3+
---
4+
5+
SOV-4179: Repositioning out of range

.changeset/three-oranges-hear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"frontend": patch
3+
---
4+
5+
SOV-4162: Unbalanced single sided ranged liquidity deposits

apps/frontend/src/app/3_organisms/EarnHistoryFrame/components/AmbientMarketMakingHistoryFrame/components/BalanceChange.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,14 @@ export const BalanceChange: React.FC<BalanceChangeProps> = ({
2828
).toString(),
2929
baseToken?.decimals,
3030
).toString()}
31+
prefix={
32+
Number(liquidityChange.baseFlow) === 0
33+
? ''
34+
: liquidityChange.changeType === 'mint'
35+
? '+'
36+
: '-'
37+
}
3138
suffix={getTokenDisplayName(baseToken?.symbol || '')}
32-
prefix={liquidityChange.changeType === 'mint' ? '+' : '-'}
3339
/>
3440

3541
<AmountRenderer
@@ -41,7 +47,13 @@ export const BalanceChange: React.FC<BalanceChangeProps> = ({
4147
quoteToken?.decimals,
4248
).toString()}
4349
suffix={getTokenDisplayName(quoteToken?.symbol || '')}
44-
prefix={liquidityChange.changeType === 'mint' ? '+' : '-'}
50+
prefix={
51+
Number(liquidityChange.quoteFlow) === 0
52+
? ''
53+
: liquidityChange.changeType === 'mint'
54+
? '+'
55+
: '-'
56+
}
4557
/>
4658
</div>
4759
);

apps/frontend/src/app/5_pages/MarketMakingPage/MarketMakingPage.types.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { SupportedTokens } from '@sovryn/contracts';
21
import { Decimal } from '@sovryn/utils';
32

43
import { AmmLiquidityPool } from './utils/AmmLiquidityPool';
@@ -34,8 +33,8 @@ export type PromotionData = {
3433
rewardAmount: number;
3534
type: 'AMM' | 'LENDING';
3635
poolTokenA: string;
37-
asset1: SupportedTokens;
38-
asset2: SupportedTokens;
36+
asset1: string;
37+
asset2: string;
3938
linkAsset?: string;
4039
ammData: AmmHistory;
4140
apy: string;

apps/frontend/src/app/5_pages/MarketMakingPage/MarketMakingPage.utils.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import { SupportedTokens } from '@sovryn/contracts';
2-
31
import { AmmHistory } from './MarketMakingPage.types';
42
import { AmmLiquidityPoolDictionary } from './utils/AmmLiquidityPoolDictionary';
53

64
export const getAmmHistory = (
75
ammData: any,
8-
asset1: SupportedTokens,
9-
asset2: SupportedTokens,
6+
asset1: string,
7+
asset2: string,
108
): AmmHistory =>
119
ammData &&
1210
ammData[

apps/frontend/src/app/5_pages/MarketMakingPage/components/AdjustAndDepositModal/components/NewPoolStatistics/NewPoolStatistics.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React, { FC, useMemo } from 'react';
33
import classNames from 'classnames';
44
import { t } from 'i18next';
55

6-
import { SupportedTokens } from '@sovryn/contracts';
76
import { HelperButton, SimpleTable, SimpleTableRow } from '@sovryn/ui';
87
import { Decimal } from '@sovryn/utils';
98

@@ -14,21 +13,21 @@ import {
1413
TOKEN_RENDER_PRECISION,
1514
} from '../../../../../../../constants/currencies';
1615
import { translations } from '../../../../../../../locales/i18n';
16+
import { COMMON_SYMBOLS } from '../../../../../../../utils/asset';
1717
import { decimalic } from '../../../../../../../utils/math';
1818
import { useGetAccumulatedReward } from '../../../../hooks/useGetAccumulatedReward';
1919
import { useGetExpectedTokenAmount } from '../../../../hooks/useGetExpectedTokenAmount';
2020
import { useGetUserInfo } from '../../../../hooks/useGetUserInfo';
2121
import { AmmLiquidityPool } from '../../../../utils/AmmLiquidityPool';
2222
import { AdjustType } from '../../AdjustAndDepositModal.types';
2323
import { useGetPoolBalanceAndRewards } from '../../hooks/useGetPoolBalanceAndRewards';
24-
import { COMMON_SYMBOLS } from '../../../../../../../utils/asset';
2524

2625
const pageTranslations =
2726
translations.marketMakingPage.adjustAndDepositModal.newPoolStatistics;
2827

2928
type NewPoolStatisticsProps = {
3029
value: string;
31-
asset: SupportedTokens;
30+
asset: string;
3231
decimalAmount: Decimal;
3332
isInitialDeposit: boolean;
3433
adjustType: AdjustType;

apps/frontend/src/app/5_pages/MarketMakingPage/components/AmbientMarketMaking/components/AmbientPoolPositions/AmbientPoolPositions.constants.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import { AmbientPosition } from '../../AmbientMarketMaking.types';
1111
import { AmbientLiquidityPool } from '../../utils/AmbientLiquidityPool';
1212
import { AmbientPoolPositionClaimFees } from './components/AmbientPoolPositionClaimFees/AmbientPoolPositionClaimFees';
1313
import { AmbientPoolPositionWithdraw } from './components/AmbientPoolPositionWithdraw/AmbientPoolPositionWithdraw';
14+
import { AmbientPoolReposition } from './components/AmbientPoolReposition/AmbientPoolReposition';
1415
import { AmbientPositionBalance } from './components/AmbientPositionBalance/AmbientPositionBalance';
1516
import { AmbientPositionPrices } from './components/AmbientPositionPrices/AmbientPositionPrices';
17+
import { AmbientPositionStatus } from './components/AmbientPositionStatus/AmbientPositionStatus';
1618
import { AmbientPositionValue } from './components/AmbientPositionValue/AmbientPositionValue';
1719

1820
export const COLUMNS_CONFIG = (pool: AmbientLiquidityPool) => [
@@ -70,6 +72,13 @@ export const COLUMNS_CONFIG = (pool: AmbientLiquidityPool) => [
7072
<AmbientPositionBalance pool={pool} position={position} />
7173
),
7274
},
75+
{
76+
id: 'status',
77+
title: t(translations.ambientMarketMaking.positionsTable.status.title),
78+
cellRenderer: (position: AmbientPosition) => (
79+
<AmbientPositionStatus position={position} pool={pool} />
80+
),
81+
},
7382
{
7483
id: '',
7584
title: '',
@@ -82,6 +91,11 @@ export const COLUMNS_CONFIG = (pool: AmbientLiquidityPool) => [
8291
className="mr-4"
8392
/>
8493
)}
94+
<AmbientPoolReposition
95+
pool={pool}
96+
position={position}
97+
className="mr-4"
98+
/>
8599
<AmbientPoolPositionWithdraw pool={pool} position={position} />
86100
</div>
87101
),

apps/frontend/src/app/5_pages/MarketMakingPage/components/AmbientMarketMaking/components/AmbientPoolPositions/AmbientPoolPositions.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { AmbientPoolPositionClaimFees } from './components/AmbientPoolPositionCl
1616
import { AmbientPoolPositionWithdraw } from './components/AmbientPoolPositionWithdraw/AmbientPoolPositionWithdraw';
1717
import { AmbientPositionBalance } from './components/AmbientPositionBalance/AmbientPositionBalance';
1818
import { AmbientPositionPrices } from './components/AmbientPositionPrices/AmbientPositionPrices';
19+
import { AmbientPositionStatus } from './components/AmbientPositionStatus/AmbientPositionStatus';
1920
import { AmbientPositionValue } from './components/AmbientPositionValue/AmbientPositionValue';
2021

2122
type AmbientPoolPositionsProps = {
@@ -49,6 +50,18 @@ export const AmbientPoolPositions: FC<AmbientPoolPositionsProps> = ({
4950
label={t(translations.ambientMarketMaking.positionsTable.balance)}
5051
value={<AmbientPositionBalance pool={pool} position={position} />}
5152
/>
53+
<SimpleTableRow
54+
label={t(
55+
translations.ambientMarketMaking.positionsTable.status.title,
56+
)}
57+
value={
58+
<AmbientPositionStatus
59+
pool={pool}
60+
position={position}
61+
className="flex justify-end"
62+
/>
63+
}
64+
/>
5265
<SimpleTableRow
5366
label={t(translations.ambientMarketMaking.positionsTable.value)}
5467
value={<AmbientPositionValue pool={pool} position={position} />}

apps/frontend/src/app/5_pages/MarketMakingPage/components/AmbientMarketMaking/components/AmbientPoolPositions/AmbientPoolPositions.utils.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1+
import { MaxAllowanceTransferAmount } from '@uniswap/permit2-sdk';
2+
3+
import { BigNumber, Contract, ethers } from 'ethers';
4+
15
import {
26
baseTokenForConcLiq,
37
bigNumToFloat,
48
floatToBigNum,
59
quoteTokenForConcLiq,
610
tickToPrice,
711
} from '@sovryn/sdex';
12+
import { CrocTokenView } from '@sovryn/sdex/dist/tokens';
13+
import { Decimal } from '@sovryn/utils';
814

15+
import { prepareApproveTransaction } from '../../../../../../../utils/transactions';
916
import { PoolPositionType } from '../../../../MarketMakingPage.types';
17+
import {
18+
MAXIMUM_PRICE,
19+
MINIMUM_PRICE,
20+
} from '../../../BobDepositModal/BobDepositModal.constants';
1021
import { AmbientPosition } from '../../AmbientMarketMaking.types';
1122

1223
export const getPositionBalance = (
@@ -58,3 +69,82 @@ export const getPositionBalance = (
5869
};
5970
}
6071
};
72+
73+
export const calculateBoundedPrice = (
74+
isMinimumPrice: boolean,
75+
value: number,
76+
currentPrice: number,
77+
) => {
78+
if (value === 0) {
79+
return currentPrice;
80+
}
81+
82+
if (value === 100) {
83+
return isMinimumPrice ? MINIMUM_PRICE : MAXIMUM_PRICE;
84+
}
85+
86+
const priceDifference = Decimal.from(currentPrice).mul(
87+
Decimal.from(value).div(100),
88+
);
89+
90+
if (isMinimumPrice) {
91+
const result = Decimal.from(currentPrice).sub(priceDifference);
92+
return result.lt(0) ? 0 : result.toNumber();
93+
}
94+
95+
return Decimal.from(currentPrice).add(priceDifference).toNumber();
96+
};
97+
98+
export const adjustPriceByPercentage = (
99+
percentage: number,
100+
currentPrice: number,
101+
): number => {
102+
const adjustmentFactor = 1 + percentage / 100;
103+
return currentPrice * adjustmentFactor;
104+
};
105+
106+
export const testAllowance = async (
107+
owner: string,
108+
token: CrocTokenView,
109+
amount: BigNumber,
110+
) => {
111+
const allowance = await token.allowance(owner);
112+
113+
if (allowance.lt(amount)) {
114+
const approval = await token.approve();
115+
return approval;
116+
}
117+
};
118+
119+
export const checkAndPrepareApproveTransaction = async ({
120+
account,
121+
token,
122+
assetAmount,
123+
chainId,
124+
signer,
125+
}) => {
126+
const allowance = await testAllowance(account, token, assetAmount);
127+
128+
if (allowance) {
129+
const approve = await prepareApproveTransaction({
130+
token: token.tokenAddr,
131+
chain: chainId,
132+
amount:
133+
allowance.weiQty === ethers.constants.MaxUint256
134+
? MaxAllowanceTransferAmount
135+
: allowance.weiQty,
136+
spender: allowance.address,
137+
contract: new Contract(
138+
token.tokenAddr,
139+
(
140+
await token.context
141+
).erc20Write.interface,
142+
signer,
143+
),
144+
});
145+
146+
return approve;
147+
}
148+
149+
return null;
150+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { FC, useCallback, useState } from 'react';
2+
3+
import { t } from 'i18next';
4+
5+
import { ButtonSize, ButtonStyle, Button } from '@sovryn/ui';
6+
7+
import { useMaintenance } from '../../../../../../../../../hooks/useMaintenance';
8+
import { translations } from '../../../../../../../../../locales/i18n';
9+
import { DepositContextProvider } from '../../../../../BobDepositModal/contexts/BobDepositModalContext';
10+
import { BobRepositionModal } from '../../../../../BobRepositionModal/BobRepositionModal';
11+
import { AmbientPosition } from '../../../../AmbientMarketMaking.types';
12+
import { AmbientLiquidityPool } from '../../../../utils/AmbientLiquidityPool';
13+
import { usePositionStatus } from '../../hooks/usePositionStatus';
14+
15+
type AmbientPoolRepositionProps = {
16+
pool: AmbientLiquidityPool;
17+
position: AmbientPosition;
18+
className?: string;
19+
};
20+
21+
export const AmbientPoolReposition: FC<AmbientPoolRepositionProps> = ({
22+
pool,
23+
position,
24+
className,
25+
}) => {
26+
const [isOpen, setIsOpen] = useState(false);
27+
const { checkMaintenance, States } = useMaintenance();
28+
const withdrawLocked = checkMaintenance(States.BOB_WITHDRAW_LIQUIDITY);
29+
const isOutOfRange = usePositionStatus(pool, position);
30+
31+
const toggleModal = useCallback(() => {
32+
setIsOpen(prevIsOpen => !prevIsOpen);
33+
}, []);
34+
35+
if (!isOutOfRange) {
36+
return null;
37+
}
38+
39+
return (
40+
<>
41+
<Button
42+
style={ButtonStyle.secondary}
43+
size={ButtonSize.small}
44+
text={t(translations.common.buttons.reposition)}
45+
onClick={toggleModal}
46+
disabled={withdrawLocked}
47+
className={className}
48+
/>
49+
<DepositContextProvider>
50+
<BobRepositionModal
51+
isOpen={isOpen}
52+
onClose={toggleModal}
53+
pool={pool}
54+
position={position}
55+
/>
56+
</DepositContextProvider>
57+
</>
58+
);
59+
};

0 commit comments

Comments
 (0)