From 1496238b4a6d9cdc8fccdbf42bcfe41084e7c93c Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 1 Apr 2024 12:03:06 +0100 Subject: [PATCH 1/4] copy --- content.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/content.md b/content.md index beef303..23bcf84 100644 --- a/content.md +++ b/content.md @@ -1,4 +1,6 @@ -The **→ lines** show what you would get with the displayed token amount at the moment of the ASI swap, along with the converted value based on the current market price of FET. The fiat values are fetched from [Coingecko](https://coingecko.com), and the token swap estimations directly from [Uniswap](https://uniswap.org) v3 swap routes. +The **→ lines** show what you would get with the displayed token amount at the moment of the ASI swap, along with the converted value based on the current market price of FET. + +The fiat values are fetched from [Coingecko](https://coingecko.com), and the token swap estimations directly from [Uniswap](https://uniswap.org) v3 swap routes. All displayed values should be seen as estimates. Except for the [fixed ASI exchange rate](https://blog.oceanprotocol.com/ocean-protocol-is-joining-the-superintelligence-alliance-767c82693f24#3c8e), all other values are constantly changing based on market conditions. There is no guarantee the displayed values reflect the value of your investment once the actual ASI swap mechanism is released. Use at your own risk. From c75354a54d9c015b2dd44f8d77e629e4df8c2a62 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 1 Apr 2024 13:42:08 +0100 Subject: [PATCH 2/4] refactor to allow switching markets --- app/page.tsx | 6 +- components/CalculationBaseOutput/index.tsx | 1 - components/FormAmount/FormAmount.tsx | 26 ------ components/FormAmount/Inputs/InputToken.tsx | 47 ---------- components/ResultRow/index.tsx | 1 - .../Select.module.css} | 8 +- components/Select/Select.tsx | 22 +++++ components/Select/index.tsx | 1 + components/Strategies/Swap/Results.tsx | 66 -------------- components/Strategies/index.tsx | 2 - .../MarketData/MarketData.module.css | 6 +- .../components/MarketData/MarketData.tsx | 8 +- .../prices/components/MarketData/index.tsx | 1 + {hooks => features/prices/hooks}/index.ts | 1 - .../prices/hooks}/use-prices.tsx | 7 ++ features/prices/index.tsx | 2 + .../strategies/components}/Buy.tsx | 9 +- .../FormAmount/FormAmount.module.css | 0 .../components/FormAmount/FormAmount.tsx | 46 ++++++++++ .../FormAmount/Inputs/InputAmount.module.css | 0 .../FormAmount/Inputs/InputAmount.tsx | 4 +- .../components}/FormAmount/index.tsx | 0 .../FormMarket/FormMarket.module.css | 8 ++ .../components/FormMarket/FormMarket.tsx | 27 ++++++ .../components/FormMarket/index.tsx | 1 + .../components/Result/Result.module.css | 0 .../strategies/components/Result/Result.tsx | 4 +- .../strategies/components/Result/index.tsx | 1 + .../strategies/components/Swap/Results.tsx | 81 +++++++++++++++++ .../strategies/components}/Swap/Swap.tsx | 15 +++- features/strategies/components/index.tsx | 3 + features/strategies/hooks/index.tsx | 1 + features/strategies/hooks/use-quote.ts | 89 +++++++++++++++++++ features/strategies/index.tsx | 4 + .../strategies/styles/shared.module.css | 1 + features/strategies/types.ts | 1 + hooks/use-quote.ts | 67 -------------- 37 files changed, 328 insertions(+), 239 deletions(-) delete mode 100644 components/CalculationBaseOutput/index.tsx delete mode 100644 components/FormAmount/FormAmount.tsx delete mode 100644 components/FormAmount/Inputs/InputToken.tsx delete mode 100644 components/ResultRow/index.tsx rename components/{FormAmount/Inputs/InputToken.module.css => Select/Select.module.css} (100%) create mode 100644 components/Select/Select.tsx create mode 100644 components/Select/index.tsx delete mode 100644 components/Strategies/Swap/Results.tsx delete mode 100644 components/Strategies/index.tsx rename components/CalculationBaseOutput/CalculationBase.module.css => features/prices/components/MarketData/MarketData.module.css (89%) rename components/CalculationBaseOutput/CalculationBase.tsx => features/prices/components/MarketData/MarketData.tsx (88%) create mode 100644 features/prices/components/MarketData/index.tsx rename {hooks => features/prices/hooks}/index.ts (50%) rename {hooks => features/prices/hooks}/use-prices.tsx (92%) create mode 100644 features/prices/index.tsx rename {components/Strategies => features/strategies/components}/Buy.tsx (91%) rename {components => features/strategies/components}/FormAmount/FormAmount.module.css (100%) create mode 100644 features/strategies/components/FormAmount/FormAmount.tsx rename {components => features/strategies/components}/FormAmount/Inputs/InputAmount.module.css (100%) rename {components => features/strategies/components}/FormAmount/Inputs/InputAmount.tsx (88%) rename {components => features/strategies/components}/FormAmount/index.tsx (100%) create mode 100644 features/strategies/components/FormMarket/FormMarket.module.css create mode 100644 features/strategies/components/FormMarket/FormMarket.tsx create mode 100644 features/strategies/components/FormMarket/index.tsx rename components/ResultRow/ResultRow.module.css => features/strategies/components/Result/Result.module.css (100%) rename components/ResultRow/ResultRow.tsx => features/strategies/components/Result/Result.tsx (93%) create mode 100644 features/strategies/components/Result/index.tsx create mode 100644 features/strategies/components/Swap/Results.tsx rename {components/Strategies => features/strategies/components}/Swap/Swap.tsx (59%) create mode 100644 features/strategies/components/index.tsx create mode 100644 features/strategies/hooks/index.tsx create mode 100644 features/strategies/hooks/use-quote.ts create mode 100644 features/strategies/index.tsx rename components/Strategies/styles.module.css => features/strategies/styles/shared.module.css (92%) create mode 100644 features/strategies/types.ts delete mode 100644 hooks/use-quote.ts diff --git a/app/page.tsx b/app/page.tsx index 1f40f8c..bad550e 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,9 +1,9 @@ import styles from './page.module.css' -import { Swap, Buy } from '@/components/Strategies' +import { Swap, Buy } from '@/features/strategies' import { Content } from '@/components/Content' -import { CalculationBase } from '@/components/CalculationBaseOutput' import { Header } from '@/components/Header' import { Footer } from '@/components/Footer' +import { MarketData } from '@/features/prices' export default function Home() { return ( @@ -16,7 +16,7 @@ export default function Home() { - + diff --git a/components/CalculationBaseOutput/index.tsx b/components/CalculationBaseOutput/index.tsx deleted file mode 100644 index cc180f9..0000000 --- a/components/CalculationBaseOutput/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './CalculationBase' diff --git a/components/FormAmount/FormAmount.tsx b/components/FormAmount/FormAmount.tsx deleted file mode 100644 index 137c28e..0000000 --- a/components/FormAmount/FormAmount.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { InputAmount } from '@/components/FormAmount/Inputs/InputAmount' -import { InputToken } from './Inputs/InputToken' -import styles from './FormAmount.module.css' -import { Dispatch, SetStateAction } from 'react' -import { TokenSymbol } from '@/types' - -export function FormAmount({ - amount, - setAmount, - token, - setToken, - isFiat -}: { - amount: number - setAmount: Dispatch> - token: TokenSymbol | string - setToken?: Dispatch> - isFiat?: boolean -}) { - return ( -
- - - - ) -} diff --git a/components/FormAmount/Inputs/InputToken.tsx b/components/FormAmount/Inputs/InputToken.tsx deleted file mode 100644 index a2e195b..0000000 --- a/components/FormAmount/Inputs/InputToken.tsx +++ /dev/null @@ -1,47 +0,0 @@ -'use client' - -import { Dispatch, SetStateAction } from 'react' -import styles from './InputToken.module.css' -import { CaretDownIcon } from '@radix-ui/react-icons' -import { TokenSymbol } from '@/types' -import { useSWRConfig } from 'swr' - -export function InputToken({ - token, - setToken, - isFiat -}: { - token: TokenSymbol | string - isFiat?: boolean - setToken?: Dispatch> -}) { - const { mutate } = useSWRConfig() - - return ( - - - {setToken ? : null} - - ) -} diff --git a/components/ResultRow/index.tsx b/components/ResultRow/index.tsx deleted file mode 100644 index 4a4b4ec..0000000 --- a/components/ResultRow/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './ResultRow' diff --git a/components/FormAmount/Inputs/InputToken.module.css b/components/Select/Select.module.css similarity index 100% rename from components/FormAmount/Inputs/InputToken.module.css rename to components/Select/Select.module.css index 0a6fd7d..579e51d 100644 --- a/components/FormAmount/Inputs/InputToken.module.css +++ b/components/Select/Select.module.css @@ -1,3 +1,7 @@ +.selectWrapper { + position: relative; +} + .select { display: inline-block; all: unset; @@ -23,10 +27,6 @@ } } -.selectWrapper { - position: relative; -} - .icon { position: absolute; right: 0.1rem; diff --git a/components/Select/Select.tsx b/components/Select/Select.tsx new file mode 100644 index 0000000..e8d533b --- /dev/null +++ b/components/Select/Select.tsx @@ -0,0 +1,22 @@ +import { SelectHTMLAttributes } from 'react' +import styles from './Select.module.css' +import { CaretDownIcon } from '@radix-ui/react-icons' + +type Props = SelectHTMLAttributes & { + options: { value: string; label: string }[] +} + +export function Select({ options, ...rest }: Props) { + return ( + + + {options.length > 1 ? : null} + + ) +} diff --git a/components/Select/index.tsx b/components/Select/index.tsx new file mode 100644 index 0000000..3e383f0 --- /dev/null +++ b/components/Select/index.tsx @@ -0,0 +1 @@ +export * from './Select' diff --git a/components/Strategies/Swap/Results.tsx b/components/Strategies/Swap/Results.tsx deleted file mode 100644 index e66b63f..0000000 --- a/components/Strategies/Swap/Results.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { Result } from '@/components/ResultRow' -import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' -import { usePrices } from '@/hooks' -import { getTokenBySymbol } from '@/lib/utils' -import { TokenSymbol } from '@/types' -import { useQuote } from '@/hooks' - -export function SwapResults({ - tokenSymbol, - amount -}: { - tokenSymbol: TokenSymbol - amount: number -}) { - const { - prices, - isValidating: isValidatingPrices, - isLoading: isLoadingPrices - } = usePrices() - - const { - amountToOcean, - amountToAgix, - amountToFet, - isValidatingToAgix, - isLoadingToAgix, - isValidatingToFet, - isLoadingToFet, - isValidatingToOcean, - isLoadingToOcean - } = useQuote(tokenSymbol, amount) - - return ( - <> - - - - - - - ) -} diff --git a/components/Strategies/index.tsx b/components/Strategies/index.tsx deleted file mode 100644 index 0f0b6ce..0000000 --- a/components/Strategies/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -export * from './Buy' -export * from './Swap/Swap' diff --git a/components/CalculationBaseOutput/CalculationBase.module.css b/features/prices/components/MarketData/MarketData.module.css similarity index 89% rename from components/CalculationBaseOutput/CalculationBase.module.css rename to features/prices/components/MarketData/MarketData.module.css index f41f363..4ed8231 100644 --- a/components/CalculationBaseOutput/CalculationBase.module.css +++ b/features/prices/components/MarketData/MarketData.module.css @@ -1,4 +1,4 @@ -.calculationBase { +.marketData { display: grid; grid-template-columns: repeat(auto-fill, minmax(235px, 1fr)); justify-content: center; @@ -9,14 +9,14 @@ margin-top: 1.5rem; } -.calculationBase li { +.marketData li { border-bottom: 1px solid rgba(var(--foreground-rgb), 0.2); border-right: 1px solid rgba(var(--foreground-rgb), 0.2); padding: 1rem; font-size: 0.9rem; } -.calculationBase p { +.marketData p { display: flex; align-items: center; } diff --git a/components/CalculationBaseOutput/CalculationBase.tsx b/features/prices/components/MarketData/MarketData.tsx similarity index 88% rename from components/CalculationBaseOutput/CalculationBase.tsx rename to features/prices/components/MarketData/MarketData.tsx index f2c4e7a..d2364a6 100644 --- a/components/CalculationBaseOutput/CalculationBase.tsx +++ b/features/prices/components/MarketData/MarketData.tsx @@ -1,11 +1,11 @@ 'use client' import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' -import styles from './CalculationBase.module.css' -import { usePrices } from '@/hooks' +import styles from './MarketData.module.css' +import { usePrices } from '@/features/prices/hooks' import { Label } from '@/components/Label' -export function CalculationBase() { +export function MarketData() { const { prices, isValidating, isLoading } = usePrices() const feedbackClasses = isLoading @@ -15,7 +15,7 @@ export function CalculationBase() { : '' return ( -
    +
    • 1 ASI

      diff --git a/features/prices/components/MarketData/index.tsx b/features/prices/components/MarketData/index.tsx new file mode 100644 index 0000000..9ea4537 --- /dev/null +++ b/features/prices/components/MarketData/index.tsx @@ -0,0 +1 @@ +export * from './MarketData' diff --git a/hooks/index.ts b/features/prices/hooks/index.ts similarity index 50% rename from hooks/index.ts rename to features/prices/hooks/index.ts index 5ec829b..95409a3 100644 --- a/hooks/index.ts +++ b/features/prices/hooks/index.ts @@ -1,2 +1 @@ export * from './use-prices' -export * from './use-quote' diff --git a/hooks/use-prices.tsx b/features/prices/hooks/use-prices.tsx similarity index 92% rename from hooks/use-prices.tsx rename to features/prices/hooks/use-prices.tsx index 0fbaad1..9a3e743 100644 --- a/hooks/use-prices.tsx +++ b/features/prices/hooks/use-prices.tsx @@ -4,6 +4,13 @@ import useSWR from 'swr' const tokenAddresses = tokens.map((token) => token.address).toString() +export type Prices = { + ocean: number + fet: number + agix: number + asi: number +} + export function usePrices(): { prices: { ocean: number; fet: number; agix: number; asi: number } isValidating: boolean diff --git a/features/prices/index.tsx b/features/prices/index.tsx new file mode 100644 index 0000000..0203c73 --- /dev/null +++ b/features/prices/index.tsx @@ -0,0 +1,2 @@ +export * from './components/MarketData' +export * from './hooks' diff --git a/components/Strategies/Buy.tsx b/features/strategies/components/Buy.tsx similarity index 91% rename from components/Strategies/Buy.tsx rename to features/strategies/components/Buy.tsx index ddce207..4e65691 100644 --- a/components/Strategies/Buy.tsx +++ b/features/strategies/components/Buy.tsx @@ -1,13 +1,12 @@ 'use client' -import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' -import { Result } from '@/components/ResultRow' import { useState } from 'react' import { useDebounce } from 'use-debounce' -import stylesShared from './styles.module.css' -import { usePrices } from '@/hooks' -import { FormAmount } from '@/components/FormAmount' +import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' +import { usePrices } from '@/features/prices' import { getTokenBySymbol } from '@/lib/utils' +import { FormAmount, Result } from '@/features/strategies/components' +import stylesShared from '@/features/strategies/styles/shared.module.css' export function Buy() { const { prices, isValidating, isLoading } = usePrices() diff --git a/components/FormAmount/FormAmount.module.css b/features/strategies/components/FormAmount/FormAmount.module.css similarity index 100% rename from components/FormAmount/FormAmount.module.css rename to features/strategies/components/FormAmount/FormAmount.module.css diff --git a/features/strategies/components/FormAmount/FormAmount.tsx b/features/strategies/components/FormAmount/FormAmount.tsx new file mode 100644 index 0000000..02ae5d0 --- /dev/null +++ b/features/strategies/components/FormAmount/FormAmount.tsx @@ -0,0 +1,46 @@ +import { InputAmount } from './Inputs/InputAmount' +import styles from './FormAmount.module.css' +import { Dispatch, SetStateAction } from 'react' +import { TokenSymbol } from '@/types' +import { Select } from '@/components/Select' + +export function FormAmount({ + amount, + setAmount, + token, + setToken, + isFiat +}: { + amount: number + setAmount: Dispatch> + token: TokenSymbol | string + setToken?: Dispatch> + isFiat?: boolean +}) { + function handleTokenChange(e: React.ChangeEvent) { + if (!setToken) return + setToken(e.target.value as TokenSymbol) + } + + const options = isFiat + ? [{ value: 'USD', label: 'USD' }] + : [ + { value: 'OCEAN', label: 'OCEAN' }, + { value: 'FET', label: 'FET' }, + { value: 'AGIX', label: 'AGIX' } + ] + + return ( +

      + + + setMarket(e.target.value as Market)} + style={{ paddingRight: '1.25rem' }} + /> + + ) +} diff --git a/features/strategies/components/FormMarket/index.tsx b/features/strategies/components/FormMarket/index.tsx new file mode 100644 index 0000000..02153f2 --- /dev/null +++ b/features/strategies/components/FormMarket/index.tsx @@ -0,0 +1 @@ +export * from './FormMarket' diff --git a/components/ResultRow/ResultRow.module.css b/features/strategies/components/Result/Result.module.css similarity index 100% rename from components/ResultRow/ResultRow.module.css rename to features/strategies/components/Result/Result.module.css diff --git a/components/ResultRow/ResultRow.tsx b/features/strategies/components/Result/Result.tsx similarity index 93% rename from components/ResultRow/ResultRow.tsx rename to features/strategies/components/Result/Result.tsx index f893363..f378288 100644 --- a/components/ResultRow/ResultRow.tsx +++ b/features/strategies/components/Result/Result.tsx @@ -1,7 +1,7 @@ -import styles from './ResultRow.module.css' +import styles from './Result.module.css' import { formatNumber } from '@/lib/utils' import { ArrowRightIcon } from '@radix-ui/react-icons' -import { TokenLogo } from '../TokenLogo/TokenLogo' +import { TokenLogo } from '../../../../components/TokenLogo/TokenLogo' import { Token } from '@/types' type Props = { diff --git a/features/strategies/components/Result/index.tsx b/features/strategies/components/Result/index.tsx new file mode 100644 index 0000000..0405368 --- /dev/null +++ b/features/strategies/components/Result/index.tsx @@ -0,0 +1 @@ +export * from './Result' diff --git a/features/strategies/components/Swap/Results.tsx b/features/strategies/components/Swap/Results.tsx new file mode 100644 index 0000000..19f6767 --- /dev/null +++ b/features/strategies/components/Swap/Results.tsx @@ -0,0 +1,81 @@ +import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' +import { usePrices, type Prices } from '@/features/prices' +import { getTokenBySymbol } from '@/lib/utils' +import { TokenSymbol } from '@/types' +import { useQuote, type Market } from '@/features/strategies' +import { Result } from '../Result' + +export function SwapResults({ + tokenSymbol, + amount, + market +}: { + tokenSymbol: TokenSymbol + amount: number + market: Market +}) { + const isUniswap = market === 'uniswap-v3' + + const { + prices, + isValidating: isValidatingPrices, + isLoading: isLoadingPrices + } = usePrices() + + const { + amountToOcean: amountToOceanUniswap, + amountToAgix: amountToAgixUniswap, + amountToFet: amountToFetUniswap, + isValidatingToAgix, + isLoadingToAgix, + isValidatingToFet, + isLoadingToFet, + isValidatingToOcean, + isLoadingToOcean + } = useQuote(tokenSymbol, amount, isUniswap) + + const amountInUsd = amount * prices[tokenSymbol.toLowerCase() as keyof Prices] + const amountToOcean = amountInUsd / prices.ocean + const amountToAgix = amountInUsd / prices.agix + const amountToFet = amountInUsd / prices.fet + + return ( + <> + + + + + + + ) +} diff --git a/components/Strategies/Swap/Swap.tsx b/features/strategies/components/Swap/Swap.tsx similarity index 59% rename from components/Strategies/Swap/Swap.tsx rename to features/strategies/components/Swap/Swap.tsx index 47a5e15..0121a98 100644 --- a/components/Strategies/Swap/Swap.tsx +++ b/features/strategies/components/Swap/Swap.tsx @@ -1,16 +1,18 @@ 'use client' -import stylesShared from '../styles.module.css' import { useState } from 'react' import { useDebounce } from 'use-debounce' -import { FormAmount } from '@/components/FormAmount' import { SwapResults } from './Results' import { TokenSymbol } from '@/types' +import { FormAmount, FormMarket } from '@/features/strategies/components' +import stylesShared from '@/features/strategies/styles/shared.module.css' +import { type Market } from '@/features/strategies' export function Swap() { const [amount, setAmount] = useState(100) const [debouncedAmount] = useDebounce(amount, 500) const [tokenSymbol, setTokenSymbol] = useState('OCEAN') + const [market, setMarket] = useState('all') return (
      @@ -22,10 +24,15 @@ export function Swap() { setAmount={setAmount} setToken={setTokenSymbol} />{' '} - on Uniswap right now gets you: + on right now gets + you: - +
      ) } diff --git a/features/strategies/components/index.tsx b/features/strategies/components/index.tsx new file mode 100644 index 0000000..f59a09f --- /dev/null +++ b/features/strategies/components/index.tsx @@ -0,0 +1,3 @@ +export * from './FormAmount' +export * from './FormMarket' +export * from './Result' diff --git a/features/strategies/hooks/index.tsx b/features/strategies/hooks/index.tsx new file mode 100644 index 0000000..1905d1d --- /dev/null +++ b/features/strategies/hooks/index.tsx @@ -0,0 +1 @@ +export * from './use-quote' diff --git a/features/strategies/hooks/use-quote.ts b/features/strategies/hooks/use-quote.ts new file mode 100644 index 0000000..61a7d4e --- /dev/null +++ b/features/strategies/hooks/use-quote.ts @@ -0,0 +1,89 @@ +import { TokenSymbol } from '@/types' +import { getTokenAddressBySymbol, fetcher } from '@/lib/utils' +import useSWR from 'swr' + +const options = { + keepPreviousData: true // so loading UI can kick in properly +} + +export function useQuote( + tokenSymbol: TokenSymbol, + amount: number, + shouldFetch: boolean +) { + // -> AGIX + const { + data: dataSwapToAgix, + isValidating: isValidatingToAgix, + isLoading: isLoadingToAgix + } = useSWR( + shouldFetch + ? `/api/quote/?tokenIn=${getTokenAddressBySymbol( + tokenSymbol + )}&tokenOut=${getTokenAddressBySymbol('AGIX')}&amountIn=${amount}` + : null, + fetcher, + options + ) + + // -> FET + const { + data: dataSwapToFet, + isValidating: isValidatingToFet, + isLoading: isLoadingToFet + } = useSWR( + shouldFetch + ? `/api/quote/?tokenIn=${getTokenAddressBySymbol( + tokenSymbol + )}&tokenOut=${getTokenAddressBySymbol('FET')}&amountIn=${amount}` + : null, + fetcher, + options + ) + + // -> OCEAN + const { + data: dataSwapToOcean, + isValidating: isValidatingToOcean, + isLoading: isLoadingToOcean + } = useSWR( + shouldFetch + ? `/api/quote/?tokenIn=${getTokenAddressBySymbol( + tokenSymbol + )}&tokenOut=${getTokenAddressBySymbol('OCEAN')}&amountIn=${amount}` + : null, + fetcher, + options + ) + + const amountToOcean = + dataSwapToOcean?.amountOut / Number(`1e${dataSwapToOcean?.decimals}`) + const amountToAgix = + dataSwapToAgix?.amountOut / Number(`1e${dataSwapToAgix?.decimals}`) + const amountToFet = + dataSwapToFet?.amountOut / Number(`1e${dataSwapToFet?.decimals}`) + + return shouldFetch + ? { + amountToOcean, + amountToAgix, + amountToFet, + isValidatingToAgix, + isLoadingToAgix, + isValidatingToFet, + isLoadingToFet, + isValidatingToOcean, + isLoadingToOcean + } + : { + amountToOcean: undefined, + amountToAgix: undefined, + amountToFet: undefined, + isValidatingToAgix: false, + isLoadingToAgix: false, + isValidatingToFet: false, + isLoadingToFet: false, + isValidatingToOcean: false, + isLoadingToOcean: false + } +} diff --git a/features/strategies/index.tsx b/features/strategies/index.tsx new file mode 100644 index 0000000..43b8607 --- /dev/null +++ b/features/strategies/index.tsx @@ -0,0 +1,4 @@ +export * from './components/Buy' +export * from './components/Swap/Swap' +export * from './hooks' +export * from './types' diff --git a/components/Strategies/styles.module.css b/features/strategies/styles/shared.module.css similarity index 92% rename from components/Strategies/styles.module.css rename to features/strategies/styles/shared.module.css index a79bd4d..5701657 100644 --- a/components/Strategies/styles.module.css +++ b/features/strategies/styles/shared.module.css @@ -9,4 +9,5 @@ font-size: 1.2rem; color: rgb(var(--foreground-rgb-highlight)); min-height: 58px; + line-height: 1.5; } diff --git a/features/strategies/types.ts b/features/strategies/types.ts new file mode 100644 index 0000000..8b18ffa --- /dev/null +++ b/features/strategies/types.ts @@ -0,0 +1 @@ +export type Market = 'all' | 'uniswap-v3' diff --git a/hooks/use-quote.ts b/hooks/use-quote.ts deleted file mode 100644 index 51304b8..0000000 --- a/hooks/use-quote.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { TokenSymbol } from '@/types' -import { getTokenAddressBySymbol, fetcher } from '@/lib/utils' -import useSWR from 'swr' - -const options = { - keepPreviousData: true // so loading UI can kick in properly -} - -export function useQuote(tokenSymbol: TokenSymbol, amount: number) { - // -> AGIX - const { - data: dataSwapToAgix, - isValidating: isValidatingToAgix, - isLoading: isLoadingToAgix - } = useSWR( - `/api/quote/?tokenIn=${getTokenAddressBySymbol( - tokenSymbol - )}&tokenOut=${getTokenAddressBySymbol('AGIX')}&amountIn=${amount}`, - fetcher, - options - ) - - // -> FET - const { - data: dataSwapToFet, - isValidating: isValidatingToFet, - isLoading: isLoadingToFet - } = useSWR( - `/api/quote/?tokenIn=${getTokenAddressBySymbol( - tokenSymbol - )}&tokenOut=${getTokenAddressBySymbol('FET')}&amountIn=${amount}`, - fetcher, - options - ) - - // -> OCEAN - const { - data: dataSwapToOcean, - isValidating: isValidatingToOcean, - isLoading: isLoadingToOcean - } = useSWR( - `/api/quote/?tokenIn=${getTokenAddressBySymbol( - tokenSymbol - )}&tokenOut=${getTokenAddressBySymbol('OCEAN')}&amountIn=${amount}`, - fetcher, - options - ) - - const amountToOcean = - dataSwapToOcean?.amountOut / Number(`1e${dataSwapToOcean?.decimals}`) - const amountToAgix = - dataSwapToAgix?.amountOut / Number(`1e${dataSwapToAgix?.decimals}`) - const amountToFet = - dataSwapToFet?.amountOut / Number(`1e${dataSwapToFet?.decimals}`) - - return { - amountToOcean, - amountToAgix, - amountToFet, - isValidatingToAgix, - isLoadingToAgix, - isValidatingToFet, - isLoadingToFet, - isValidatingToOcean, - isLoadingToOcean - } -} From f2991d22dfefeb7edb560722276e537e4e9dada1 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 1 Apr 2024 14:23:01 +0100 Subject: [PATCH 3/4] more refactor for feature structure --- app/layout.tsx | 6 ++-- app/page.tsx | 4 +-- components/Header/Header.tsx | 6 ++-- .../Input/Input.module.css | 0 components/Input/Input.tsx | 8 +++++ components/Input/index.tsx | 1 + components/index.tsx | 7 ++++ constants.ts | 4 +++ .../components/MarketData/MarketData.tsx | 4 +-- features/prices/hooks/{index.ts => index.tsx} | 0 features/prices/hooks/use-prices.tsx | 2 ++ .../components/FormAmount/FormAmount.tsx | 24 +++++++++++-- .../FormAmount/Inputs/InputAmount.tsx | 34 ------------------- .../components/FormMarket/FormMarket.tsx | 2 +- .../strategies/components/Result/Result.tsx | 2 +- .../strategies/components/Swap/Results.tsx | 6 ++-- features/strategies/components/Swap/index.tsx | 1 + features/strategies/hooks/use-quote.ts | 2 ++ features/strategies/index.tsx | 2 +- 19 files changed, 60 insertions(+), 55 deletions(-) rename features/strategies/components/FormAmount/Inputs/InputAmount.module.css => components/Input/Input.module.css (100%) create mode 100644 components/Input/Input.tsx create mode 100644 components/Input/index.tsx create mode 100644 components/index.tsx rename features/prices/hooks/{index.ts => index.tsx} (100%) delete mode 100644 features/strategies/components/FormAmount/Inputs/InputAmount.tsx create mode 100644 features/strategies/components/Swap/index.tsx diff --git a/app/layout.tsx b/app/layout.tsx index 0ccf9e5..364e640 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -3,16 +3,14 @@ import { Hanken_Grotesk } from 'next/font/google' import '@/styles/globals.css' import '@/styles/loading-ui.css' import Script from 'next/script' +import { title, description } from '@/constants' const hankenGrotesk = Hanken_Grotesk({ subsets: ['latin'], variable: '--font-hanken-grotesk' }) -export const metadata: Metadata = { - title: 'ASI Calculator', - description: 'See how much ASI you get for your OCEAN, AGIX, or FET.' -} +export const metadata: Metadata = { title, description } export default function RootLayout({ children diff --git a/app/page.tsx b/app/page.tsx index bad550e..79f0236 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,9 +1,7 @@ import styles from './page.module.css' import { Swap, Buy } from '@/features/strategies' -import { Content } from '@/components/Content' -import { Header } from '@/components/Header' -import { Footer } from '@/components/Footer' import { MarketData } from '@/features/prices' +import { Content, Footer, Header } from '@/components' export default function Home() { return ( diff --git a/components/Header/Header.tsx b/components/Header/Header.tsx index 7e150b7..78c7e33 100644 --- a/components/Header/Header.tsx +++ b/components/Header/Header.tsx @@ -1,11 +1,11 @@ -import { metadata } from '@/app/layout' +import { title, description } from '@/constants' import styles from './Header.module.css' export function Header() { return (
      -

      {`${metadata.title}`}

      -

      {`${metadata.description}`}

      +

      {`${title}`}

      +

      {`${description}`}

      ) } diff --git a/features/strategies/components/FormAmount/Inputs/InputAmount.module.css b/components/Input/Input.module.css similarity index 100% rename from features/strategies/components/FormAmount/Inputs/InputAmount.module.css rename to components/Input/Input.module.css diff --git a/components/Input/Input.tsx b/components/Input/Input.tsx new file mode 100644 index 0000000..90969ad --- /dev/null +++ b/components/Input/Input.tsx @@ -0,0 +1,8 @@ +import { InputHTMLAttributes } from 'react' +import styles from './Input.module.css' + +type Props = InputHTMLAttributes + +export function Input(props: Props) { + return +} diff --git a/components/Input/index.tsx b/components/Input/index.tsx new file mode 100644 index 0000000..54e51f6 --- /dev/null +++ b/components/Input/index.tsx @@ -0,0 +1 @@ +export * from './Input' diff --git a/components/index.tsx b/components/index.tsx new file mode 100644 index 0000000..caafba3 --- /dev/null +++ b/components/index.tsx @@ -0,0 +1,7 @@ +export * from './Content' +export * from './Footer' +export * from './Header' +export * from './Input' +export * from './Label' +export * from './Select' +export * from './TokenLogo' diff --git a/constants.ts b/constants.ts index 9705db9..a384df9 100644 --- a/constants.ts +++ b/constants.ts @@ -1,5 +1,9 @@ import { Token } from '@/types' +export const title = 'ASI Calculator' +export const description = + 'See how much ASI you get for your OCEAN, AGIX, or FET.' + export const ratioOceanToAsi = 0.433226 export const ratioAgixToAsi = 0.43335 export const ratioFetToAsi = 1 diff --git a/features/prices/components/MarketData/MarketData.tsx b/features/prices/components/MarketData/MarketData.tsx index d2364a6..c388866 100644 --- a/features/prices/components/MarketData/MarketData.tsx +++ b/features/prices/components/MarketData/MarketData.tsx @@ -2,8 +2,8 @@ import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' import styles from './MarketData.module.css' -import { usePrices } from '@/features/prices/hooks' -import { Label } from '@/components/Label' +import { usePrices } from '@/features/prices' +import { Label } from '@/components' export function MarketData() { const { prices, isValidating, isLoading } = usePrices() diff --git a/features/prices/hooks/index.ts b/features/prices/hooks/index.tsx similarity index 100% rename from features/prices/hooks/index.ts rename to features/prices/hooks/index.tsx diff --git a/features/prices/hooks/use-prices.tsx b/features/prices/hooks/use-prices.tsx index 9a3e743..7bea155 100644 --- a/features/prices/hooks/use-prices.tsx +++ b/features/prices/hooks/use-prices.tsx @@ -1,3 +1,5 @@ +'use client' + import { tokens } from '@/constants' import { fetcher, getTokenAddressBySymbol } from '@/lib/utils' import useSWR from 'swr' diff --git a/features/strategies/components/FormAmount/FormAmount.tsx b/features/strategies/components/FormAmount/FormAmount.tsx index 02ae5d0..a8b8e09 100644 --- a/features/strategies/components/FormAmount/FormAmount.tsx +++ b/features/strategies/components/FormAmount/FormAmount.tsx @@ -1,8 +1,7 @@ -import { InputAmount } from './Inputs/InputAmount' import styles from './FormAmount.module.css' import { Dispatch, SetStateAction } from 'react' import { TokenSymbol } from '@/types' -import { Select } from '@/components/Select' +import { Select, Input } from '@/components' export function FormAmount({ amount, @@ -17,6 +16,16 @@ export function FormAmount({ setToken?: Dispatch> isFiat?: boolean }) { + function handleAmountChange(e: React.ChangeEvent) { + const { value } = e.target + + if (value === '') { + setAmount(0) + } else { + setAmount(Number(value)) + } + } + function handleTokenChange(e: React.ChangeEvent) { if (!setToken) return setToken(e.target.value as TokenSymbol) @@ -32,7 +41,16 @@ export function FormAmount({ return (
      - + - ) -} diff --git a/features/strategies/components/FormMarket/FormMarket.tsx b/features/strategies/components/FormMarket/FormMarket.tsx index feaa14b..875d98f 100644 --- a/features/strategies/components/FormMarket/FormMarket.tsx +++ b/features/strategies/components/FormMarket/FormMarket.tsx @@ -1,6 +1,6 @@ import styles from './FormMarket.module.css' import { Dispatch, SetStateAction } from 'react' -import { Select } from '@/components/Select' +import { Select } from '@/components' import { type Market } from '@/features/strategies' export function FormMarket({ diff --git a/features/strategies/components/Result/Result.tsx b/features/strategies/components/Result/Result.tsx index f378288..1e75173 100644 --- a/features/strategies/components/Result/Result.tsx +++ b/features/strategies/components/Result/Result.tsx @@ -1,7 +1,7 @@ import styles from './Result.module.css' import { formatNumber } from '@/lib/utils' import { ArrowRightIcon } from '@radix-ui/react-icons' -import { TokenLogo } from '../../../../components/TokenLogo/TokenLogo' +import { TokenLogo } from '@/components' import { Token } from '@/types' type Props = { diff --git a/features/strategies/components/Swap/Results.tsx b/features/strategies/components/Swap/Results.tsx index 19f6767..9c0c2f3 100644 --- a/features/strategies/components/Swap/Results.tsx +++ b/features/strategies/components/Swap/Results.tsx @@ -1,8 +1,8 @@ import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' -import { usePrices, type Prices } from '@/features/prices' import { getTokenBySymbol } from '@/lib/utils' -import { TokenSymbol } from '@/types' -import { useQuote, type Market } from '@/features/strategies' +import { type TokenSymbol } from '@/types' +import { usePrices } from '@/features/prices' +import { type Market, useQuote } from '@/features/strategies' import { Result } from '../Result' export function SwapResults({ diff --git a/features/strategies/components/Swap/index.tsx b/features/strategies/components/Swap/index.tsx new file mode 100644 index 0000000..0fba608 --- /dev/null +++ b/features/strategies/components/Swap/index.tsx @@ -0,0 +1 @@ +export * from './Swap' diff --git a/features/strategies/hooks/use-quote.ts b/features/strategies/hooks/use-quote.ts index 61a7d4e..91c7700 100644 --- a/features/strategies/hooks/use-quote.ts +++ b/features/strategies/hooks/use-quote.ts @@ -1,3 +1,5 @@ +'use client' + import { TokenSymbol } from '@/types' import { getTokenAddressBySymbol, fetcher } from '@/lib/utils' import useSWR from 'swr' diff --git a/features/strategies/index.tsx b/features/strategies/index.tsx index 43b8607..22d2f5f 100644 --- a/features/strategies/index.tsx +++ b/features/strategies/index.tsx @@ -1,4 +1,4 @@ export * from './components/Buy' -export * from './components/Swap/Swap' +export * from './components/Swap' export * from './hooks' export * from './types' From 68ce3d01024e84194d85b4d396f9bdf9b547e6d7 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 1 Apr 2024 14:25:11 +0100 Subject: [PATCH 4/4] type fix --- features/strategies/components/Swap/Results.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/strategies/components/Swap/Results.tsx b/features/strategies/components/Swap/Results.tsx index 9c0c2f3..d8a7fb1 100644 --- a/features/strategies/components/Swap/Results.tsx +++ b/features/strategies/components/Swap/Results.tsx @@ -1,7 +1,7 @@ import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' import { getTokenBySymbol } from '@/lib/utils' import { type TokenSymbol } from '@/types' -import { usePrices } from '@/features/prices' +import { usePrices, type Prices } from '@/features/prices' import { type Market, useQuote } from '@/features/strategies' import { Result } from '../Result'