Skip to content

Commit

Permalink
refactor: reuse Token Card from swap, add cfg from sdk, decompose com…
Browse files Browse the repository at this point in the history
…ponents
  • Loading branch information
damnnou committed Mar 21, 2024
1 parent acfea3e commit 07bad2b
Show file tree
Hide file tree
Showing 8 changed files with 636 additions and 648 deletions.
241 changes: 38 additions & 203 deletions src/components/create-pool/CreatePoolForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,41 @@
import { Button } from '@/components/ui/button';
import { ChevronsUpDownIcon, Equal } from 'lucide-react';
import TokenCard from '../TokenCard';
import {
useDerivedSwapInfo,
useSwapActionHandlers,
useSwapState,
} from '@/state/swapStore';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useDerivedSwapInfo, useSwapState } from '@/state/swapStore';
import { useMemo } from 'react';
import { SwapField } from '@/types/swap-field';
import {
Currency,
INITIAL_POOL_FEE,
Token,
NonfungiblePositionManager,
computePoolAddress,
encodeSqrtRatioX96,
toHex,
} from '@cryptoalgebra/integral-sdk';
import { usePrepareAlgebraPositionManagerCreateAndInitializePoolIfNecessary } from '@/generated';
import { usePrepareAlgebraPositionManagerMulticall } from '@/generated';
import { useTransitionAwait } from '@/hooks/common/useTransactionAwait';
import { Address, useContractWrite } from 'wagmi';
import { useDerivedMintInfo, useMintActionHandlers } from '@/state/mintStore';
import { DEFAULT_CHAIN_ID } from '@/constants/default-chain-id';
import { useDerivedMintInfo } from '@/state/mintStore';
import Loader from '@/components/common/Loader';
import CurrencyLogo from '@/components/common/CurrencyLogo';
import { Skeleton } from '@/components/ui/skeleton';
import {
usePoolsListQuery,
useSingleTokenQuery,
} from '@/graphql/generated/graphql';
import { PoolState, usePool } from '@/hooks/pools/usePool';
import Summary from '../Summary';
import SelectPair from '../SelectPair';

const CreatePoolForm = () => {
const [isPoolExists, setIsPoolExists] = useState(false);
const [isSwapButtonVisible, setIsSwapButtonVisible] = useState(false);
const [suggestedPrice, setSuggestedPrice] = useState(0);

const { onCurrencySelection, onUserInput, onSwitchTokens } =
useSwapActionHandlers();

const { data: poolsList } = usePoolsListQuery();

const { currencies } = useDerivedSwapInfo();

const { typedValue } = useSwapState();

const currencyA = currencies[SwapField.INPUT];
const currencyB = currencies[SwapField.OUTPUT];

const token0 = currencyA?.wrapped.address.toLowerCase() as Address;
const token1 = currencyB?.wrapped.address.toLowerCase() as Address;

const { data: singleToken0 } = useSingleTokenQuery({
variables: {
tokenId: token0,
},
skip: !token0,
});

const { data: singleToken1 } = useSingleTokenQuery({
variables: {
tokenId: token1,
},
skip: !token1,
});

const isSameTokens = token0 === token1;

const poolAddress =
currencyA && currencyB && !isSameTokens
currencyA && currencyB
? (computePoolAddress({
tokenA: new Token(
DEFAULT_CHAIN_ID,
currencyA.wrapped.address,
currencyA.decimals
),
tokenB: new Token(
DEFAULT_CHAIN_ID,
currencyB.wrapped.address,
currencyB.decimals
),
tokenA: currencyA.wrapped,
tokenB: currencyB.wrapped,
}) as Address)
: undefined;

const [poolState] = usePool(poolAddress);

const isPoolExists = poolState === PoolState.EXISTS;

const mintInfo = useDerivedMintInfo(
currencyA ?? undefined,
currencyB ?? undefined,
Expand All @@ -90,172 +45,52 @@ const CreatePoolForm = () => {
undefined
);

const { onStartPriceInput } = useMintActionHandlers(mintInfo.noLiquidity);
const { calldata, value } = useMemo(() => {
if (!mintInfo?.pool)
return {
calldata: undefined,
value: undefined,
};

const [sortedToken0, sortedToken1] =
currencyA && currencyB && !isSameTokens
? currencyA.wrapped.sortsBefore(currencyB.wrapped)
? [token0, token1]
: [token1, token0]
: [undefined, undefined];

const sqrtRatioX96 = useMemo(() => {
if (!mintInfo.price) {
return undefined;
}
if (sortedToken0 === token0) {
return encodeSqrtRatioX96(
mintInfo.price.numerator,
mintInfo.price.denominator
);
} else if (sortedToken0 === token1) {
return encodeSqrtRatioX96(
mintInfo.price.denominator,
mintInfo.price.numerator
);
}
}, [sortedToken0, mintInfo.price, token0, token1]);
return NonfungiblePositionManager.createCallParameters(mintInfo.pool);
}, [mintInfo?.pool]);

const { config: createPoolConfig } =
usePrepareAlgebraPositionManagerCreateAndInitializePoolIfNecessary({
enabled: Boolean(token0 && token1 && sqrtRatioX96),
args:
sortedToken0 && sortedToken1 && sqrtRatioX96
? [sortedToken0, sortedToken1, BigInt(toHex(sqrtRatioX96))]
: undefined,
usePrepareAlgebraPositionManagerMulticall({
args: Array.isArray(calldata)
? [calldata as Address[]]
: [[calldata] as Address[]],
value: BigInt(value || 0),
enabled: Boolean(calldata),
});

const { data: createPoolData, write: createPool } =
useContractWrite(createPoolConfig);

const { isLoading } = useTransitionAwait(
createPoolData?.hash,
'Create Pool'
);

const handleInputSelect = useCallback(
(inputCurrency: Currency) => {
onCurrencySelection(SwapField.INPUT, inputCurrency);
},
[onCurrencySelection]
'Create Pool',
'',
'/pools'
);

const handleOutputSelect = useCallback(
(outputCurrency: Currency) => {
onCurrencySelection(SwapField.OUTPUT, outputCurrency);
},
[onCurrencySelection]
);

const handleTypeInput = useCallback(
(value: string) => {
onUserInput(SwapField.INPUT, value);
onStartPriceInput(value);
},
[onUserInput, onStartPriceInput]
);

useEffect(() => {
if (!poolsList) return;
if (!poolAddress) return;
const exist = poolsList.pools.find(
(pool) => pool.id.toLowerCase() === poolAddress?.toLowerCase()
);
if (!exist) {
setIsPoolExists(false);
return;
}
setIsPoolExists(true);
}, [poolAddress, poolsList, onSwitchTokens]);

useEffect(() => {
if (!singleToken0?.token || !singleToken1?.token) return;
if (
singleToken0.token.derivedMatic == 0 ||
singleToken1.token.derivedMatic == 0
) {
setSuggestedPrice(0);
return;
}

const suggstdPrice =
singleToken1.token.derivedMatic / singleToken0.token.derivedMatic;
const filteredSuggstdPrice = Number(suggstdPrice.toFixed(4));
setSuggestedPrice(filteredSuggstdPrice);
}, [singleToken0, singleToken1, onSwitchTokens]);

useEffect(() => {
console.log(sqrtRatioX96);
}, [sqrtRatioX96]);

return (
<div className="flex flex-col gap-4">
<h2 className="font-semibold text-2xl text-left ml-2 mt-2">
Select Pair
</h2>

<div className="flex flex-col gap-2 items-center">
<TokenCard
value={typedValue}
handleTokenSelection={handleInputSelect}
currency={currencyA}
otherCurrency={currencyB}
handleValueChange={handleTypeInput}
/>
{isSwapButtonVisible ? (
<ChevronsUpDownIcon
onClick={onSwitchTokens}
className="cursor-pointer animate-fade-in w-12"
onMouseLeave={() => setIsSwapButtonVisible(false)}
/>
) : (
<Equal
className="cursor-pointer w-12"
onMouseEnter={() => setIsSwapButtonVisible(true)}
/>
)}
<TokenCard
disabled
value={'1'}
currency={currencyB}
otherCurrency={currencyA}
handleTokenSelection={handleOutputSelect}
/>
</div>
<SelectPair
mintInfo={mintInfo}
currencyA={currencyA}
currencyB={currencyB}
/>

{!isPoolExists && (
<div className="flex flex-col gap-4">
<h2 className="font-semibold text-2xl text-left ml-2 ">
Summary
</h2>
<div className="flex items-center gap-4 ml-2 justify-between">
<div className="flex">
<CurrencyLogo currency={currencyA} size={30} />
<CurrencyLogo
currency={currencyB}
size={30}
className="-ml-2"
/>
</div>

{currencyA && currencyB ? (
<div className="mr-auto">{`${currencyA?.symbol} - ${currencyB?.symbol}`}</div>
) : (
<Skeleton className="h-[20px] w-[90px] bg-card" />
)}

<div>
{`1 ${currencyB?.symbol} = ${typedValue || 0} ${
currencyA?.symbol
}`}
</div>
</div>
{suggestedPrice > 0 && (
<div className="text-left ml-2 flex justify-between">
<p className="opacity-50">Suggested price:</p>
<p className="opacity-50">{` 1 ${currencyB?.symbol} = ${suggestedPrice} ${currencyA?.symbol}`}</p>
</div>
)}
<Summary currencyA={currencyA} currencyB={currencyB} />
</div>
)}

Expand Down
71 changes: 71 additions & 0 deletions src/components/create-pool/SelectPair/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import TokenCard from '@/components/swap/TokenCard';
import { IDerivedMintInfo, useMintActionHandlers } from '@/state/mintStore';
import { useSwapActionHandlers, useSwapState } from '@/state/swapStore';
import { SwapField } from '@/types/swap-field';
import { Currency } from '@cryptoalgebra/integral-sdk';
import { ChevronsUpDownIcon } from 'lucide-react';
import { useCallback } from 'react';

interface ISelectPair {
mintInfo: IDerivedMintInfo;
currencyA: Currency | undefined;
currencyB: Currency | undefined;
}

const SelectPair = ({ mintInfo, currencyA, currencyB }: ISelectPair) => {
const { onCurrencySelection, onUserInput, onSwitchTokens } =
useSwapActionHandlers();

const { onStartPriceInput } = useMintActionHandlers(mintInfo.noLiquidity);

const { typedValue } = useSwapState();

const handleInputSelect = useCallback(
(inputCurrency: Currency) => {
onCurrencySelection(SwapField.INPUT, inputCurrency);
},
[onCurrencySelection]
);

const handleOutputSelect = useCallback(
(outputCurrency: Currency) => {
onCurrencySelection(SwapField.OUTPUT, outputCurrency);
},
[onCurrencySelection]
);

const handleTypeInput = useCallback(
(value: string) => {
onUserInput(SwapField.INPUT, value);
onStartPriceInput(value);
},
[onUserInput, onStartPriceInput]
);
return (
<div className="flex flex-col gap-2 items-center">
<TokenCard
showBalance={false}
value={typedValue}
handleTokenSelection={handleInputSelect}
currency={currencyA}
otherCurrency={currencyB}
handleValueChange={handleTypeInput}
/>

<ChevronsUpDownIcon
onClick={onSwitchTokens}
className="cursor-pointer w-12"
/>

<TokenCard
disabled
value={'1'}
currency={currencyB}
otherCurrency={currencyA}
handleTokenSelection={handleOutputSelect}
/>
</div>
);
};

export default SelectPair;
Loading

0 comments on commit 07bad2b

Please sign in to comment.