Skip to content

Commit

Permalink
Adding Uniswap import button to advanced page (#854)
Browse files Browse the repository at this point in the history
* Adding import option to advanced page

* Updating empty uniswap position state

* Switching to simpler empty states
  • Loading branch information
IanWoodard authored Apr 29, 2024
1 parent 1c80634 commit 91831c2
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 37 deletions.
152 changes: 115 additions & 37 deletions earn/src/components/advanced/UniswapPositionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
UniswapPositionCardContainer,
UniswapPositionCardWrapper,
} from '../common/UniswapPositionCard';
import ImportUniswapNFTModal from './modal/ImportUniswapNFTModal';
import { WithdrawUniswapNFTModal } from './modal/WithdrawUniswapNFTModal';

const ACCENT_COLOR = 'rgba(130, 160, 182, 1)';
Expand All @@ -47,23 +48,84 @@ const PositionList = styled.div`
justify-content: space-between;
`;

enum TextAlignment {
LEFT = 'text-left',
RIGHT = 'text-right',
}

function TokenInfo(props: { textAlignment: TextAlignment; amount?: string; percentage?: number; symbol: string }) {
const { textAlignment, amount, percentage, symbol } = props;
return (
<div className={`${textAlignment}`}>
<Display size='XS' color={ACCENT_COLOR}>
{percentage ?? '-'}%
</Display>
<Display size='S'>{amount ?? '-'}</Display>
<Text size='XS'>{symbol}</Text>
</div>
);
}

function PriceInfo(props: {
textAlignment: TextAlignment;
label: string;
amount?: string;
token0Symbol: string;
token1Symbol: string;
}) {
const { textAlignment, label, amount, token0Symbol, token1Symbol } = props;
return (
<div className={`${textAlignment}`}>
<Text size='S' color={ACCENT_COLOR}>
{label}
</Text>
<Display size='S'>{amount ?? '-'}</Display>
<Text size='XS'>
{token1Symbol} per {token0Symbol}
</Text>
</div>
);
}

type UniswapPositionCardProps = {
borrower?: BorrowerNftBorrower;
uniswapPosition?: UniswapPosition;
withdrawableUniswapNFTs: Map<number, UniswapNFTPosition>;
hasImportableUniswapNFT: boolean;
setIsImportingUniswapNFT: (isImporting: boolean) => void;
setSelectedUniswapPosition: (uniswapPosition: SelectedUniswapPosition | null) => void;
setPendingTxn: (pendingTxn: SendTransactionResult | null) => void;
};

function UniswapPositionCard(props: UniswapPositionCardProps) {
const { borrower, uniswapPosition, withdrawableUniswapNFTs, setSelectedUniswapPosition } = props;
const {
borrower,
uniswapPosition,
withdrawableUniswapNFTs,
hasImportableUniswapNFT,
setIsImportingUniswapNFT,
setSelectedUniswapPosition,
} = props;

if (!borrower || !uniswapPosition) {
return (
<UniswapPositionCardWrapper $color={GREY_700}>
<Text size='S' color={ACCENT_COLOR} className='text-center'>
Empty
</Text>
{hasImportableUniswapNFT ? (
<div className='flex justify-center items-center'>
<FilledGradientButton
size='S'
disabled={!hasImportableUniswapNFT}
onClick={() => setIsImportingUniswapNFT(true)}
fillWidth
>
Import
</FilledGradientButton>
</div>
) : (
<Text size='S' color={ACCENT_COLOR} className='text-center'>
Empty
</Text>
)}
</UniswapPositionCardWrapper>
);
}
Expand Down Expand Up @@ -109,40 +171,34 @@ function UniswapPositionCard(props: UniswapPositionCardProps) {
/>
</div>
<div className='flex justify-between'>
<div className='text-left'>
<Display size='XS' color={ACCENT_COLOR}>
{roundPercentage(amount0Percent, 1)}%
</Display>
<Display size='S'>{formatTokenAmount(amount0, 5)}</Display>
<Text size='XS'>{borrower.token0.symbol}</Text>
</div>
<div className='text-right'>
<Display size='XS' color={ACCENT_COLOR}>
{roundPercentage(amount1Percent, 1)}%
</Display>
<Display size='S'>{formatTokenAmount(amount1, 5)}</Display>
<Text size='XS'>{borrower.token1.symbol}</Text>
</div>
<TokenInfo
textAlignment={TextAlignment.LEFT}
amount={formatTokenAmount(amount0, 5)}
percentage={roundPercentage(amount0Percent, 1)}
symbol={borrower.token0.symbol}
/>
<TokenInfo
textAlignment={TextAlignment.RIGHT}
amount={formatTokenAmount(amount1, 5)}
percentage={roundPercentage(amount1Percent, 1)}
symbol={borrower.token1.symbol}
/>
</div>
<div className='flex justify-between'>
<div className='text-left'>
<Text size='S' color={ACCENT_COLOR}>
Min Price
</Text>
<Display size='S'>{formatTokenAmount(minPrice, 5)}</Display>
<Text size='XS'>
{borrower.token1.symbol} per {borrower.token0.symbol}
</Text>
</div>
<div className='text-right'>
<Text size='S' color={ACCENT_COLOR}>
Max Price
</Text>
<Display size='S'>{formatTokenAmount(maxPrice, 5)}</Display>
<Text size='XS'>
{borrower.token1.symbol} per {borrower.token0.symbol}
</Text>
</div>
<PriceInfo
textAlignment={TextAlignment.LEFT}
label='Min Price'
amount={formatTokenAmount(minPrice, 5)}
token0Symbol={borrower.token0.symbol}
token1Symbol={borrower.token1.symbol}
/>
<PriceInfo
textAlignment={TextAlignment.RIGHT}
label='Max Price'
amount={formatTokenAmount(maxPrice, 5)}
token0Symbol={borrower.token0.symbol}
token1Symbol={borrower.token1.symbol}
/>
</div>
<div className='flex justify-between'>
{isInRange ? <InRangeBadge /> : <OutOfRangeBadge />}
Expand All @@ -168,13 +224,18 @@ function UniswapPositionCard(props: UniswapPositionCardProps) {

export type UniswapPositionListProps = {
borrower?: BorrowerNftBorrower;
importableUniswapNFTPositions: Map<number, UniswapNFTPosition>;
withdrawableUniswapNFTs: Map<number, UniswapNFTPosition>;
setPendingTxn: (pendingTxn: SendTransactionResult | null) => void;
};

export function UniswapPositionList(props: UniswapPositionListProps) {
const { borrower, withdrawableUniswapNFTs, setPendingTxn } = props;
const { borrower, importableUniswapNFTPositions, withdrawableUniswapNFTs, setPendingTxn } = props;
const [selectedUniswapPosition, setSelectedUniswapPosition] = useState<SelectedUniswapPosition | null>(null);
const [isImportingUniswapNFT, setIsImportingUniswapNFT] = useState(false);

const defaultImportableNFTPosition =
importableUniswapNFTPositions.size > 0 ? Array.from(importableUniswapNFTPositions.entries())[0] : null;

return (
<>
Expand All @@ -188,6 +249,10 @@ export function UniswapPositionList(props: UniswapPositionListProps) {
borrower={borrower}
uniswapPosition={borrower?.assets.uniswapPositions.at(index)}
withdrawableUniswapNFTs={withdrawableUniswapNFTs}
hasImportableUniswapNFT={
importableUniswapNFTPositions.size > 0 && borrower?.assets.uniswapPositions.length === index
}
setIsImportingUniswapNFT={() => setIsImportingUniswapNFT(true)}
setSelectedUniswapPosition={setSelectedUniswapPosition}
setPendingTxn={props.setPendingTxn}
/>
Expand All @@ -208,6 +273,19 @@ export function UniswapPositionList(props: UniswapPositionListProps) {
setPendingTxn={setPendingTxn}
/>
)}
{borrower && importableUniswapNFTPositions.size > 0 && defaultImportableNFTPosition && (
<ImportUniswapNFTModal
isOpen={isImportingUniswapNFT}
borrower={borrower}
uniswapNFTPositions={importableUniswapNFTPositions}
defaultUniswapNFTPosition={defaultImportableNFTPosition}
existingUniswapPositions={borrower.assets.uniswapPositions}
setIsOpen={() => {
setIsImportingUniswapNFT(false);
}}
setPendingTxn={setPendingTxn}
/>
)}
</>
);
}
25 changes: 25 additions & 0 deletions earn/src/components/advanced/modal/ImportUniswapNFTModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SendTransactionResult } from '@wagmi/core';
import Modal from 'shared/lib/components/common/Modal';

import { BorrowerNftBorrower } from '../../../data/BorrowerNft';
import { UniswapNFTPosition, UniswapPosition } from '../../../data/Uniswap';
import { AddUniswapNFTAsCollateralTab } from './tab/AddUniswapNFTAsCollateralTab';

export type ImportUniswapNFTModalProps = {
isOpen: boolean;
borrower: BorrowerNftBorrower;
existingUniswapPositions: readonly UniswapPosition[];
uniswapNFTPositions: Map<number, UniswapNFTPosition>;
defaultUniswapNFTPosition: [number, UniswapNFTPosition];
setIsOpen: (open: boolean) => void;
setPendingTxn: (pendingTxn: SendTransactionResult | null) => void;
};

export default function ImportUniswapNFTModal(props: ImportUniswapNFTModalProps) {
const { isOpen, setIsOpen } = props;
return (
<Modal isOpen={isOpen} title='Import Uniswap NFT Position' setIsOpen={setIsOpen} maxHeight='650px' maxWidth='500px'>
<AddUniswapNFTAsCollateralTab {...props} />
</Modal>
);
}
1 change: 1 addition & 0 deletions earn/src/pages/AdvancedPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ export default function AdvancedPage() {
/>
<UniswapPositionList
borrower={selectedMarginAccount}
importableUniswapNFTPositions={filteredNonZeroUniswapNFTPositions}
withdrawableUniswapNFTs={withdrawableUniswapNFTPositions}
setPendingTxn={setPendingTxn}
/>
Expand Down

0 comments on commit 91831c2

Please sign in to comment.