Skip to content

Commit

Permalink
spookyswap ui
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitindenis1 committed Aug 27, 2023
1 parent 4d87856 commit 0cf6361
Show file tree
Hide file tree
Showing 13 changed files with 742 additions and 556 deletions.
62 changes: 43 additions & 19 deletions packages/dapp-example/src/SpookySwap.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,77 @@
import { StyledModalContent, StyledSpookySwap, StyledSpookySwapBox, StyledSpookySwapLayout } from "./styles";
import { TWAP, Orders } from "@orbs-network/twap-ui-spookyswap";
import { useConnectWallet, useGetTokensFromViaProtocol, useTheme } from "./hooks";
import { useConnectWallet, useNetwork, useTheme } from "./hooks";
import { useWeb3React } from "@web3-react/core";
import { Configs } from "@orbs-network/twap";
import { Dapp, TokensList, UISelector } from "./Components";
import { Popup } from "./Components";
import { SelectorOption, TokenListItem } from "./types";
import _ from "lodash";
import { erc20sData, zeroAddress } from "@defi.org/web3-candies";
import { erc20sData, zeroAddress, erc20s } from "@defi.org/web3-candies";
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";

const config = Configs.SpookySwap;

const useDappTokens = () => {
return useGetTokensFromViaProtocol(config.chainId);
export const useDappTokens = () => {
const { account } = useWeb3React();
const { isInValidNetwork } = useNetwork(config.chainId);

return useQuery(
["useGetTokens", config.chainId],
async () => {
const response = await fetch(`https://raw.githubusercontent.com/viaprotocol/tokenlists/main/tokenlists/ftm.json`);
const tokenList = await response.json();
const parsed = tokenList.map(({ symbol, address, decimals, logoURI, name, chainId }: any) => ({
decimals,
symbol,
name,
chainId,
address,
tokenInfo: { address, chainId, decimals, symbol, name, logoURI: (logoURI as string)?.replace("/logo_24.png", "/logo_48.png") },
tags: [],
}));
const candiesAddresses = [zeroAddress, ..._.map(erc20s.poly, (t) => t().address)];

const _tokens = _.sortBy(parsed, (t: any) => {
const index = candiesAddresses.indexOf(t.address);
return index >= 0 ? index : Number.MAX_SAFE_INTEGER;
});

return { ..._.mapKeys(_tokens, (t) => t.address) } as any;
},
{ enabled: !!account && !isInValidNetwork }
);
};

interface TokenSelectModalProps {
isOpen: boolean;
selectedToken?: any;
onSelect: (token: any) => void;
onClose: () => void;
selectedCurrency?: any;
onCurrencySelect: (token: any) => void;
onDismiss: () => void;
}

const parseList = (rawList?: any): TokenListItem[] => {
return _.map(rawList, (rawToken) => {
return {
token: {
address: rawToken.address,
decimals: rawToken.decimals,
symbol: rawToken.symbol,
logoUrl: rawToken.logoUrl,
address: rawToken.address ?? rawToken.tokenInfo?.address,
decimals: rawToken.decimals ?? rawToken.tokenInfo?.decimals,
symbol: rawToken.symbol ?? rawToken.tokenInfo?.symbol,
logoUrl: rawToken.tokenInfo?.logoURI,
},
rawToken,
};
});
};

export const TokenSelectModal = ({ isOpen, onSelect, onClose }: TokenSelectModalProps) => {
export const TokenSelectModal = ({ isOpen, onCurrencySelect, onDismiss }: TokenSelectModalProps) => {
const tokensList = useDappTokens().data;
const parsedList = parseList(tokensList);
return (
<Popup isOpen={isOpen} onClose={onClose}>
<Popup isOpen={isOpen} onClose={onDismiss}>
<StyledModalContent>
<TokensList tokens={parsedList} onClick={onSelect} />
<TokensList tokens={parsedList} onClick={onCurrencySelect} />
</StyledModalContent>
</Popup>
);
Expand All @@ -54,19 +82,15 @@ const TWAPComponent = ({ limit }: { limit?: boolean }) => {
const connect = useConnectWallet();
const { data: dappTokens } = useDappTokens();

const getTokenImageUrl = (symbol: string) => dappTokens?.find((t) => t.symbol === symbol)?.logoUrl;

const getProvider = () => library;
const { isDarkTheme } = useTheme();

return (
<TWAP
getProvider={getProvider}
provider={library?.givenProvider}
connect={connect}
account={account}
srcToken={zeroAddress}
dstToken={erc20sData.ftm.USDC.address}
getTokenImageUrl={getTokenImageUrl}
dappTokens={dappTokens}
onSrcTokenSelected={(token: any) => console.log(token)}
onDstTokenSelected={(token: any) => console.log(token)}
Expand Down
2 changes: 1 addition & 1 deletion packages/dapp-example/src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const StyledPangolin = styled(StyledDapp)<{ isDarkMode: number }>(({ isDa
}));

export const StyledSpookySwapLayout = styled(DappLayout)({
maxWidth: 520,
maxWidth: 420,
width: "calc(100% - 30px)",
});

Expand Down
51 changes: 35 additions & 16 deletions packages/lib/src/components/Components.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CSSProperties, FC, ReactElement, ReactNode } from "react";
import { CSSProperties, FC, ReactElement, ReactNode, useCallback } from "react";
import {
Balance,
Button,
Expand Down Expand Up @@ -237,14 +237,17 @@ interface TokenSelectProps extends TWAPTokenSelectProps {
export const TokenSelectModal = ({ Component, isOpen, onClose, parseToken, isSrc = false, onSrcSelect, onDstSelect }: TokenSelectProps) => {
const onTokenSelectedCallback = useOnTokenSelectCallback();

const onSelect = (token: any) => {
const parsedToken = parseToken ? parseToken(token) : token;
onTokenSelectedCallback(isSrc, token, parsedToken, onSrcSelect, onDstSelect);
onClose();
};
const onSelect = useCallback(
(token: any) => {
const parsedToken = parseToken ? parseToken(token) : token;
onTokenSelectedCallback(isSrc, token, parsedToken, onSrcSelect, onDstSelect);
onClose();
},
[onTokenSelectedCallback, onSrcSelect, onDstSelect, isSrc]
);

if (!isOpen || !Component) return null;
return <Component isOpen={true} onClose={onClose} onSelect={onSelect} srcTokenSelected={undefined} dstTokenSelected={undefined} />;
if (!Component) return null;
return <Component isOpen={isOpen} onClose={onClose} onSelect={onSelect} srcTokenSelected={undefined} dstTokenSelected={undefined} />;
};

export function LimitPriceToggle({ variant, style }: { variant?: SwitchVariant; style?: CSSProperties }) {
Expand All @@ -263,7 +266,7 @@ export function LimitPriceToggle({ variant, style }: { variant?: SwitchVariant;
);
}

export function LimitPriceRadioGroup() {
export function LimitPriceRadioGroup({ className }: { className?: string }) {
const loadingState = useLoadingState();
const translations = useTwapContext().translations;
const isLoading = loadingState.srcUsdLoading || loadingState.dstUsdLoading;
Expand All @@ -278,7 +281,7 @@ export function LimitPriceRadioGroup() {

return (
<Tooltip text={isLoading ? `${translations.loading}...` : selectTokensWarning ? translations.selectTokens : ""}>
<FormControl disabled={!!selectTokensWarning || isLoading}>
<FormControl className={`twap-radio ${className}`} disabled={!!selectTokensWarning || isLoading}>
<RadioGroup row name="isLimitOrder" value={String(isLimitOrder)} onChange={handleChange}>
<Radio label="Market Price" value="false" />
<Radio label="Limit Price" value="true" />
Expand Down Expand Up @@ -472,10 +475,14 @@ export const useLimitPriceComponents = ({
placeholder = "0.00",
showDefault,
toggleIcon = <TbArrowsRightLeft style={{ width: 20, height: 20 }} />,
hideSymbol,
reverse,
}: {
placeholder?: string;
showDefault?: boolean;
toggleIcon?: ReactElement;
hideSymbol?: boolean;
reverse?: boolean;
}) => {
const isLimitOrder = useTwapStore((store) => store.isLimitOrder);
const { leftToken, rightToken, onChange, limitPrice, toggleInverted } = useLimitPrice();
Expand All @@ -485,15 +492,27 @@ export const useLimitPriceComponents = ({
if (!_isLimitOrder || !leftToken || !rightToken) return null;

return {
leftToken: <TokenDisplay singleToken symbol={leftToken?.symbol} logo={leftToken?.logoUrl} />,
rightToken: <TokenDisplay symbol={rightToken?.symbol} logo={rightToken?.logoUrl} />,
leftToken: <TokenDisplay reverse={reverse} hideSymbol={hideSymbol} singleToken symbol={leftToken?.symbol} logo={leftToken?.logoUrl} />,
rightToken: <TokenDisplay reverse={reverse} hideSymbol={hideSymbol} symbol={rightToken?.symbol} logo={rightToken?.logoUrl} />,
input: <NumericInput placeholder={placeholder} onChange={onChange} value={limitPrice} />,
toggle: <IconButton onClick={toggleInverted} icon={toggleIcon} />,
};
};

export function LimitPriceInput({ placeholder = "0.00", className = "", showDefault }: { placeholder?: string; className?: string; showDefault?: boolean }) {
const components = useLimitPriceComponents({ placeholder, showDefault });
export function LimitPriceInput({
placeholder = "0.00",
className = "",
showDefault,
hideSymbol,
reverse,
}: {
placeholder?: string;
className?: string;
showDefault?: boolean;
hideSymbol?: boolean;
reverse?: boolean;
}) {
const components = useLimitPriceComponents({ placeholder, showDefault, hideSymbol, reverse });

if (!components) return null;
return (
Expand Down Expand Up @@ -1001,7 +1020,7 @@ export const TradeSizeValue = ({ symbol }: { symbol?: boolean }) => {
);
};

export const TradeSize = ({ hideLabel }: { hideLabel?: boolean }) => {
export const TradeSize = ({ hideLabel, hideSymbol }: { hideLabel?: boolean; hideSymbol?: boolean }) => {
const srcToken = useTwapStore((store) => store.srcToken);
const dsToken = useTwapStore((store) => store.dstToken);

Expand All @@ -1017,7 +1036,7 @@ export const TradeSize = ({ hideLabel }: { hideLabel?: boolean }) => {
{!hideLabel && <ChunksAmountLabel />}
<StyledRowFlex gap={7} className="content">
<TokenLogo isSrc={true} />
<TradeSizeValue symbol={true} />
<TradeSizeValue symbol={!hideSymbol} />
</StyledRowFlex>
</StyledTradeSize>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/lib/src/components/Labels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ export const CurrentMarketPriceLabel = () => {
return <Label>{translations.currentMarketPrice}</Label>;
};

export const LimitPriceLabel = () => {
export const LimitPriceLabel = ({ custom }: { custom?: string }) => {
const translations = useTwapContext().translations;
const isLimitOrder = useTwapStore((store) => store.isLimitOrder);

return (
<Styles.StyledRowFlex justifyContent="flex-start" style={{ width: "auto", position: "relative" }} gap={3}>
<Label tooltipText={isLimitOrder ? translations.limitPriceTooltip : translations.marketPriceTooltip}>{translations.limitPrice}</Label>{" "}
<Label tooltipText={isLimitOrder ? translations.limitPriceTooltip : translations.marketPriceTooltip}>{custom || translations.limitPrice}</Label>{" "}
</Styles.StyledRowFlex>
);
};
Expand Down
7 changes: 6 additions & 1 deletion packages/lib/src/components/base/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { SlInfo } from "react-icons/sl";
import Icon from "./Icon";
import { StyledColumnFlex, StyledRowFlex, StyledText } from "../../styles";
import { Typography } from "@mui/material";
import { useTwapContext } from "../../context";
import { IconType } from "react-icons";

interface Props {
children: string | number | ReactNode;
Expand All @@ -16,6 +18,9 @@ interface Props {
}

function Label({ children, tooltipText, className = "", fontSize, placement, subtitle }: Props) {
const { uiPreferences } = useTwapContext();

const InfoIcon = uiPreferences.infoIcon || SlInfo;
if (subtitle) {
return (
<StyledColumnFlex className={`twap-label ${className}`}>
Expand All @@ -30,7 +35,7 @@ function Label({ children, tooltipText, className = "", fontSize, placement, sub
{tooltipText && (
<Tooltip placement={placement} text={tooltipText}>
<StyledTooltipContent className={`twap-label-tooltip-content ${className}`}>
<Icon icon={<SlInfo className="twap-tooltip-icon" style={{ width: 14, height: 14 }} />} />
<Icon icon={<InfoIcon className="twap-tooltip-icon" style={{ width: 14, height: 14 }} />} />
</StyledTooltipContent>
</Tooltip>
)}
Expand Down
10 changes: 6 additions & 4 deletions packages/lib/src/components/base/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Backdrop from "@mui/material/Backdrop";

export interface Props {
open: boolean;
onClose: () => void;
onClose?: () => void;
children: ReactNode;
title?: string;
className?: string;
Expand All @@ -32,9 +32,11 @@ function Modal({ onClose, open, children, title, className = "", disableBackdrop
>
<Fade in={open}>
<StyledModalContent className="twap-modal-content" id="twap-modal-content">
<StyledClose className="twap-ui-close" onClick={onClose}>
<IoMdClose />
</StyledClose>
{onClose && (
<StyledClose className="twap-ui-close" onClick={onClose}>
<IoMdClose />
</StyledClose>
)}
{title && (
<>
<StyledTitle>{title}</StyledTitle>
Expand Down
7 changes: 4 additions & 3 deletions packages/lib/src/components/base/TokenDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ interface Props {
className?: string;
reverse?: boolean;
singleToken?: boolean;
hideSymbol?: boolean;
}

function TokenDisplay({ symbol, logo, className = "", reverse, singleToken }: Props) {
function TokenDisplay({ symbol, logo, className = "", reverse, singleToken, hideSymbol }: Props) {
return (
<StyledContainer className={`twap-token-display ${className}`}>
{reverse ? (
<>
{singleToken && <StyledText>1</StyledText>}
<TokenName name={symbol} />
{!hideSymbol && <TokenName name={symbol} />}
<TokenLogo logo={logo} />
</>
) : (
<>
<TokenLogo logo={logo} />
{singleToken && <StyledText>1</StyledText>}
<TokenName name={symbol} />
{!hideSymbol && <TokenName name={symbol} />}
</>
)}
</StyledContainer>
Expand Down
22 changes: 13 additions & 9 deletions packages/lib/src/components/base/TokenPriceCompare.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TokenData } from "@orbs-network/twap";
import { TbArrowsRightLeft } from "react-icons/tb";
import { Loader, Tooltip } from ".";
import { useFormatNumber } from "../../hooks";
import { StyledText } from "../../styles";
import { StyledRowFlex, StyledText } from "../../styles";
import Icon from "./Icon";
import IconButton from "./IconButton";
import TokenLogo from "./TokenLogo";
Expand Down Expand Up @@ -39,18 +39,22 @@ function TokenPriceCompare({ leftToken, rightToken, price, className, toggleInve
}
return (
<StyledContainer className={`twap-price-compare ${className}`}>
<TokenLogo logo={leftToken?.logoUrl} />
<StyledText>1</StyledText>
<TokenName name={leftToken?.symbol} />
<StyledRowFlex style={{ width: "auto", gap: 5 }}>
<TokenLogo logo={leftToken?.logoUrl} />
<StyledText className="value">1</StyledText>
<TokenName name={leftToken?.symbol} />
</StyledRowFlex>
<IconButton onClick={toggleInverted}>
<Icon icon={<TbArrowsRightLeft />} />
</IconButton>

<TokenLogo logo={rightToken?.logoUrl} />
<Tooltip text={`${formattedValueTooltip} ${rightToken.symbol}`}>
{`${formattedValue} `}
{rightToken?.symbol}
</Tooltip>
<StyledRowFlex style={{ width: "auto", gap: 5 }}>
<TokenLogo logo={rightToken?.logoUrl} />
<Tooltip text={`${formattedValueTooltip} ${rightToken.symbol}`}>
<span className="value"> {`${formattedValue} `}</span>
<span className="symbol"> {rightToken?.symbol}</span>
</Tooltip>
</StyledRowFlex>
</StyledContainer>
);
}
Expand Down
Loading

0 comments on commit 0cf6361

Please sign in to comment.