Skip to content

Commit f19d814

Browse files
committed
feat: migration modal styles
1 parent 1641f7d commit f19d814

File tree

10 files changed

+231
-53
lines changed

10 files changed

+231
-53
lines changed

pages/v3-migration.page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ export default function V3Migration() {
118118
hfV2AfterChange={'2'} // TODO: need value
119119
hfV3Current={'1.2'} // TODO: need value
120120
hfV3AfterChange={'2'} // TODO: need value
121+
disableButton={
122+
!Object.keys(selectedSupplyAssets).length && !Object.keys(selectedBorrowAssets).length
123+
}
121124
loading={loading}
122125
/>
123126
</ContentContainer>
Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,44 @@
1+
import { Trans } from '@lingui/macro';
12
import { useTransactionHandler } from 'src/helpers/useTransactionHandler';
23
import { useRootStore } from 'src/store/root';
34

4-
export const MigrateV3Actions = () => {
5-
// const selectedAssets = useRootStore((store) => )
5+
import { TxActionsWrapper } from '../TxActionsWrapper';
6+
7+
export type MigrateV3ActionsProps = {
8+
isWrongNetwork: boolean;
9+
blocked: boolean;
10+
};
11+
12+
export const MigrateV3Actions = ({ isWrongNetwork, blocked }: MigrateV3ActionsProps) => {
613
const migrateWithPermits = useRootStore((store) => store.migrateWithPermits);
714
const migrateWithoutPermits = useRootStore((store) => store.migrateWithoutPermits);
815
const getApprovePermitsForSelectedAssets = useRootStore(
916
(store) => store.getApprovePermitsForSelectedAssets
1017
);
11-
const { approval, action, loadingTxns, approvalTxState } = useTransactionHandler({
12-
handleGetTxns: async () => migrateWithoutPermits(),
13-
handleGetPermitTxns: async (signatures, deadline) => migrateWithPermits(signatures, deadline),
14-
tryPermit: true,
15-
});
18+
const { approval, action, loadingTxns, requiresApproval, mainTxState, approvalTxState } =
19+
useTransactionHandler({
20+
handleGetTxns: async () => migrateWithoutPermits(),
21+
handleGetPermitTxns: async (signatures, deadline) => migrateWithPermits(signatures, deadline),
22+
tryPermit: true,
23+
});
1624

1725
const handleApproval = async () => {
1826
const approvePermitsForSelectedAssets = await getApprovePermitsForSelectedAssets();
1927
approval(approvePermitsForSelectedAssets);
2028
};
2129

2230
return (
23-
<div>
24-
{(loadingTxns || approvalTxState.loading) && 'loading'}
25-
<button onClick={handleApproval}>Approve</button>
26-
{/* <button onClick={() => }></button> */}
27-
<button onClick={action}>Migrate</button>
28-
</div>
31+
<TxActionsWrapper
32+
requiresApproval={requiresApproval}
33+
preparingTransactions={loadingTxns}
34+
mainTxState={mainTxState}
35+
approvalTxState={approvalTxState}
36+
isWrongNetwork={isWrongNetwork}
37+
handleAction={action}
38+
handleApproval={handleApproval}
39+
blocked={blocked}
40+
actionText={<Trans>Migrate</Trans>}
41+
actionInProgressText={<Trans>Migrating</Trans>}
42+
/>
2943
);
3044
};
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import React from 'react';
2+
import { BasicModal } from 'src/components/primitives/BasicModal';
23
import { ModalType, useModalContext } from 'src/hooks/useModal';
34

4-
import { BasicModal } from '../../primitives/BasicModal';
5-
import { MigrateV3Actions } from './MigrateV3Actions';
5+
import { MigrateV3ModalContent } from './MigrateV3ModalContent';
66

77
export const MigrateV3Modal = () => {
88
const { type, close } = useModalContext();
9+
910
return (
1011
<BasicModal open={type === ModalType.V3Migration} setOpen={close}>
11-
<MigrateV3Actions />
12+
<MigrateV3ModalContent />
1213
</BasicModal>
1314
);
1415
};
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Box, Typography } from '@mui/material';
2+
import { ReactNode } from 'react';
3+
import { FormattedNumber } from 'src/components/primitives/FormattedNumber';
4+
import { Row } from 'src/components/primitives/Row';
5+
import { TokenIcon } from 'src/components/primitives/TokenIcon';
6+
7+
export type Asset = {
8+
underlyingAsset: string;
9+
iconSymbol: string;
10+
symbol: string;
11+
amount: string;
12+
amountInUSD: string;
13+
};
14+
15+
interface MigrateV3ModalAssetsListProps {
16+
caption: ReactNode;
17+
assets: (Asset | undefined)[];
18+
}
19+
20+
export const MigrateV3ModalAssetsList = ({ caption, assets }: MigrateV3ModalAssetsListProps) => {
21+
return (
22+
<Row
23+
caption={caption}
24+
captionVariant="description"
25+
align="flex-start"
26+
sx={{ mb: 6, '&:last-of-type': { mb: 0 } }}
27+
>
28+
{!!assets.length ? (
29+
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
30+
{assets.map((asset) =>
31+
asset ? (
32+
<Box
33+
key={asset.underlyingAsset}
34+
sx={{ mb: 2, display: 'flex', alignItems: 'flex-end', flexDirection: 'column' }}
35+
>
36+
<Box sx={{ display: 'flex', alignItems: 'center' }}>
37+
<TokenIcon symbol={asset.symbol} sx={{ mr: 1, fontSize: '16px' }} />
38+
<FormattedNumber value={asset.amount} variant="secondary14" compact />
39+
<Typography ml={1} variant="secondary14">
40+
{asset.symbol}
41+
</Typography>
42+
</Box>
43+
<FormattedNumber
44+
value={asset.amountInUSD}
45+
variant="helperText"
46+
compact
47+
symbol="USD"
48+
color="text.secondary"
49+
/>
50+
</Box>
51+
) : (
52+
<></>
53+
)
54+
)}
55+
</Box>
56+
) : (
57+
<Typography></Typography>
58+
)}
59+
</Row>
60+
);
61+
};
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { Trans } from '@lingui/macro';
2+
import { useModalContext } from 'src/hooks/useModal';
3+
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
4+
import { useUserReserves } from 'src/hooks/useUserReserves';
5+
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
6+
import { useRootStore } from 'src/store/root';
7+
import { getNetworkConfig } from 'src/utils/marketsAndNetworksConfig';
8+
9+
import { TxErrorView } from '../FlowCommons/Error';
10+
import { GasEstimationError } from '../FlowCommons/GasEstimationError';
11+
import { TxSuccessView } from '../FlowCommons/Success';
12+
import { TxModalDetails } from '../FlowCommons/TxModalDetails';
13+
import { TxModalTitle } from '../FlowCommons/TxModalTitle';
14+
import { ChangeNetworkWarning } from '../Warnings/ChangeNetworkWarning';
15+
import { MigrateV3Actions } from './MigrateV3Actions';
16+
import { MigrateV3ModalAssetsList } from './MigrateV3ModalAssetsList';
17+
18+
export const MigrateV3ModalContent = () => {
19+
const {
20+
selectedMigrationSupplyAssets: selectedSupplyAssets,
21+
selectedMigrationBorrowAssets: selectedBorrowAssets,
22+
} = useRootStore();
23+
24+
const { user, borrowPositions } = useUserReserves();
25+
26+
const { gasLimit, mainTxState: migrateTxState, txError } = useModalContext();
27+
const { currentChainId } = useProtocolDataContext();
28+
const { chainId: connectedChainId, watchModeOnlyAddress } = useWeb3Context();
29+
const networkConfig = getNetworkConfig(currentChainId);
30+
31+
const supplyAssets = Object.keys(selectedSupplyAssets).map((asset) => {
32+
const reserve = user.userReservesData.find(
33+
(reserve) => reserve.underlyingAsset.toLowerCase() === asset.toLowerCase()
34+
);
35+
36+
if (reserve) {
37+
return {
38+
underlyingAsset: asset,
39+
iconSymbol: reserve.reserve.iconSymbol,
40+
symbol: reserve.reserve.symbol,
41+
amount: reserve.underlyingBalance,
42+
amountInUSD: reserve.underlyingBalanceUSD,
43+
};
44+
}
45+
});
46+
47+
const borrowsAssets = Object.keys(selectedBorrowAssets).map((asset) => {
48+
const reserve = borrowPositions.find(
49+
(reserve) => reserve.underlyingAsset.toLowerCase() === asset.toLowerCase()
50+
);
51+
52+
if (reserve) {
53+
return {
54+
underlyingAsset: asset,
55+
iconSymbol: reserve.reserve.iconSymbol,
56+
symbol: reserve.reserve.symbol,
57+
amount: reserve.totalBorrows,
58+
amountInUSD: reserve.totalBorrowsUSD,
59+
};
60+
}
61+
});
62+
63+
// is Network mismatched
64+
const isWrongNetwork = currentChainId !== connectedChainId;
65+
66+
if (txError && txError.blocking) {
67+
return <TxErrorView txError={txError} />;
68+
}
69+
if (migrateTxState.success) return <TxSuccessView action={<Trans>Migrated</Trans>} />;
70+
71+
return (
72+
<>
73+
<TxModalTitle title="Migrate to V3" />
74+
{isWrongNetwork && !watchModeOnlyAddress && (
75+
<ChangeNetworkWarning networkName={networkConfig.name} chainId={currentChainId} />
76+
)}
77+
78+
<TxModalDetails gasLimit={gasLimit}>
79+
<MigrateV3ModalAssetsList
80+
caption={<Trans>Selected supply assets</Trans>}
81+
assets={supplyAssets}
82+
/>
83+
<MigrateV3ModalAssetsList
84+
caption={<Trans>Selected borrow assets</Trans>}
85+
assets={borrowsAssets}
86+
/>
87+
</TxModalDetails>
88+
89+
{txError && <GasEstimationError txError={txError} />}
90+
91+
<MigrateV3Actions isWrongNetwork={isWrongNetwork} blocked={false} />
92+
</>
93+
);
94+
};

src/locales/en/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/messages.po

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ msgstr "Back to Dashboard"
269269
#: src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsList.tsx
270270
#: src/modules/dashboard/lists/SuppliedPositionsList/SuppliedPositionsList.tsx
271271
#: src/modules/dashboard/lists/SuppliedPositionsList/SuppliedPositionsList.tsx
272+
#: src/modules/migration/MigrationList.tsx
272273
msgid "Balance"
273274
msgstr "Balance"
274275

@@ -1089,6 +1090,7 @@ msgstr "Maximum loan to value"
10891090
msgid "Menu"
10901091
msgstr "Menu"
10911092

1093+
#: src/components/transactions/MigrateV3/MigrateV3Actions.tsx
10921094
#: src/modules/migration/MigrationBottomPanel.tsx
10931095
msgid "Migrate"
10941096
msgstr "Migrate"
@@ -1097,6 +1099,14 @@ msgstr "Migrate"
10971099
msgid "Migrate to V3"
10981100
msgstr "Migrate to V3"
10991101

1102+
#: src/components/transactions/MigrateV3/MigrateV3ModalContent.tsx
1103+
msgid "Migrated"
1104+
msgstr "Migrated"
1105+
1106+
#: src/components/transactions/MigrateV3/MigrateV3Actions.tsx
1107+
msgid "Migrating"
1108+
msgstr "Migrating"
1109+
11001110
#: src/modules/migration/MigrationBottomPanel.tsx
11011111
msgid "Migrating multiple collaterals and borrowed assets at the same time can be an expensive operation and might fail in certain situations.<0>Therefore it’s not recommended to migrate positions with more than 5 assets (deposited + borrowed) at the same time.</0>"
11021112
msgstr "Migrating multiple collaterals and borrowed assets at the same time can be an expensive operation and might fail in certain situations.<0>Therefore it’s not recommended to migrate positions with more than 5 assets (deposited + borrowed) at the same time.</0>"
@@ -1491,6 +1501,14 @@ msgstr "Select token to add"
14911501
msgid "Select token to view in block explorer"
14921502
msgstr "Select token to view in block explorer"
14931503

1504+
#: src/components/transactions/MigrateV3/MigrateV3ModalContent.tsx
1505+
msgid "Selected borrow assets"
1506+
msgstr "Selected borrow assets"
1507+
1508+
#: src/components/transactions/MigrateV3/MigrateV3ModalContent.tsx
1509+
msgid "Selected supply assets"
1510+
msgstr "Selected supply assets"
1511+
14941512
#: src/components/HALLink.tsx
14951513
msgid "Setup notifications about your Health Factor using the Hal app."
14961514
msgstr "Setup notifications about your Health Factor using the Hal app."

src/modules/migration/MigrationBottomPanel.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface MigrationBottomPanelProps {
2222
hfV2AfterChange: string;
2323
hfV3Current: string;
2424
hfV3AfterChange: string;
25+
disableButton?: boolean;
2526
loading?: boolean;
2627
}
2728

@@ -30,6 +31,7 @@ export const MigrationBottomPanel = ({
3031
hfV2AfterChange,
3132
hfV3Current,
3233
hfV3AfterChange,
34+
disableButton,
3335
loading,
3436
}: MigrationBottomPanelProps) => {
3537
const { breakpoints } = useTheme();
@@ -89,7 +91,7 @@ export const MigrationBottomPanel = ({
8991
<Box>
9092
<Button
9193
onClick={openV3Migration}
92-
disabled={!isChecked}
94+
disabled={!isChecked || disableButton}
9395
sx={{ minWidth: 140 }}
9496
variant="contained"
9597
size="medium"

src/modules/migration/MigrationList.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import { ListColumn } from 'src/components/lists/ListColumn';
55
import { ListHeaderTitle } from 'src/components/lists/ListHeaderTitle';
66
import { ListHeaderWrapper } from 'src/components/lists/ListHeaderWrapper';
77
import { ListWrapper } from 'src/components/lists/ListWrapper';
8+
import { ListTopInfoItem } from 'src/modules/dashboard/lists/ListTopInfoItem';
89

910
interface MigrationListProps {
1011
titleComponent: ReactNode;
12+
totalAmount: string;
1113
isBottomOnMobile?: boolean;
1214
children: ReactNode;
1315
onSelectAllClick: () => void;
@@ -17,6 +19,7 @@ interface MigrationListProps {
1719

1820
export const MigrationList = ({
1921
titleComponent,
22+
totalAmount,
2023
isBottomOnMobile,
2124
children,
2225
onSelectAllClick,
@@ -29,7 +32,18 @@ export const MigrationList = ({
2932

3033
return (
3134
<Box sx={{ width: paperWidth, mt: { xs: isBottomOnMobile ? 2 : 0, md: 0 } }}>
32-
<ListWrapper titleComponent={titleComponent}>
35+
<ListWrapper
36+
titleComponent={
37+
<Typography component="div" variant="h3" sx={{ mr: 4 }}>
38+
{titleComponent}
39+
</Typography>
40+
}
41+
topInfo={
42+
!(loading || +totalAmount <= 0) && (
43+
<ListTopInfoItem title={<Trans>Balance</Trans>} value={totalAmount || 0} />
44+
)
45+
}
46+
>
3347
{(isAvailable || loading) && (
3448
<ListHeaderWrapper>
3549
<ListColumn align="center" maxWidth={isTablet ? 100 : 60}>

0 commit comments

Comments
 (0)