From 077816386f78c0835c0e8152e31124ce04b156d9 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Fri, 6 Oct 2023 11:24:43 +0900 Subject: [PATCH 01/43] [GSW-371] fix: Manage slippage on local storage --- packages/web/src/hooks/common/use-slippage.ts | 30 +++++++++++++++++++ packages/web/src/states/common.ts | 3 ++ packages/web/src/utils/number-utils.ts | 9 ++++++ 3 files changed, 42 insertions(+) create mode 100644 packages/web/src/hooks/common/use-slippage.ts diff --git a/packages/web/src/hooks/common/use-slippage.ts b/packages/web/src/hooks/common/use-slippage.ts new file mode 100644 index 000000000..b38c9447c --- /dev/null +++ b/packages/web/src/hooks/common/use-slippage.ts @@ -0,0 +1,30 @@ +import { useAtom } from "jotai"; +import { CommonState } from "@states/index"; +import { useCallback } from "react"; +import { toDecimalNumber } from "@utils/number-utils"; + +const DEFAULT_SLIPPAGE = 0.5; + +export const useSlippage = () => { + const [slippage, setSlippage] = useAtom(CommonState.slippage); + + const changeSlippage = useCallback( + (slippage: number) => { + let changedSlippage = slippage; + if (slippage < 0) { + changedSlippage = 0; + } else if (slippage > 100) { + changedSlippage = 100; + } + changedSlippage = toDecimalNumber(changedSlippage); + setSlippage(changedSlippage); + }, + [setSlippage], + ); + + const resetSlippage = useCallback(() => { + setSlippage(DEFAULT_SLIPPAGE); + }, [setSlippage]); + + return { slippage, changeSlippage, resetSlippage }; +}; diff --git a/packages/web/src/states/common.ts b/packages/web/src/states/common.ts index c70a18af1..05f7c0665 100644 --- a/packages/web/src/states/common.ts +++ b/packages/web/src/states/common.ts @@ -2,6 +2,7 @@ import { NetworkModel } from "@models/common/network-model"; import { DEVICE_TYPE } from "@styles/media"; import { atom } from "jotai"; import NetworkData from "@resources/chains.json"; +import { atomWithStorage } from "jotai/utils"; interface HeaderToggleProps { walletConnect: boolean; @@ -20,3 +21,5 @@ export const modalContent = atom(null); export const breakpoint = atom(DEVICE_TYPE.WEB); export const network = atom(NetworkData[0]); + +export const slippage = atomWithStorage("slippage", 0.5); diff --git a/packages/web/src/utils/number-utils.ts b/packages/web/src/utils/number-utils.ts index 4e048966d..9099bc7c1 100644 --- a/packages/web/src/utils/number-utils.ts +++ b/packages/web/src/utils/number-utils.ts @@ -114,3 +114,12 @@ export const toUnitFormat = ( // TODO : Else Return Type return (usd ? "$" : "") + bigNumber.decimalPlaces(2).toString(); }; + +export function toDecimalNumber( + value: BigNumber | string | number, + decimals?: number, +) { + const powers = 10 ** (decimals || 0); + const num = BigNumber(value).toNumber(); + return Math.round(num * powers) / powers; +} From 185c1c92eeba487fd4d1fd9c8879528b1f22a705 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Fri, 6 Oct 2023 11:28:29 +0900 Subject: [PATCH 02/43] feat: Add Default slippage variable --- packages/web/src/constants/option.constant.ts | 2 ++ packages/web/src/hooks/common/use-slippage.ts | 3 +-- packages/web/src/states/common.ts | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/web/src/constants/option.constant.ts b/packages/web/src/constants/option.constant.ts index 31aaa7662..0ee43e036 100644 --- a/packages/web/src/constants/option.constant.ts +++ b/packages/web/src/constants/option.constant.ts @@ -77,3 +77,5 @@ export const PriceRangeTooltip: { "A passive price range of [-50% ~ +100%] for moderate risks & returns.", Custom: undefined, }; + +export const DEFAULT_SLIPPAGE = 0.5; diff --git a/packages/web/src/hooks/common/use-slippage.ts b/packages/web/src/hooks/common/use-slippage.ts index b38c9447c..92209b1e2 100644 --- a/packages/web/src/hooks/common/use-slippage.ts +++ b/packages/web/src/hooks/common/use-slippage.ts @@ -2,8 +2,7 @@ import { useAtom } from "jotai"; import { CommonState } from "@states/index"; import { useCallback } from "react"; import { toDecimalNumber } from "@utils/number-utils"; - -const DEFAULT_SLIPPAGE = 0.5; +import { DEFAULT_SLIPPAGE } from "@constants/option.constant"; export const useSlippage = () => { const [slippage, setSlippage] = useAtom(CommonState.slippage); diff --git a/packages/web/src/states/common.ts b/packages/web/src/states/common.ts index 05f7c0665..de41fa30e 100644 --- a/packages/web/src/states/common.ts +++ b/packages/web/src/states/common.ts @@ -3,6 +3,7 @@ import { DEVICE_TYPE } from "@styles/media"; import { atom } from "jotai"; import NetworkData from "@resources/chains.json"; import { atomWithStorage } from "jotai/utils"; +import { DEFAULT_SLIPPAGE } from "@constants/option.constant"; interface HeaderToggleProps { walletConnect: boolean; @@ -22,4 +23,4 @@ export const breakpoint = atom(DEVICE_TYPE.WEB); export const network = atom(NetworkData[0]); -export const slippage = atomWithStorage("slippage", 0.5); +export const slippage = atomWithStorage("slippage", DEFAULT_SLIPPAGE); From 1fa3b8b3d4ab18d17dae25b09a1a63858cb4203d Mon Sep 17 00:00:00 2001 From: jinoosss Date: Fri, 6 Oct 2023 11:30:38 +0900 Subject: [PATCH 03/43] fix: Fix Parameters --- packages/web/src/hooks/common/use-slippage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/hooks/common/use-slippage.ts b/packages/web/src/hooks/common/use-slippage.ts index 92209b1e2..ccae466c6 100644 --- a/packages/web/src/hooks/common/use-slippage.ts +++ b/packages/web/src/hooks/common/use-slippage.ts @@ -15,7 +15,7 @@ export const useSlippage = () => { } else if (slippage > 100) { changedSlippage = 100; } - changedSlippage = toDecimalNumber(changedSlippage); + changedSlippage = toDecimalNumber(changedSlippage, 2); setSlippage(changedSlippage); }, [setSlippage], From f818af76d159c27f6313ccde9dbd51f91e0a1cdb Mon Sep 17 00:00:00 2001 From: jinoosss Date: Thu, 12 Oct 2023 11:20:58 +0900 Subject: [PATCH 04/43] [GSW-371] fix: Simplify code --- packages/web/src/hooks/common/use-slippage.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/web/src/hooks/common/use-slippage.ts b/packages/web/src/hooks/common/use-slippage.ts index ccae466c6..0e9f865f2 100644 --- a/packages/web/src/hooks/common/use-slippage.ts +++ b/packages/web/src/hooks/common/use-slippage.ts @@ -1,7 +1,6 @@ import { useAtom } from "jotai"; import { CommonState } from "@states/index"; import { useCallback } from "react"; -import { toDecimalNumber } from "@utils/number-utils"; import { DEFAULT_SLIPPAGE } from "@constants/option.constant"; export const useSlippage = () => { @@ -9,13 +8,7 @@ export const useSlippage = () => { const changeSlippage = useCallback( (slippage: number) => { - let changedSlippage = slippage; - if (slippage < 0) { - changedSlippage = 0; - } else if (slippage > 100) { - changedSlippage = 100; - } - changedSlippage = toDecimalNumber(changedSlippage, 2); + const changedSlippage = Math.min(100, Math.max(0, slippage)); setSlippage(changedSlippage); }, [setSlippage], From e049c7e10e3d9b68e93d2abdf03b0e8f1ff21b45 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Thu, 12 Oct 2023 16:21:27 +0900 Subject: [PATCH 05/43] [GSW-323] chore: Add Storybook build option --- packages/web/.storybook/main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/web/.storybook/main.js b/packages/web/.storybook/main.js index 247f34afc..f52e68e7f 100644 --- a/packages/web/.storybook/main.js +++ b/packages/web/.storybook/main.js @@ -21,6 +21,9 @@ module.exports = { }, }); return merge(config, { + experiments: { + topLevelAwait: true, + }, resolve: { plugins: [new TsconfigPathsPlugin()], }, From 066843b5f7e2ab36408df64ae3c754c90d5190fc Mon Sep 17 00:00:00 2001 From: jinoosss Date: Thu, 12 Oct 2023 16:23:08 +0900 Subject: [PATCH 06/43] [GSW-323] feat: Change Token price data --- .../web/src/hooks/token/use-token-data.tsx | 23 ++-- .../web/src/models/token/token-price-model.ts | 16 +-- .../repositories/token/mock/token-prices.json | 100 ++++++------------ .../response/token-price-list-response.ts | 4 +- .../token/token-repository-impl.ts | 2 +- 5 files changed, 62 insertions(+), 83 deletions(-) diff --git a/packages/web/src/hooks/token/use-token-data.tsx b/packages/web/src/hooks/token/use-token-data.tsx index 9c0c2d465..5a9455b4e 100644 --- a/packages/web/src/hooks/token/use-token-data.tsx +++ b/packages/web/src/hooks/token/use-token-data.tsx @@ -2,11 +2,12 @@ import { useGnoswapContext } from "@hooks/common/use-gnoswap-context"; import { useWallet } from "@hooks/wallet/use-wallet"; import { CardListTokenInfo } from "@models/common/card-list-item-info"; import { TokenModel } from "@models/token/token-model"; +import { TokenPriceModel } from "@models/token/token-price-model"; import { TokenState } from "@states/index"; import { evaluateExpressionToNumber } from "@utils/rpc-utils"; import BigNumber from "bignumber.js"; import { useAtom } from "jotai"; -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; export const useTokenData = () => { const { account } = useWallet(); @@ -15,10 +16,16 @@ export const useTokenData = () => { const [tokenPrices, setTokenPrices] = useAtom(TokenState.tokenPrices); const [balances, setBalances] = useAtom(TokenState.balances); + useEffect(() => { + if (rpcProvider && account) { + updateBalances(); + } + }, [rpcProvider, account]); + const trendingTokens: CardListTokenInfo[] = useMemo(() => { const sortedTokens = tokens.sort((t1, t2) => { if (tokenPrices[t1.priceId] && tokenPrices[t2.priceId]) { - return tokenPrices[t2.priceId].volume - tokenPrices[t1.priceId].volume; + return BigNumber(tokenPrices[t2.priceId].volume).toNumber() - BigNumber(tokenPrices[t1.priceId].volume).toNumber(); } if (tokenPrices[t2.priceId]) { return 1; @@ -31,8 +38,8 @@ export const useTokenData = () => { return sortedTokens.map(token => ( tokenPrices[token.priceId] ? { token, - upDown: tokenPrices[token.priceId].changedBefore1D > 0 ? "up" : "down", - content: `${BigNumber(tokenPrices[token.priceId].changedBefore1D).toFixed()}%` + upDown: BigNumber(tokenPrices[token.priceId].change1d).isPositive() ? "up" : "down", + content: `${BigNumber(tokenPrices[token.priceId].change1d).toFixed()}%` } : { token, upDown: "none", @@ -65,7 +72,11 @@ export const useTokenData = () => { async function updateTokenPrices() { const response = await tokenRepository.getTokenPrices(); - setTokenPrices(response.prices); + const priceMap = response.prices.reduce>((prev, current) => { + prev[current.path] = current; + return prev; + }, {}); + setTokenPrices(priceMap); } async function updateBalances() { @@ -85,7 +96,7 @@ export const useTokenData = () => { const balances: Record = {}; fetchResults.forEach((result, index) => { if (index < tokens.length) { - balances[tokens[index].priceId] = result; + balances[tokens[index].path] = result; } }); setBalances(balances); diff --git a/packages/web/src/models/token/token-price-model.ts b/packages/web/src/models/token/token-price-model.ts index 6f75c5c3b..d2b35a90e 100644 --- a/packages/web/src/models/token/token-price-model.ts +++ b/packages/web/src/models/token/token-price-model.ts @@ -1,9 +1,11 @@ export interface TokenPriceModel { - usd: number; - changedBefore1D: number; - changedBefore7D: number; - changedBefore30D: number; - marketCap: number; - liquidity: number; - volume: number; + path: string; + usd: string; + change1h: string; + change1d: string; + change7d: string; + change30d: string; + marketCap: string; + liquidity: string; + volume: string; } diff --git a/packages/web/src/repositories/token/mock/token-prices.json b/packages/web/src/repositories/token/mock/token-prices.json index eb35bb4c6..8e12b7bfe 100644 --- a/packages/web/src/repositories/token/mock/token-prices.json +++ b/packages/web/src/repositories/token/mock/token-prices.json @@ -1,73 +1,41 @@ { - "message": "Successful", - "count": 7, "meta": { - "timestamp": 1695363312078, - "ageRaw": 56 + "height": "94", + "timestamp": "2023-10-10T17:51:46+09:00" }, - "prices": { - "1inch": { - "usd": 0.03077532, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 + "prices": [ + { + "path": "gno.land/r/bar", + "usd": "1.000000", + "change1h": "0.000000", + "change1d": "0.000000", + "change7d": "0.000000", + "change30d": "0.000000", + "marketCap": "110200000000.000000", + "liquidity": "195871.000000", + "volume": "195886.000000" }, - "usd-coin": { - "usd": 0.999292, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 + { + "path": "gno.land/r/foo", + "usd": "0.074070", + "change1h": "0.000000", + "change1d": "0.000000", + "change7d": "0.000000", + "change30d": "0.000000", + "marketCap": "8162479867.948110", + "liquidity": "195871.000000", + "volume": "195871.000000" }, - "weth": { - "usd": 1592.57, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 - }, - "uniswap": { - "usd": 4.23, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 - }, - "ethereum": { - "usd": 1618.72, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 - }, - "wrapped-bitcoin": { - "usd": 26598, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 - }, - "wrapped-steth": { - "usd": 1814.66, - "changedBefore1D": 19.92, - "changedBefore7D": -12.09, - "changedBefore30D": 19.12, - "marketCap": 31142124125500000000, - "liquidity": 1421241255, - "volume": 311421241 + { + "path": "gno.land/r/bar", + "usd": "1.000000", + "change1h": "0.000000", + "change1d": "0.000000", + "change7d": "0.000000", + "change30d": "0.000000", + "marketCap": "110200000000.000000", + "liquidity": "195871.000000", + "volume": "195886.000000" } - } + ] } diff --git a/packages/web/src/repositories/token/response/token-price-list-response.ts b/packages/web/src/repositories/token/response/token-price-list-response.ts index 9049efa9f..25f7b0407 100644 --- a/packages/web/src/repositories/token/response/token-price-list-response.ts +++ b/packages/web/src/repositories/token/response/token-price-list-response.ts @@ -1,7 +1,5 @@ import { TokenPriceModel } from "@models/token/token-price-model"; export interface TokenPriceListResponse { - prices: { - [tokenPriceId in string]: TokenPriceModel; - }; + prices: TokenPriceModel[]; } diff --git a/packages/web/src/repositories/token/token-repository-impl.ts b/packages/web/src/repositories/token/token-repository-impl.ts index 33032391b..0867418c7 100644 --- a/packages/web/src/repositories/token/token-repository-impl.ts +++ b/packages/web/src/repositories/token/token-repository-impl.ts @@ -31,7 +31,7 @@ export class TokenRepositoryImpl implements TokenRepository { public getTokenPrices = async (): Promise => { const response = await this.networkClient.get({ - url: "/tokenPrice", + url: "/tokenPrices", }); return response.data; }; From aa3fe85c8fd8f3ef13a1315295af663876f81b77 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Thu, 12 Oct 2023 16:24:29 +0900 Subject: [PATCH 07/43] [GSW-323] fix: Fix ABCI Response Parser --- packages/web/src/utils/rpc-utils.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/web/src/utils/rpc-utils.ts b/packages/web/src/utils/rpc-utils.ts index 5f639ad8e..f04044afb 100644 --- a/packages/web/src/utils/rpc-utils.ts +++ b/packages/web/src/utils/rpc-utils.ts @@ -2,14 +2,14 @@ import BigNumber from "bignumber.js"; export function evaluateExpressionToNumber(evaluateExpression: string) { try { - const regexp = /(.*?)/; - const result = Array.from( - evaluateExpression.matchAll(regexp), - match => `${match[0]}`, - ); - if (result.length > 0) { - return BigNumber(result[0]).toNumber(); + const regexp = /\((.*)\)/; + const result = evaluateExpression.match(regexp); + if (result === null || result.length < 1) { + return 0; } + + const parsedValue = result[1].split(" ")[0]; + return BigNumber(parsedValue).toNumber(); } catch { console.log("Parse Error: " + evaluateExpression); } From 32ae7edccdfb26448244acaf252778ae7508cbb4 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Thu, 12 Oct 2023 16:47:58 +0900 Subject: [PATCH 08/43] [GSW-323] feat: Update Parameters --- .../LiquidityEnterAmounts.stories.tsx | 24 +++---- .../LiquidityEnterAmounts.tsx | 22 +++---- .../components/common/modal/Modal.styles.ts | 1 + .../common/pool-graph/PoolGraph.stories.tsx | 6 +- .../select-fee-tier/SelectFeeTier.stories.tsx | 4 +- .../common/select-fee-tier/SelectFeeTier.tsx | 64 +++++++++++-------- .../SelectPairButton.stories.tsx | 14 ++-- .../select-pair-button/SelectPairButton.tsx | 6 +- .../common/select-pair/SelectPair.stories.tsx | 27 +++++--- .../common/select-pair/SelectPair.tsx | 18 +++--- .../SelectPriceRange.stories.tsx | 6 +- .../select-price-range/SelectPriceRange.tsx | 46 ++++++------- .../common/select-token/SelectToken.spec.tsx | 2 +- .../TokenAmountInput.spec.tsx | 14 ++-- .../TokenAmountInput.stories.tsx | 14 ++-- .../token-amount-input/TokenAmountInput.tsx | 4 +- .../common/token-amount/TokenAmount.spec.tsx | 13 ++-- .../token-amount/TokenAmount.stories.tsx | 13 ++-- .../common/token-amount/TokenAmount.tsx | 4 +- 19 files changed, 169 insertions(+), 133 deletions(-) diff --git a/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.stories.tsx b/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.stories.tsx index 383a3bf02..16f7a4637 100644 --- a/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.stories.tsx +++ b/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.stories.tsx @@ -17,31 +17,33 @@ const Template: ComponentStory = args => ( ); const token = { - path: "1", - name: "HEX", - symbol: "HEX", - logoURI: - "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png", + "chainId": "test3", + "address": "0x111111111117dC0aa78b770fA6A738034120C302", + "path": "gno.land/r/demo/1inch", + "name": "1inch", + "symbol": "1INCH", + "decimals": 6, + "logoURI": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceId": "1inch", + "createdAt": "1999-01-01T00:00:01Z" }; export const Default = Template.bind({}); Default.args = { - token0Input: { + tokenAInput: { token: token, amount: "121", usdValue: "$0.00", balance: "0", changeAmount: action("changeAmount"), - changeBalance: action("changeBalance"), }, - token1Input: { + tokenBInput: { token: token, amount: "121", usdValue: "$0.00", balance: "0", changeAmount: action("changeAmount"), - changeBalance: action("changeBalance"), }, - changeToken0: action("changeToken0"), - changeToken1: action("changeToken1"), + changeTokenA: action("changeTokenA"), + changeTokenB: action("changeTokenB"), }; diff --git a/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx b/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx index ad42f7ad7..f04ccc1d8 100644 --- a/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx +++ b/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx @@ -3,26 +3,26 @@ import IconAdd from "../icons/IconAdd"; import { LiquidityEnterAmountsWrapper } from "./LiquidityEnterAmounts.styles"; import TokenAmountInput from "../token-amount-input/TokenAmountInput"; import { TokenAmountInputModel } from "@hooks/token/use-token-amount-input"; -import { TokenInfo } from "@models/token/token-info"; +import { TokenModel } from "@models/token/token-model"; interface LiquidityEnterAmountsProps { - token0Input: TokenAmountInputModel; - token1Input: TokenAmountInputModel; - changeToken0: (token: TokenInfo) => void; - changeToken1: (token: TokenInfo) => void; + tokenAInput: TokenAmountInputModel; + tokenBInput: TokenAmountInputModel; + changeTokenA: (token: TokenModel) => void; + changeTokenB: (token: TokenModel) => void; } const LiquidityEnterAmounts: React.FC = ({ - token0Input, - token1Input, - changeToken0, - changeToken1, + tokenAInput, + tokenBInput, + changeTokenA, + changeTokenB, }) => { return ( - - + +
diff --git a/packages/web/src/components/common/modal/Modal.styles.ts b/packages/web/src/components/common/modal/Modal.styles.ts index 21c13b91e..d07bdb840 100644 --- a/packages/web/src/components/common/modal/Modal.styles.ts +++ b/packages/web/src/components/common/modal/Modal.styles.ts @@ -24,6 +24,7 @@ export const ModalWrapper = styled.div` }}; padding: 24px; ${mixins.positionCenter()}; + position: fixed; z-index: ${Z_INDEX.modal}; background-color: ${({ theme }) => theme.color.background06}; border: 1px solid ${({ theme }) => theme.color.border02}; diff --git a/packages/web/src/components/common/pool-graph/PoolGraph.stories.tsx b/packages/web/src/components/common/pool-graph/PoolGraph.stories.tsx index b4c82a3e7..10969c413 100644 --- a/packages/web/src/components/common/pool-graph/PoolGraph.stories.tsx +++ b/packages/web/src/components/common/pool-graph/PoolGraph.stories.tsx @@ -1,4 +1,3 @@ -import { DUMMY_POOL_TICKS } from "@containers/earn-add-liquidity-container/earn-add-liquidity-dummy"; import PoolGraph, { type PoolGraphProps } from "./PoolGraph"; import { Meta, StoryObj } from "@storybook/react"; import { action } from "@storybook/addon-actions"; @@ -10,12 +9,9 @@ export default { export const Default: StoryObj = { args: { - ticks: DUMMY_POOL_TICKS, - currentTick: DUMMY_POOL_TICKS[20], + ticks: [], width: 400, height: 200, - minTick: DUMMY_POOL_TICKS[10], - maxTick: DUMMY_POOL_TICKS[30], onChangeMinTick: action("onChangeMinTick"), onChangeMaxTick: action("onChangeMaxTick"), }, diff --git a/packages/web/src/components/common/select-fee-tier/SelectFeeTier.stories.tsx b/packages/web/src/components/common/select-fee-tier/SelectFeeTier.stories.tsx index 5f10a9fa9..f1193c354 100644 --- a/packages/web/src/components/common/select-fee-tier/SelectFeeTier.stories.tsx +++ b/packages/web/src/components/common/select-fee-tier/SelectFeeTier.stories.tsx @@ -2,7 +2,6 @@ import React from "react"; import { ComponentStory, ComponentMeta } from "@storybook/react"; import SelectFeeTier from "./SelectFeeTier"; import { action } from "@storybook/addon-actions"; -import { DUMMY_FEE_TIERS } from "@containers/earn-add-liquidity-container/earn-add-liquidity-dummy"; export default { title: "common/AddLiquidity/SelectFeeTier", @@ -15,7 +14,6 @@ const Template: ComponentStory = args => ( export const Default = Template.bind({}); Default.args = { - feeTiers: DUMMY_FEE_TIERS, - feeRate: "0.01", + feeTiers: [], selectFeeTier: action("selectFeeTier"), }; diff --git a/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx b/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx index 3a04f184b..f68beca5f 100644 --- a/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx +++ b/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx @@ -1,65 +1,77 @@ import React, { useCallback, useMemo } from "react"; import { SelectFeeTierItemWrapper, SelectFeeTierWrapper } from "./SelectFeeTier.styles"; -import { AddLiquidityFeeTier } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; -import { FEE_RATE_OPTION } from "@constants/option.constant"; +import { SwapFeeTierInfoMap, SwapFeeTierType } from "@constants/option.constant"; +import { PoolModel } from "@models/pool/pool-model"; +import BigNumber from "bignumber.js"; interface SelectFeeTierProps { - feeTiers: AddLiquidityFeeTier[]; - feeRate: string | undefined; - selectFeeTier: (feeRate: FEE_RATE_OPTION) => void; + feeTiers: SwapFeeTierType[]; + feeTier: SwapFeeTierType | null; + pools: PoolModel[], + selectFeeTier: (feeTier: SwapFeeTierType) => void; } const SelectFeeTier: React.FC = ({ feeTiers, - feeRate, + feeTier, + pools, selectFeeTier, }) => { - const onClickFeeTierItem = useCallback((feeRate: string) => { - const feeRateOption = Object.values(FEE_RATE_OPTION).find(option => option === feeRate); - if (feeRateOption) { - selectFeeTier(feeRateOption); - } + const onClickFeeTierItem = useCallback((feeTier: SwapFeeTierType) => { + selectFeeTier(feeTier); }, [selectFeeTier]); return ( - {feeTiers.map((feeTier, index) => ( + {feeTiers.map((item, index) => ( onClickFeeTierItem(feeTier.feeRate)} + selected={feeTier === item} + feeTier={item} + pools={pools} + onClick={() => onClickFeeTierItem(item)} /> ))} ); }; -interface SelectFeeTierItemProps extends AddLiquidityFeeTier { +interface SelectFeeTierItemProps { selected: boolean; + feeTier: SwapFeeTierType; + pools: PoolModel[]; onClick: () => void; } const SelectFeeTierItem: React.FC = ({ selected, - feeRate, - description, - range, + feeTier, + pools, onClick, }) => { const feeRateStr = useMemo(() => { - return `${feeRate}%`; - }, [feeRate]); + return SwapFeeTierInfoMap[feeTier].rateStr; + }, [feeTier]); const rangeStr = useMemo(() => { - if (range === "0") { + const fee = SwapFeeTierInfoMap[feeTier].fee; + const pool = pools.find(pool => pool.fee === fee); + if (!pool || pool.bins.length < 2) { return "Not created"; } - return `${range}% select`; - }, [range]); + const sortedBins = pool.bins.sort((p1, p2) => p1.currentTick - p2.currentTick); + const fullTickRange = 1774545; + const currentTickGap = sortedBins[0].currentTick - sortedBins[sortedBins.length - 1].currentTick; + return BigNumber(currentTickGap) + .dividedBy(fullTickRange) + .multipliedBy(100) + .toFixed(); + }, [feeTier, pools]); + + const description = useMemo(() => { + return SwapFeeTierInfoMap[feeTier].description; + }, [feeTier]); return ( diff --git a/packages/web/src/components/common/select-pair-button/SelectPairButton.stories.tsx b/packages/web/src/components/common/select-pair-button/SelectPairButton.stories.tsx index 8743ca9f0..661a03cd3 100644 --- a/packages/web/src/components/common/select-pair-button/SelectPairButton.stories.tsx +++ b/packages/web/src/components/common/select-pair-button/SelectPairButton.stories.tsx @@ -15,11 +15,15 @@ const Template: ComponentStory = args => ( export const Selected = Template.bind({}); Selected.args = { token: { - path: Math.floor(Math.random() * 50 + 1).toString(), - name: "HEX", - symbol: "HEX", - logoURI: - "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png", + chainId: "test3", + address: "0x111111111117dC0aa78b770fA6A738034120C302", + path: "gno.land/r/demo/1inch", + name: "1inch", + symbol: "1INCH", + decimals: 6, + logoURI: "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + priceId: "1inch", + createdAt: "1999-01-01T00:00:01Z" }, }; diff --git a/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx b/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx index 6c4f06662..daad47884 100644 --- a/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx +++ b/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx @@ -1,12 +1,12 @@ import React, { useCallback } from "react"; import IconStrokeArrowDown from "@components/common/icons/IconStrokeArrowDown"; import { wrapper } from "./SelectPairButton.styles"; -import { TokenInfo } from "@models/token/token-info"; import { useSelectTokenModal } from "@hooks/token/use-select-token-modal"; +import { TokenModel } from "@models/token/token-model"; interface SelectPairButtonProps { - token?: TokenInfo; - changeToken?: (token: TokenInfo) => void; + token: TokenModel | null; + changeToken?: (token: TokenModel) => void; disabled?: boolean; } diff --git a/packages/web/src/components/common/select-pair/SelectPair.stories.tsx b/packages/web/src/components/common/select-pair/SelectPair.stories.tsx index 5ec79c943..731d697f3 100644 --- a/packages/web/src/components/common/select-pair/SelectPair.stories.tsx +++ b/packages/web/src/components/common/select-pair/SelectPair.stories.tsx @@ -13,17 +13,28 @@ const Template: ComponentStory = args => ( ); const tokenA = { - path: "0", - name: "HEX", - symbol: "HEX", - logoURI: "", + chainId: "test3", + address: "0x111111111117dC0aa78b770fA6A738034120C302", + path: "gno.land/r/demo/1inch", + name: "1inch", + symbol: "1INCH", + decimals: 6, + logoURI: "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + priceId: "1inch", + createdAt: "1999-01-01T00:00:01Z" }; const tokenB = { - path: "1", - name: "USDCoin", - symbol: "USDC", - logoURI: "", + name: "Wrapped Ether", + address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + path: "gno.land/r/demo/weth", + symbol: "WETH", + decimals: 6, + chainId: "test3", + priceId: "weth", + createdAt: "1999-01-01T00:00:02Z", + isWrappedGasToken: true, + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/2396.png" }; export const Default = Template.bind({}); diff --git a/packages/web/src/components/common/select-pair/SelectPair.tsx b/packages/web/src/components/common/select-pair/SelectPair.tsx index 544cda1f0..e1f940429 100644 --- a/packages/web/src/components/common/select-pair/SelectPair.tsx +++ b/packages/web/src/components/common/select-pair/SelectPair.tsx @@ -1,28 +1,28 @@ import React from "react"; import SelectPairButton from "@components/common/select-pair-button/SelectPairButton"; import { SelectPairWrapper } from "./SelectPair.styles"; -import { TokenInfo } from "@models/token/token-info"; +import { TokenModel } from "@models/token/token-model"; interface SelectPairProps { - tokenA: TokenInfo | undefined; - tokenB: TokenInfo | undefined; - changeToken0: (token: TokenInfo) => void; - changeToken1: (token: TokenInfo) => void; + tokenA: TokenModel | null; + tokenB: TokenModel | null; + changeTokenA: (token: TokenModel) => void; + changeTokenB: (token: TokenModel) => void; disabled?: boolean; } const SelectPair: React.FC = ({ tokenA, tokenB, - changeToken0, - changeToken1, + changeTokenA, + changeTokenB, disabled, }) => { return ( - - + + ); }; diff --git a/packages/web/src/components/common/select-price-range/SelectPriceRange.stories.tsx b/packages/web/src/components/common/select-price-range/SelectPriceRange.stories.tsx index 6a2ec1f53..9ae6d48ad 100644 --- a/packages/web/src/components/common/select-price-range/SelectPriceRange.stories.tsx +++ b/packages/web/src/components/common/select-price-range/SelectPriceRange.stories.tsx @@ -1,9 +1,7 @@ import React from "react"; import { ComponentStory, ComponentMeta } from "@storybook/react"; - import SelectPriceRange from "./SelectPriceRange"; import { action } from "@storybook/addon-actions"; -import { DUMMY_PRICE_RANGE_MAP } from "@containers/earn-add-liquidity-container/earn-add-liquidity-dummy"; export default { title: "common/AddLiquidity/SelectPriceRange", @@ -16,7 +14,7 @@ const Template: ComponentStory = args => ( export const Default = Template.bind({}); Default.args = { - priceRangeMap: DUMMY_PRICE_RANGE_MAP, + priceRanges: [], priceRange: undefined, - selectPriceRange: action("selectPriceRange"), + changePriceRange: action("changePriceRange"), }; diff --git a/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx b/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx index 194006299..08d4f94c2 100644 --- a/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx +++ b/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx @@ -1,4 +1,4 @@ -import { PriceRangeTooltip, PriceRangeType } from "@constants/option.constant"; +import { PriceRangeTooltip } from "@constants/option.constant"; import React, { useCallback, useMemo } from "react"; import IconInfo from "@components/common/icons/IconInfo"; import IconStrokeArrowRight from "@components/common/icons/IconStrokeArrowRight"; @@ -7,30 +7,27 @@ import { SelectPriceRangeItemWrapper, SelectPriceRangeWrapper } from "./SelectPr import { AddLiquidityPriceRage } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; interface SelectPriceRangeProps { - priceRangeMap: { [key in PriceRangeType]: AddLiquidityPriceRage | undefined }; - priceRange: PriceRangeType | undefined; - selectPriceRange: (priceRange: PriceRangeType) => void; + priceRanges: AddLiquidityPriceRage[]; + priceRange: AddLiquidityPriceRage | null; + changePriceRange: (priceRange: AddLiquidityPriceRage) => void; } -const PRICE_RANGE_ORDERS: PriceRangeType[] = ["Active", "Passive", "Custom"]; - const SelectPriceRange: React.FC = ({ - priceRangeMap, + priceRanges, priceRange, - selectPriceRange, + changePriceRange, }) => { return (
- {PRICE_RANGE_ORDERS.map((priceRangeType, index: number) => ( + {priceRanges.map((item, index) => ( ))}
@@ -40,37 +37,36 @@ const SelectPriceRange: React.FC = ({ interface SelectPriceRangeItemProps { selected: boolean; - priceRage: PriceRangeType; + priceRange: AddLiquidityPriceRage; tooltip: string | undefined; - apr: string | undefined; - selectPriceRange: (priceRange: PriceRangeType) => void; + changePriceRange: (priceRange: AddLiquidityPriceRage) => void; } export const SelectPriceRangeItem: React.FC = ({ selected, - priceRage, + priceRange, tooltip, - apr, - selectPriceRange, + changePriceRange, }) => { const aprStr = useMemo(() => { + const apr = priceRange.apr; if (apr) { return `${apr}%`; } - if (priceRage === "Custom") { + if (priceRange.type === "Custom") { return null; } return "-"; - }, [apr, priceRage]); + }, [priceRange]); const onClickItem = useCallback(() => { - selectPriceRange(priceRage); - }, [priceRage, selectPriceRange]); + changePriceRange(priceRange); + }, [priceRange, changePriceRange]); return ( - {priceRage} + {priceRange.type} {tooltip && (
{ keyword: "", defaultTokens: [], tokens: [], - tokenPrices: [], + tokenPrices: {}, changeKeyword: () => { return; }, changeToken: () => { return; }, close: () => { return; }, diff --git a/packages/web/src/components/common/token-amount-input/TokenAmountInput.spec.tsx b/packages/web/src/components/common/token-amount-input/TokenAmountInput.spec.tsx index af0b1e9dc..d02b67481 100644 --- a/packages/web/src/components/common/token-amount-input/TokenAmountInput.spec.tsx +++ b/packages/web/src/components/common/token-amount-input/TokenAmountInput.spec.tsx @@ -4,10 +4,15 @@ import GnoswapThemeProvider from "@providers/gnoswap-theme-provider/GnoswapTheme import TokenAmountInput, { TokenAmountInputProps } from "./TokenAmountInput"; const token = { - path: "1", - name: "Gnoland", - symbol: "GNO.LAND", - logoURI: "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOS", + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/5994.png", + priceId: "gno.land/r/gnos" }; describe("TokenAmountInput Component", () => { @@ -18,7 +23,6 @@ describe("TokenAmountInput Component", () => { balance: "12,211", usdValue: "12.3", changable: true, - changeBalance: () => { return; }, changeAmount: () => { return; }, changeToken: () => { return; }, }; diff --git a/packages/web/src/components/common/token-amount-input/TokenAmountInput.stories.tsx b/packages/web/src/components/common/token-amount-input/TokenAmountInput.stories.tsx index e16b0e090..e230e47e8 100644 --- a/packages/web/src/components/common/token-amount-input/TokenAmountInput.stories.tsx +++ b/packages/web/src/components/common/token-amount-input/TokenAmountInput.stories.tsx @@ -8,10 +8,15 @@ export default { } as Meta; const token = { - path: "1", - name: "Gnoland", - symbol: "GNO.LAND", - logoURI: "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOS", + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/5994.png", + priceId: "gno.land/r/gnos" }; export const Default: StoryObj = { @@ -21,7 +26,6 @@ export const Default: StoryObj = { balance: "12,211", usdValue: "12.3", changable: true, - changeBalance: action("changeBalance"), changeAmount: action("changeAmount"), changeToken: action("changeToken"), }, diff --git a/packages/web/src/components/common/token-amount-input/TokenAmountInput.tsx b/packages/web/src/components/common/token-amount-input/TokenAmountInput.tsx index 58d0e19bd..26a03ac37 100644 --- a/packages/web/src/components/common/token-amount-input/TokenAmountInput.tsx +++ b/packages/web/src/components/common/token-amount-input/TokenAmountInput.tsx @@ -3,11 +3,11 @@ import { TokenAmountInputWrapper } from "./TokenAmountInput.styles"; import SelectPairButton from "../select-pair-button/SelectPairButton"; import BigNumber from "bignumber.js"; import { TokenAmountInputModel } from "@hooks/token/use-token-amount-input"; -import { TokenInfo } from "@models/token/token-info"; +import { TokenModel } from "@models/token/token-model"; export interface TokenAmountInputProps extends TokenAmountInputModel { changable?: boolean; - changeToken: (token: TokenInfo) => void; + changeToken: (token: TokenModel) => void; } const TokenAmountInput: React.FC = ({ diff --git a/packages/web/src/components/common/token-amount/TokenAmount.spec.tsx b/packages/web/src/components/common/token-amount/TokenAmount.spec.tsx index 13ebeb6b0..3bd07b0ac 100644 --- a/packages/web/src/components/common/token-amount/TokenAmount.spec.tsx +++ b/packages/web/src/components/common/token-amount/TokenAmount.spec.tsx @@ -4,10 +4,15 @@ import GnoswapThemeProvider from "@providers/gnoswap-theme-provider/GnoswapTheme import TokenAmount, { TokenAmountProps } from "./TokenAmount"; const token = { - path: "1", - name: "Gnoland", - symbol: "GNO.LAND", - logoURI: "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOS", + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/5994.png", + priceId: "gno.land/r/gnos" }; describe("TokenAmount Component", () => { diff --git a/packages/web/src/components/common/token-amount/TokenAmount.stories.tsx b/packages/web/src/components/common/token-amount/TokenAmount.stories.tsx index 9224b6870..88c16fc8e 100644 --- a/packages/web/src/components/common/token-amount/TokenAmount.stories.tsx +++ b/packages/web/src/components/common/token-amount/TokenAmount.stories.tsx @@ -7,10 +7,15 @@ export default { } as Meta; const token = { - path: "1", - name: "Gnoland", - symbol: "GNO.LAND", - logoURI: "", + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOS", + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/5994.png", + priceId: "gno.land/r/gnos" }; export const Default: StoryObj = { diff --git a/packages/web/src/components/common/token-amount/TokenAmount.tsx b/packages/web/src/components/common/token-amount/TokenAmount.tsx index 51b0d2fbd..5e85a8402 100644 --- a/packages/web/src/components/common/token-amount/TokenAmount.tsx +++ b/packages/web/src/components/common/token-amount/TokenAmount.tsx @@ -1,10 +1,10 @@ import React from "react"; import { TokenAmountWrapper } from "./TokenAmount.styles"; import SelectPairButton from "../select-pair-button/SelectPairButton"; -import { TokenInfo } from "@models/token/token-info"; +import { TokenModel } from "@models/token/token-model"; export interface TokenAmountProps { - token: TokenInfo; + token: TokenModel; usdPrice: string; amount: string; } From c3d19197244cb42af697e65a2ff72778fac7c3ee Mon Sep 17 00:00:00 2001 From: jinoosss Date: Thu, 12 Oct 2023 16:48:24 +0900 Subject: [PATCH 09/43] [GSW-323] feat: Create Pool --- .../EarnAddConfirmAmountInfo.stories.tsx | 13 +- .../EarnAddConfirmAmountInfo.tsx | 6 +- .../EarnAddConfirm.stories.tsx | 26 +- .../earn-add-confirm/EarnAddConfirm.styles.ts | 7 +- .../earn-add-confirm/EarnAddConfirm.tsx | 8 +- .../EarnAddLiquidity.stories.tsx | 38 +-- .../earn-add-liquidity/EarnAddLiquidity.tsx | 151 +++++----- .../home/home-swap/HomeSwap.stories.tsx | 28 +- .../token/token-swap/TokenSwap.spec.tsx | 46 --- .../token/token-swap/TokenSwap.stories.tsx | 28 +- .../components/token/token-swap/TokenSwap.tsx | 6 +- packages/web/src/constants/option.constant.ts | 49 +++- .../BestPoolsContainer.tsx | 6 +- .../EarnAddLiquidityContainer.tsx | 181 +++++++----- .../earn-add-liquidity-dummy.ts | 263 ------------------ .../home-swap-container/HomeSwapContainer.tsx | 28 +- .../SelectTokenContainer.tsx | 3 +- .../TokenSwapContainer.tsx | 28 +- packages/web/src/hooks/pool/use-pool.tsx | 55 ++++ .../use-earn-add-liquidity-confirm-modal.tsx | 138 +++++++++ .../hooks/token/use-select-token-modal.tsx | 4 +- .../hooks/token/use-token-amount-input.tsx | 39 ++- packages/web/src/hooks/wallet/use-wallet.ts | 15 +- .../swap/{ => info}/swap-confirm-model.ts | 0 .../web/src/models/swap/swap-fee-tier-info.ts | 6 + .../web/src/models/swap/swap-token-model.ts | 4 +- .../GnoswapServiceProvider.tsx | 6 +- .../repositories/pool/pool-repository-impl.ts | 146 +++++++++- .../repositories/pool/pool-repository-mock.ts | 4 + .../src/repositories/pool/pool-repository.ts | 3 + .../pool/request/create-pool-request.ts | 15 + 31 files changed, 798 insertions(+), 552 deletions(-) delete mode 100644 packages/web/src/components/token/token-swap/TokenSwap.spec.tsx delete mode 100644 packages/web/src/containers/earn-add-liquidity-container/earn-add-liquidity-dummy.ts create mode 100644 packages/web/src/hooks/pool/use-pool.tsx create mode 100644 packages/web/src/hooks/token/use-earn-add-liquidity-confirm-modal.tsx rename packages/web/src/models/swap/{ => info}/swap-confirm-model.ts (100%) create mode 100644 packages/web/src/models/swap/swap-fee-tier-info.ts create mode 100644 packages/web/src/repositories/pool/request/create-pool-request.ts diff --git a/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.stories.tsx b/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.stories.tsx index b4f847d7f..3691f170c 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.stories.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.stories.tsx @@ -4,10 +4,15 @@ import { Meta, StoryObj } from "@storybook/react"; const token = { info: { - path: "1", - name: "Gnoland", - symbol: "GNO.LAND", - logoURI: "", + chainId: "test3", + address: "0x111111111117dC0aa78b770fA6A738034120C302", + path: "gno.land/r/demo/1inch", + name: "1inch", + symbol: "1INCH", + decimals: 6, + logoURI: "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + priceId: "1inch", + createdAt: "1999-01-01T00:00:01Z" }, amount: "12,211", usdPrice: "$12.3", diff --git a/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.tsx b/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.tsx index 9b4b425d9..768bc6091 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm-amount-info/EarnAddConfirmAmountInfo.tsx @@ -1,17 +1,17 @@ import React from "react"; import { EarnAddConfirmAmountInfoWrapper, EarnAddConfirmFeeInfoSection } from "./EarnAddConfirmAmountInfo.styles"; -import { TokenInfo } from "@models/token/token-info"; import TokenAmount from "@components/common/token-amount/TokenAmount"; import IconAdd from "@components/common/icons/IconAdd"; +import { TokenModel } from "@models/token/token-model"; export interface EarnAddConfirmAmountInfoProps { tokenA: { - info: TokenInfo; + info: TokenModel; amount: string; usdPrice: string; }; tokenB: { - info: TokenInfo; + info: TokenModel; amount: string; usdPrice: string; }; diff --git a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx index 38d3317e7..459a62463 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx @@ -9,10 +9,15 @@ export default { const tokenA = { info: { - path: "1", - name: "Gnoland", - symbol: "GNOT", - logoURI: "", + chainId: "test3", + address: "0x111111111117dC0aa78b770fA6A738034120C302", + path: "gno.land/r/demo/1inch", + name: "1inch", + symbol: "1INCH", + decimals: 6, + logoURI: "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + priceId: "1inch", + createdAt: "1999-01-01T00:00:01Z" }, amount: "12,211", usdPrice: "$12.3", @@ -20,10 +25,15 @@ const tokenA = { const tokenB = { info: { - path: "2", - name: "Ether", - symbol: "ETH", - logoURI: "", + chainId: "test3", + address: "0x111111111117dC0aa78b770fA6A738034120C302", + path: "gno.land/r/demo/1inch", + name: "1inch", + symbol: "1INCH", + decimals: 6, + logoURI: "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + priceId: "1inch", + createdAt: "1999-01-01T00:00:01Z" }, amount: "12,211", usdPrice: "$12.3", diff --git a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.styles.ts b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.styles.ts index 1dccc99db..94a30e99b 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.styles.ts +++ b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.styles.ts @@ -4,14 +4,9 @@ import styled from "@emotion/styled"; export const EarnAddConfirmWrapper = styled.div` display: flex; flex-direction: column; - width: 100%; + width: 460px; height: auto; - padding: 24px; gap: 16px; - border-radius: 8px; - border: 1px solid ${({ theme }) => theme.color.border02}; - background-color: ${({ theme }) => theme.color.background06}; - box-shadow: 10px 14px 60px 0px rgba(0, 0, 0, 0.40); .confirm-header { display: flex; diff --git a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx index 2151292db..bad3ed9b9 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx @@ -2,20 +2,20 @@ import React from "react"; import { EarnAddConfirmWrapper } from "./EarnAddConfirm.styles"; import Button, { ButtonHierarchy } from "@components/common/button/Button"; import IconClose from "@components/common/icons/IconCancel"; -import { TokenInfo } from "@models/token/token-info"; import EarnAddConfirmAmountInfo from "../earn-add-confirm-amount-info/EarnAddConfirmAmountInfo"; import EarnAddConfirmPriceRangeInfo from "../earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo"; import EarnAddConfirmFeeInfo from "../earn-add-confirm-fee-info/EarnAddConfirmFeeInfo"; +import { TokenModel } from "@models/token/token-model"; export interface EarnAddConfirmProps { amountInfo: { tokenA: { - info: TokenInfo; + info: TokenModel; amount: string; usdPrice: string; }; tokenB: { - info: TokenInfo; + info: TokenModel; amount: string; usdPrice: string; }; @@ -31,7 +31,7 @@ export interface EarnAddConfirmProps { estimatedAPR: string; }; feeInfo: { - token: TokenInfo; + token: TokenModel; fee: string; }; confirm: () => void; diff --git a/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.stories.tsx b/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.stories.tsx index b6c95f792..94aa4d369 100644 --- a/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.stories.tsx +++ b/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.stories.tsx @@ -3,7 +3,6 @@ import { ComponentStory, ComponentMeta } from "@storybook/react"; import EarnAddLiquidity from "./EarnAddLiquidity"; import { action } from "@storybook/addon-actions"; -import { DUMMY_FEE_TIERS, DUMMY_POOL_TICKS, DUMMY_PRICE_RANGE_MAP } from "@containers/earn-add-liquidity-container/earn-add-liquidity-dummy"; export default { title: "earn-add/EarnAddLiquidity", @@ -14,16 +13,26 @@ const Template: ComponentStory = args => ( ); const tokenA = { - path: "1", - logoURI: "", - name: "Bitcoin", - symbol: "BTC", + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOS", + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/5994.png", + priceId: "gno.land/r/gnos" }; const tokenB = { - path: "2", - logoURI: "", - name: "Ethereum", - symbol: "ETH", + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOS", + logoURI: "https://s2.coinmarketcap.com/static/img/coins/64x64/5994.png", + priceId: "gno.land/r/gnos" }; export const Default = Template.bind({}); @@ -31,12 +40,9 @@ Default.args = { mode: "POOL", tokenA: tokenA, tokenB: tokenB, - feeTiers: DUMMY_FEE_TIERS, - feeRate: "0.01", + feeTiers: [], selectFeeTier: action("selectFeeTier"), - priceRangeMap: DUMMY_PRICE_RANGE_MAP, - priceRange: "Custom", - selectPriceRange: action("selectPriceRange"), - ticks: DUMMY_POOL_TICKS, - currentTick: DUMMY_POOL_TICKS[20], + priceRanges: [], + changePriceRange: action("selectPriceRange"), + ticks: [], }; diff --git a/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx b/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx index 05870b31d..e7b5609aa 100644 --- a/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx +++ b/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx @@ -1,96 +1,90 @@ import Button, { ButtonHierarchy } from "@components/common/button/Button"; import SelectFeeTier from "@components/common/select-fee-tier/SelectFeeTier"; -import SelectPriceRange from "@components/common/select-price-range/SelectPriceRange"; import React, { useCallback, useMemo, useState } from "react"; import { EarnAddLiquidityWrapper } from "./EarnAddLiquidity.styles"; -import { AddLiquidityType, FEE_RATE_OPTION, PriceRangeType } from "@constants/option.constant"; -import { AddLiquidityFeeTier, AddLiquidityPriceRage, PoolTick, PriceRangeSummary } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; +import { AddLiquidityType, SwapFeeTierType, SwapFeeTierInfoMap, AddLiquiditySubmitType } from "@constants/option.constant"; +import { AddLiquidityPriceRage, PoolTick, PriceRangeSummary } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; import LiquidityEnterAmounts from "@components/common/liquidity-enter-amounts/LiquidityEnterAmounts"; -import { TokenInfo } from "@models/token/token-info"; import SelectPair from "@components/common/select-pair/SelectPair"; import { TokenAmountInputModel } from "@hooks/token/use-token-amount-input"; import DoubleLogo from "@components/common/double-logo/DoubleLogo"; import IconSettings from "@components/common/icons/IconSettings"; import Badge, { BADGE_TYPE } from "@components/common/badge/Badge"; -import SelectPriceRangeCustom from "@components/common/select-price-range-custom/SelectPriceRangeCustom"; +import { TokenModel } from "@models/token/token-model"; +import { PoolModel } from "@models/pool/pool-model"; +import SelectPriceRange from "@components/common/select-price-range/SelectPriceRange"; import SelectPriceRangeSummary from "@components/common/select-price-range-summary/SelectPriceRangeSummary"; interface EarnAddLiquidityProps { mode: AddLiquidityType; - tokenA: TokenInfo | undefined; - tokenB: TokenInfo | undefined; - changeToken0: (token: TokenInfo) => void; - changeToken1: (token: TokenInfo) => void; - token0Input: TokenAmountInputModel; - token1Input: TokenAmountInputModel; - feeTiers: AddLiquidityFeeTier[]; - feeRate: FEE_RATE_OPTION | undefined; - selectFeeTier: (feeRate: FEE_RATE_OPTION) => void; - priceRangeMap: { [key in PriceRangeType]: AddLiquidityPriceRage | undefined }; - priceRange: PriceRangeType | undefined; + tokenA: TokenModel | null; + tokenB: TokenModel | null; + changeTokenA: (token: TokenModel) => void; + changeTokenB: (token: TokenModel) => void; + tokenAInput: TokenAmountInputModel; + tokenBInput: TokenAmountInputModel; + feeTiers: SwapFeeTierType[]; + feeTier: SwapFeeTierType | null; + pools: PoolModel[]; + selectFeeTier: (feeRate: SwapFeeTierType) => void; + priceRanges: AddLiquidityPriceRage[]; + priceRange: AddLiquidityPriceRage | null; + changePriceRange: (priceRange: AddLiquidityPriceRage) => void; priceRangeSummary: PriceRangeSummary; - selectPriceRange: (priceRange: PriceRangeType) => void; ticks: PoolTick[]; - currentTick?: PoolTick; + currentTick: PoolTick | null; + submitType: AddLiquiditySubmitType; + submit: () => void; } const EarnAddLiquidity: React.FC = ({ tokenA, tokenB, - changeToken0, - changeToken1, - token0Input, - token1Input, + changeTokenA, + changeTokenB, + tokenAInput, + tokenBInput, feeTiers, - feeRate, + feeTier, + pools, selectFeeTier, - priceRangeMap, + priceRanges, priceRange, priceRangeSummary, - selectPriceRange, - ticks, - currentTick, + changePriceRange, + submitType, + submit, }) => { const [openedSelectPair, setOpenedSelectPair] = useState(true); const [openedFeeTier, setOpenedFeeTier] = useState(true); const [openedPriceRange, setOpenedPriceRange] = useState(true); const existTokenPair = useMemo(() => { - return tokenA !== undefined && tokenB !== undefined; + return tokenA !== null && tokenB !== null; }, [tokenA, tokenB]); - const token0Logo = useMemo(() => { + const tokenALogo = useMemo(() => { return tokenA?.logoURI || ""; }, [tokenA]); - const token1Logo = useMemo(() => { + const tokenBLogo = useMemo(() => { return tokenB?.logoURI || ""; }, [tokenB]); const selectedFeeRate = useMemo(() => { - if (!feeRate) { + if (!feeTier) { return null; } - return `${feeRate}%`; - }, [feeRate]); + return SwapFeeTierInfoMap[feeTier].rateStr; + }, [feeTier]); const selectedPriceRange = useMemo(() => { if (!priceRange) { return null; } - return `${priceRange}`; + return `${priceRange.type}`; }, [priceRange]); - const selectableCustomPriceRange = useMemo(() => { - if (priceRange !== "Custom") { - return false; - } - if (!tokenA || !tokenB) { - return false; - } - return true; - }, [priceRange, tokenA, tokenB]); - const toggleSelectPair = useCallback(() => { setOpenedSelectPair(!openedSelectPair); }, [openedSelectPair]); @@ -103,6 +97,37 @@ const EarnAddLiquidity: React.FC = ({ setOpenedPriceRange(!openedPriceRange); }, [openedPriceRange]); + const activatedSubmit = useMemo(() => { + switch (submitType) { + case "CREATE_POOL": + case "ADD_LIQUIDITY": + case "CONNECT_WALLET": + return true; + default: + return false; + } + }, [submitType]); + + const submitButtonStr = useMemo(() => { + switch (submitType) { + case "CREATE_POOL": + return "Create Pool"; + case "ADD_LIQUIDITY": + return "Add Liquidity"; + case "CONNECT_WALLET": + return "Connect Wallet"; + case "INVALID_PAIR": + return "Invalid Pair"; + case "INSUFFICIENT_BALANCE": + return "Insufficient Balance"; + case "INVALID_RANGE": + return "Invalid Range"; + case "ENTER_AMOUNT": + default: + return "Enter Amount"; + } + }, [submitType]); + return (

Add Liquidity

@@ -112,8 +137,8 @@ const EarnAddLiquidity: React.FC = ({
1. Select Pair
{existTokenPair && ( )} @@ -122,8 +147,8 @@ const EarnAddLiquidity: React.FC = ({ )} @@ -142,7 +167,8 @@ const EarnAddLiquidity: React.FC = ({ {openedFeeTier && ( )} @@ -161,18 +187,9 @@ const EarnAddLiquidity: React.FC = ({ {openedPriceRange && ( - )} - - {selectableCustomPriceRange && ( - )} @@ -187,18 +204,18 @@ const EarnAddLiquidity: React.FC = ({