diff --git a/features/prices/components/Price/Price.tsx b/features/prices/components/Price/Price.tsx
index ead9b7f..400ed8d 100644
--- a/features/prices/components/Price/Price.tsx
+++ b/features/prices/components/Price/Price.tsx
@@ -1,9 +1,11 @@
-import { usePrices, type PriceCoingecko } from '@/features/prices'
+import { useLocale, usePrices, type PriceCoingecko } from '@/features/prices'
import { PriceChange } from './PriceChange'
import styles from './Price.module.css'
+import { formatFiat } from '@/lib'
export function Price({ price }: { price: PriceCoingecko }) {
const { isValidating, isLoading } = usePrices()
+ const locale = useLocale()
const feedbackClasses = isLoading
? 'isLoading'
@@ -13,7 +15,9 @@ export function Price({ price }: { price: PriceCoingecko }) {
return (
- ${price.usd}
+
+ {formatFiat(price.usd, 'USD', locale)}
+
{price?.usd_24h_change ? (
) : null}
diff --git a/features/prices/components/Price/PriceChange.tsx b/features/prices/components/Price/PriceChange.tsx
index 65a4313..e7e2ee5 100644
--- a/features/prices/components/Price/PriceChange.tsx
+++ b/features/prices/components/Price/PriceChange.tsx
@@ -2,19 +2,12 @@
import { TriangleUpIcon, TriangleDownIcon } from '@radix-ui/react-icons'
import styles from './PriceChange.module.css'
-import { useEffect, useState } from 'react'
+import { useLocale } from '@/features/prices/hooks/use-locale'
export function PriceChange({ priceChange }: { priceChange: number }) {
- const [locale, setLocale] = useState('en-US')
+ const locale = useLocale()
const styleClasses = priceChange > 0 ? styles.positive : styles.negative
- useEffect(() => {
- const userLocale = navigator?.languages?.length
- ? navigator.languages[0]
- : navigator.language
- setLocale(userLocale)
- }, [])
-
return (
{
+ const userLocale = navigator?.languages?.length
+ ? navigator.languages[0]
+ : navigator.language
+ setLocale(userLocale)
+ }, [])
+
+ return locale
+}
diff --git a/features/prices/hooks/use-prices.tsx b/features/prices/hooks/use-prices.tsx
index a9b1823..4d333ae 100644
--- a/features/prices/hooks/use-prices.tsx
+++ b/features/prices/hooks/use-prices.tsx
@@ -1,7 +1,7 @@
'use client'
import { tokens } from '@/constants'
-import { fetcher, getTokenAddressBySymbol } from '@/lib/utils'
+import { fetcher, getTokenAddressBySymbol } from '@/lib'
import useSWR from 'swr'
const tokenAddresses = tokens.map((token) => token.address).toString()
diff --git a/features/strategies/components/Buy.tsx b/features/strategies/components/Buy.tsx
index 243c600..bf8553e 100644
--- a/features/strategies/components/Buy.tsx
+++ b/features/strategies/components/Buy.tsx
@@ -4,8 +4,8 @@ import { useState } from 'react'
import { useDebounce } from 'use-debounce'
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
import { usePrices } from '@/features/prices'
-import { getTokenBySymbol } from '@/lib/utils'
-import { FormAmount, Result } from '@/features/strategies/components'
+import { getTokenBySymbol } from '@/lib'
+import { FormAmount, Result } from '@/features/strategies'
import stylesShared from '@/features/strategies/styles/shared.module.css'
export function Buy() {
diff --git a/features/strategies/components/FormAmount.tsx b/features/strategies/components/FormAmount.tsx
index 14dc583..61d8c87 100644
--- a/features/strategies/components/FormAmount.tsx
+++ b/features/strategies/components/FormAmount.tsx
@@ -20,6 +20,8 @@ export function FormAmount({
if (value === '') {
setAmount(0)
+ } else if (isNaN(Number(value))) {
+ return
} else {
setAmount(Number(value))
}
@@ -30,6 +32,10 @@ export function FormAmount({
setToken(e.target.value as TokenSymbol)
}
+ function handleFocus(e: React.FocusEvent) {
+ e.target.select()
+ }
+
const options = isFiat
? [{ value: 'USD', label: 'USD' }]
: [
@@ -46,6 +52,7 @@ export function FormAmount({
pattern="[0-9]*"
value={amount}
onChange={handleAmountChange}
+ onFocus={handleFocus}
style={{ width: amount.toString().length + 'ch' }}
/>
diff --git a/features/strategies/components/Result/Result.tsx b/features/strategies/components/Result/Result.tsx
index 1e75173..35fa392 100644
--- a/features/strategies/components/Result/Result.tsx
+++ b/features/strategies/components/Result/Result.tsx
@@ -1,8 +1,9 @@
import styles from './Result.module.css'
-import { formatNumber } from '@/lib/utils'
+import { formatCrypto, formatFiat } from '@/lib'
import { ArrowRightIcon } from '@radix-ui/react-icons'
import { TokenLogo } from '@/components'
import { Token } from '@/types'
+import { useLocale } from '@/features/prices'
type Props = {
token: Token | undefined
@@ -23,11 +24,12 @@ export function Result({
isValidating,
isLoading
}: Props) {
+ const locale = useLocale()
const feedbackClasses = isLoading
? 'isLoading'
: isValidating
- ? 'isValidating'
- : ''
+ ? 'isValidating'
+ : ''
return (
@@ -35,15 +37,18 @@ export function Result({
-
- {formatNumber(amount || 0, token?.symbol || '')}
+
+ {formatCrypto(amount || 0, token?.symbol || '', locale)}
{amountOriginalFiat ? (
- {formatNumber(amountOriginalFiat || 0, 'USD')}
+ {formatFiat(amountOriginalFiat || 0, 'USD', locale)}
) : null}
@@ -53,13 +58,13 @@ export function Result({
-
- {formatNumber(amountAsi || 0, 'ASI')}
+
+ {formatCrypto(amountAsi || 0, 'ASI', locale)}
- {formatNumber(amountFiat || 0, 'USD')}
+ {formatFiat(amountFiat || 0, 'USD', locale)}
diff --git a/features/strategies/components/Swap/Results.tsx b/features/strategies/components/Swap/Results.tsx
index 8202f58..5e61639 100644
--- a/features/strategies/components/Swap/Results.tsx
+++ b/features/strategies/components/Swap/Results.tsx
@@ -1,5 +1,5 @@
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
-import { getTokenBySymbol } from '@/lib/utils'
+import { getTokenBySymbol } from '@/lib'
import { type TokenSymbol } from '@/types'
import { usePrices, type Prices } from '@/features/prices'
import { type Market, useQuote } from '@/features/strategies'
diff --git a/features/strategies/hooks/use-quote.ts b/features/strategies/hooks/use-quote.ts
index 91c7700..b45bfc7 100644
--- a/features/strategies/hooks/use-quote.ts
+++ b/features/strategies/hooks/use-quote.ts
@@ -1,7 +1,7 @@
'use client'
import { TokenSymbol } from '@/types'
-import { getTokenAddressBySymbol, fetcher } from '@/lib/utils'
+import { getTokenAddressBySymbol, fetcher } from '@/lib'
import useSWR from 'swr'
const options = {
diff --git a/lib/fetch.ts b/lib/fetch.ts
new file mode 100644
index 0000000..21f956c
--- /dev/null
+++ b/lib/fetch.ts
@@ -0,0 +1,5 @@
+export async function fetcher(url: string) {
+ const res = await fetch(url)
+ if (!res.ok) throw new Error('Failed to fetch')
+ return await res.json()
+}
diff --git a/lib/index.ts b/lib/index.ts
new file mode 100644
index 0000000..56b0f5d
--- /dev/null
+++ b/lib/index.ts
@@ -0,0 +1,3 @@
+export * from './numbers'
+export * from './fetch'
+export * from './tokens'
diff --git a/lib/numbers.ts b/lib/numbers.ts
new file mode 100644
index 0000000..92bbe6d
--- /dev/null
+++ b/lib/numbers.ts
@@ -0,0 +1,22 @@
+import { formatCurrency } from '@coingecko/cryptoformat'
+
+export function formatCrypto(price: number, currency: string, locale: string) {
+ return formatCurrency(price, currency, locale, false, {
+ decimalPlaces: 3,
+ significantFigures: 1
+ })
+}
+
+export function formatFiat(price: number, currency: string, locale: string) {
+ let formattedPrice = formatCurrency(price, currency, locale, false, {
+ decimalPlaces: 2,
+ significantFigures: 8
+ })
+
+ // Add a trailing zero if only one digit after the decimal
+ if (formattedPrice.includes('.') && formattedPrice.split('.')[1].length < 2) {
+ formattedPrice += '0'
+ }
+
+ return formattedPrice
+}
diff --git a/lib/utils.ts b/lib/tokens.ts
similarity index 50%
rename from lib/utils.ts
rename to lib/tokens.ts
index 416d50a..655282c 100644
--- a/lib/utils.ts
+++ b/lib/tokens.ts
@@ -1,19 +1,5 @@
import { tokens } from '@/constants'
import type { TokenAddress, Token } from '@/types'
-import { formatCurrency } from '@coingecko/cryptoformat'
-
-export function formatNumber(price: number, currency: string) {
- return formatCurrency(price, currency, 'en', false, {
- decimalPlaces: 3,
- significantFigures: 5
- })
-}
-
-export async function fetcher(url: string) {
- const res = await fetch(url)
- if (!res.ok) throw new Error('Failed to fetch')
- return await res.json()
-}
export function getTokenBySymbol(symbol: string): Token | undefined {
const token = tokens.find((t) => t.symbol === symbol)