From 3fc78896ee6ecaa9a519fc0d1b1b1904185d9188 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Sat, 16 Dec 2023 00:08:26 +0900 Subject: [PATCH] faet: [GSW-681] Integrate position info data on Add Position --- .../DoubleTokenLogo.styles.ts | 53 ++++++ .../double-token-logo/DoubleTokenLogo.tsx | 22 +++ .../common/pool-graph/PoolGraph.tsx | 5 +- .../common/token-logo/TokenLogo.tsx | 15 ++ .../IncentivizedPoolCard.tsx | 15 +- .../components/earn/pool-info/PoolInfo.tsx | 12 +- .../one-click-staking/OneClickStaking.tsx | 170 +++++++++--------- .../OneClickStakingContainer.tsx | 32 +++- .../web/src/hooks/common/use-background.tsx | 11 +- .../GnoswapServiceProvider.tsx | 6 + packages/web/src/react-query/token/queries.ts | 15 +- 11 files changed, 250 insertions(+), 106 deletions(-) create mode 100644 packages/web/src/components/common/double-token-logo/DoubleTokenLogo.styles.ts create mode 100644 packages/web/src/components/common/double-token-logo/DoubleTokenLogo.tsx create mode 100644 packages/web/src/components/common/token-logo/TokenLogo.tsx diff --git a/packages/web/src/components/common/double-token-logo/DoubleTokenLogo.styles.ts b/packages/web/src/components/common/double-token-logo/DoubleTokenLogo.styles.ts new file mode 100644 index 000000000..fbb976df1 --- /dev/null +++ b/packages/web/src/components/common/double-token-logo/DoubleTokenLogo.styles.ts @@ -0,0 +1,53 @@ +import { fonts } from "@constants/font.constant"; +import styled from "@emotion/styled"; +import { media } from "@styles/media"; +import mixins from "@styles/mixins"; + +export interface DoubleTokenLogoStyleProps { + size?: string | number; + overlap?: string | number; + fontSize?: number; +} + +export const DoubleTokenLogoWrapper = styled.div` + ${mixins.flexbox("row", "center", "center")}; + img { + width: ${({ size }) => { + if (size) return typeof size === "number" ? `${size}px` : size; + return "36px"; + }}; + height: ${({ size }) => { + if (size) return typeof size === "number" ? `${size}px` : size; + return "36px"; + }}; + border-radius: 50%; + } + .right-logo { + margin-left: ${({ overlap }) => { + if (overlap) + return typeof overlap === "number" ? `-${overlap}px` : `-${overlap}`; + return "-6px"; + }}; + } + .missing-logo { + ${mixins.flexbox("row", "center", "center")}; + width: ${({ size }) => { + if (size) return typeof size === "number" ? `${size}px` : size; + return "36px"; + }}; + height: ${({ size }) => { + if (size) return typeof size === "number" ? `${size}px` : size; + return "36px"; + }}; + border-radius: 50%; + color: ${({ theme }) => theme.color.text02}; + background-color: ${({ theme }) => theme.color.border02}; + ${fonts.p6} + font-size: ${({ fontSize }) => `${fontSize}px`}; + line-height: 1.1em; + ${media.mobile} { + font-size: 8px; + line-height: 10px; + } + } +`; diff --git a/packages/web/src/components/common/double-token-logo/DoubleTokenLogo.tsx b/packages/web/src/components/common/double-token-logo/DoubleTokenLogo.tsx new file mode 100644 index 000000000..4c7d043f9 --- /dev/null +++ b/packages/web/src/components/common/double-token-logo/DoubleTokenLogo.tsx @@ -0,0 +1,22 @@ +import { TokenModel } from "@models/token/token-model"; +import { DoubleTokenLogoWrapper } from "./DoubleTokenLogo.styles"; +import TokenLogo from "../token-logo/TokenLogo"; + +interface DoubleTokenLogoProps { + left: TokenModel; + right: TokenModel; + size?: string | number; + overlap?: string | number; + fontSize?: number; +} + +const DoubleTokenLogo = ({ left, right, size, overlap, fontSize }: DoubleTokenLogoProps) => { + return ( + + + + + ); +}; + +export default DoubleTokenLogo; diff --git a/packages/web/src/components/common/pool-graph/PoolGraph.tsx b/packages/web/src/components/common/pool-graph/PoolGraph.tsx index 5f3fedc95..a0d3a5eb1 100644 --- a/packages/web/src/components/common/pool-graph/PoolGraph.tsx +++ b/packages/web/src/components/common/pool-graph/PoolGraph.tsx @@ -9,6 +9,7 @@ import { tickToPriceStr } from "@utils/swap-utils"; import { makeDisplayTokenAmount } from "@utils/token-utils"; import FloatingTooltip from "../tooltip/FloatingTooltip"; import { FloatingPosition } from "@hooks/common/use-floating-tooltip"; +import TokenLogo from "../token-logo/TokenLogo"; export interface PoolGraphProps { tokenA: TokenModel; @@ -376,7 +377,7 @@ const PoolGraphBinTooptip: React.FC = ({
- logo + {tooltipInfo.tokenA.symbol} @@ -386,7 +387,7 @@ const PoolGraphBinTooptip: React.FC = ({
- logo + {tooltipInfo.tokenB.symbol} diff --git a/packages/web/src/components/common/token-logo/TokenLogo.tsx b/packages/web/src/components/common/token-logo/TokenLogo.tsx new file mode 100644 index 000000000..a0e4472a0 --- /dev/null +++ b/packages/web/src/components/common/token-logo/TokenLogo.tsx @@ -0,0 +1,15 @@ +import { TokenModel } from "@models/token/token-model"; +import React from "react"; + +export interface TokenLogoProps { + className?: string; + token: TokenModel; +} + +const TokenLogo: React.FC = ({ className, token }) => { + return token?.logoURI ? + token logo : +
{token.symbol.slice(0, 3)}
; +}; + +export default TokenLogo; \ No newline at end of file diff --git a/packages/web/src/components/earn/incentivized-pool-card/IncentivizedPoolCard.tsx b/packages/web/src/components/earn/incentivized-pool-card/IncentivizedPoolCard.tsx index 45d680d3f..f54759e46 100644 --- a/packages/web/src/components/earn/incentivized-pool-card/IncentivizedPoolCard.tsx +++ b/packages/web/src/components/earn/incentivized-pool-card/IncentivizedPoolCard.tsx @@ -1,5 +1,4 @@ import Badge, { BADGE_TYPE } from "@components/common/badge/Badge"; -import DoubleLogo from "@components/common/double-logo/DoubleLogo"; import { POOL_CONTENT_TITLE } from "@containers/incentivized-pool-card-list-container/IncentivizedPoolCardListContainer"; import { PoolCardWrapper, @@ -9,6 +8,7 @@ import { PoolCardInfo } from "@models/pool/info/pool-card-info"; import { useMemo } from "react"; import { SwapFeeTierInfoMap } from "@constants/option.constant"; import PoolGraph from "@components/common/pool-graph/PoolGraph"; +import DoubleTokenLogo from "@components/common/double-token-logo/DoubleTokenLogo"; export interface IncentivizedPoolCardProps { pool: PoolCardInfo; @@ -34,9 +34,9 @@ const IncentivizedPoolCard: React.FC = ({
- {pairName}
@@ -45,10 +45,11 @@ const IncentivizedPoolCard: React.FC = ({ type={BADGE_TYPE.DARK_DEFAULT} text={<> Incentivized - } /> diff --git a/packages/web/src/components/earn/pool-info/PoolInfo.tsx b/packages/web/src/components/earn/pool-info/PoolInfo.tsx index c12901f6c..d67f6997e 100644 --- a/packages/web/src/components/earn/pool-info/PoolInfo.tsx +++ b/packages/web/src/components/earn/pool-info/PoolInfo.tsx @@ -8,6 +8,8 @@ import { PoolInfoWrapper, TableColumn } from "./PoolInfo.styles"; import { PoolListInfo } from "@models/pool/info/pool-list-info"; import { SwapFeeTierInfoMap } from "@constants/option.constant"; import PoolGraph from "@components/common/pool-graph/PoolGraph"; +import TokenLogo from "@components/common/token-logo/TokenLogo"; +import DoubleTokenLogo from "@components/common/double-token-logo/DoubleTokenLogo"; interface PoolInfoProps { pool: PoolListInfo; @@ -35,9 +37,9 @@ const PoolInfo: React.FC = ({ pool, routeItem, themeKey }) => { return <>-; } if (rewards.length === 1) { - return icon reward; + return ; } - return ; + return ; }, [rewards]); const resolvedBins = useMemo(() => { @@ -58,9 +60,9 @@ const PoolInfo: React.FC = ({ pool, routeItem, themeKey }) => { onClick={() => routeItem(poolId)} > - {`${tokenA.symbol}/${tokenB.symbol}`} diff --git a/packages/web/src/components/stake/one-click-staking/OneClickStaking.tsx b/packages/web/src/components/stake/one-click-staking/OneClickStaking.tsx index 8a821a213..c189efd9c 100644 --- a/packages/web/src/components/stake/one-click-staking/OneClickStaking.tsx +++ b/packages/web/src/components/stake/one-click-staking/OneClickStaking.tsx @@ -3,106 +3,114 @@ import DoubleLogo from "@components/common/double-logo/DoubleLogo"; import IconStrokeArrowRight from "@components/common/icons/IconStrokeArrowRight"; import { useAtom } from "jotai"; import { SwapState } from "@states/index"; +import DoubleTokenLogo from "@components/common/double-token-logo/DoubleTokenLogo"; +import { PositionModel } from "@models/position/position-model"; +import { useMemo } from "react"; +import { toNumberFormat } from "@utils/number-utils"; interface Props { + stakedPositions: PositionModel[]; + unstakedPositions: PositionModel[]; handleClickGotoStaking: () => void; } -const tempDATA = [ - { - label: "Total APR", - value: 108.85, - }, - { - label: "Fee APR", - value: 108.85, - }, - { - label: "Staking APR", - value: 108.85, - }, -]; +const OneClickStaking: React.FC = ({ + stakedPositions, + unstakedPositions, + handleClickGotoStaking +}) => { + const [swapValue] = useAtom(SwapState.swap); + const { tokenA = null, tokenB = null } = swapValue; -const UNSTAKE_DATA = [ - { - label: "ID #14450", - value: 65541.51, - }, - { - label: "ID #14450", - value: 65541.51, - }, - { - label: "ID #14450", - value: 65541.51, - }, -]; + const isStakedPositions = useMemo(() => { + return stakedPositions.length > 0; + }, [stakedPositions]); + + const isUnstakedPositions = useMemo(() => { + return unstakedPositions.length > 0; + }, [unstakedPositions]); + + if (!tokenA || !tokenB) { + return <>; + } -const OneClickStaking: React.FC = ({ handleClickGotoStaking }) => { - const [swapValue] = useAtom(SwapState.swap); - const { tokenA = null, tokenB = null} = swapValue; - return (
- {tempDATA.map((item, index) => { - return ( -
-
{item.label}
-
{item.value}%
-
- ); - })} +
+
Total APR
+
-
+
+
+
Fee APR
+
-
+
+
+
Staking APR
+
-
+
Rewards
- +
- -
-
-
My Unstaked Positions
-
- Go to Staking -
-
- {UNSTAKE_DATA.map((item, index) => ( -
-
- - {item.label} + {(isStakedPositions || isUnstakedPositions) && } + {isUnstakedPositions && ( +
+
+
My Unstaked Positions
+
+ Go to Staking
-
${item.value.toLocaleString()}
- ))} -
-
-
-
My Staked Positions
-
- {UNSTAKE_DATA.map((item, index) => ( -
-
- - {item.label} + {unstakedPositions.map((item, index) => ( +
+
+ + #{item.id} +
+
${toNumberFormat(item.positionUsdValue)}
-
${item.value.toLocaleString()}
+ ))} +
+ )} + + {isStakedPositions && ( +
+
+
My Staked Positions
+ {!isUnstakedPositions && ( +
+ Go to Staking +
+ )}
- ))} -
+ {stakedPositions.map((item, index) => ( +
+
+ + #{item.id} +
+
${toNumberFormat(item.positionUsdValue)}
+
+ ))} +
+ )} ); }; diff --git a/packages/web/src/containers/one-click-staking-container/OneClickStakingContainer.tsx b/packages/web/src/containers/one-click-staking-container/OneClickStakingContainer.tsx index 843bc2ee1..da1eae3be 100644 --- a/packages/web/src/containers/one-click-staking-container/OneClickStakingContainer.tsx +++ b/packages/web/src/containers/one-click-staking-container/OneClickStakingContainer.tsx @@ -1,14 +1,42 @@ import OneClickStaking from "@components/stake/one-click-staking/OneClickStaking"; -import React, { useCallback } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { useRouter } from "next/router"; +import { useWallet } from "@hooks/wallet/use-wallet"; +import { usePositionData } from "@hooks/common/use-position-data"; +import { PoolPositionModel } from "@models/position/pool-position-model"; const OneClickStakingContainer: React.FC = () => { const router = useRouter(); + const { account } = useWallet(); + const { getPositionsByPoolId } = usePositionData(); + const [positions, setPositions] = useState([]); + + const poolPath = `${router.query?.["pool-path"]}`; + + const stakedPositions = useMemo(() => { + return positions.filter(position => position.staked); + }, [positions]); + + const unstakedPositions = useMemo(() => { + return positions.filter(position => !position.staked); + }, [positions]); const handleClickGotoStaking = useCallback(() => { router.push(`/earn/pool/${router.query?.["pool-path"]}/stake`); }, [router]); - return ; + useEffect(() => { + if (account?.address) { + getPositionsByPoolId(poolPath).then(setPositions); + } + }, [account?.address, getPositionsByPoolId, poolPath]); + + return ( + + ); }; export default OneClickStakingContainer; diff --git a/packages/web/src/hooks/common/use-background.tsx b/packages/web/src/hooks/common/use-background.tsx index 2ae3c27c2..416bb9596 100644 --- a/packages/web/src/hooks/common/use-background.tsx +++ b/packages/web/src/hooks/common/use-background.tsx @@ -1,12 +1,14 @@ -import { useEffect } from "react"; +import { useEffect, useLayoutEffect } from "react"; import { useWallet } from "@hooks/wallet/use-wallet"; import { useAtom } from "jotai"; import { TokenState, WalletState } from "@states/index"; import { useTokenData } from "@hooks/token/use-token-data"; import { useGetTokenPrices, useGetTokensList } from "@query/token"; import { TokenPriceModel } from "@models/token/token-price-model"; +import { useGnoswapContext } from "./use-gnoswap-context"; export const useBackground = () => { + const { accountRepository } = useGnoswapContext(); const { account, initSession, connectAccount, updateWalletEvents } = useWallet(); const [walletClient] = useAtom(WalletState.client); const [, setTokens] = useAtom(TokenState.tokens); @@ -33,11 +35,12 @@ export const useBackground = () => { } }, [tokenPrices]); - useEffect(() => { - if (window.adena) { + useLayoutEffect(() => { + if (window?.adena?.version) { + console.log(window?.adena?.version); initSession(); } - }, [window.adena]); + }, [window?.adena?.version, accountRepository]); useEffect(() => { if (walletClient) { diff --git a/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx b/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx index 208fb7a23..54fea74db 100644 --- a/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx +++ b/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx @@ -21,6 +21,7 @@ import { PositionRepository } from "@repositories/position/position-repository"; import { PositionRepositoryImpl } from "@repositories/position/position-repository-impl"; interface GnoswapContextProps { + initialized: boolean; rpcProvider: GnoProvider | null; accountRepository: AccountRepository; liquidityRepository: LiquidityRepository; @@ -51,6 +52,10 @@ const GnoswapServiceProvider: React.FC = ({ const [rpcProvider, setRPCProvider] = useState(null); + const initialized = useMemo(() => { + return rpcProvider !== null && window !== undefined; + }, [rpcProvider]); + useEffect(() => { if (window) { setLocalStorageClient(WebStorageClient.createLocalStorageClient()); @@ -129,6 +134,7 @@ const GnoswapServiceProvider: React.FC = ({ return ( + options?: UseQueryOptions, ) => { const { tokenRepository } = useGnoswapContext(); @@ -16,7 +21,7 @@ export const useGetTokensList = ( }; export const useGetTokenPrices = ( - options?: UseQueryOptions + options?: UseQueryOptions, ) => { const { tokenRepository } = useGnoswapContext(); return useQuery({ @@ -28,7 +33,7 @@ export const useGetTokenPrices = ( export const useGetTokenDetailByPath = ( path: string, - option?: UseQueryOptions + option?: UseQueryOptions, ) => { const { tokenRepository } = useGnoswapContext(); return useQuery({ @@ -39,7 +44,7 @@ export const useGetTokenDetailByPath = ( }; export const useGetChainList = ( - option?: UseQueryOptions + option?: UseQueryOptions, ) => { const { tokenRepository } = useGnoswapContext(); return useQuery({