diff --git a/bun.lockb b/bun.lockb index f79f216..05f5b1c 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/app/UserWallet.tsx b/components/app/UserWallet.tsx index 2ab3f97..536c3b3 100644 --- a/components/app/UserWallet.tsx +++ b/components/app/UserWallet.tsx @@ -1,7 +1,7 @@ // UserWallet.tsx import React from "react"; import { RxCaretDown } from "react-icons/rx"; -import PlaceholderFromHexAddress from "@/components/app/molecules/PlaceholderFromHexAddress"; +import PlaceholderImageFromSeed from "@/components/app/molecules/PlaceholderImageFromSeed"; import { SecretString } from "@/types"; interface UserWalletProps { @@ -27,7 +27,7 @@ const UserWallet: React.FC = ({ {isConnected ? ( <>
- +
diff --git a/components/app/atoms/Swap/MaxButton.tsx b/components/app/atoms/Swap/MaxButton.tsx new file mode 100644 index 0000000..aeb4ec5 --- /dev/null +++ b/components/app/atoms/Swap/MaxButton.tsx @@ -0,0 +1,11 @@ +const MaxButton = ({ onClick }: { onClick: () => void }) => { + return ( + + ); +}; +export default MaxButton; diff --git a/components/app/atoms/Swap/TokenInput/InputBalanceAffordance.tsx b/components/app/atoms/Swap/TokenInput/InputBalanceAffordance.tsx new file mode 100644 index 0000000..3c047ff --- /dev/null +++ b/components/app/atoms/Swap/TokenInput/InputBalanceAffordance.tsx @@ -0,0 +1,11 @@ +export default function InputBalanceAffordance({ + balance, +}: { + balance: number; +}) { + return ( +
+ {balance.toFixed(2)} +
+ ); +} diff --git a/components/app/atoms/Swap/TokenInputBaseInput.tsx b/components/app/atoms/Swap/TokenInputBaseInput.tsx new file mode 100644 index 0000000..e6f3160 --- /dev/null +++ b/components/app/atoms/Swap/TokenInputBaseInput.tsx @@ -0,0 +1,16 @@ +export default function TokenInputBaseInput({ + amount, + handleChange, +}: { + amount: string; + handleChange: (event: React.ChangeEvent) => void; +}) { + return ( + + ); +} diff --git a/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionCloseButton.tsx b/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionCloseButton.tsx new file mode 100644 index 0000000..22c171d --- /dev/null +++ b/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionCloseButton.tsx @@ -0,0 +1,6 @@ +{ + /*
+

Select a token

+ +
*/ +} diff --git a/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionSearchBar.tsx b/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionSearchBar.tsx new file mode 100644 index 0000000..51d9962 --- /dev/null +++ b/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionSearchBar.tsx @@ -0,0 +1,24 @@ +import { FaSearch } from "react-icons/fa"; + +export default function TokenSelectionSearchBar({ + searchTerm, + setSearchTerm, +}: { + searchTerm: string; + setSearchTerm: React.Dispatch>; +}) { + return ( +
+
+ + setSearchTerm(e.target.value)} + /> +
+
+ ); +} diff --git a/components/app/molecules/PlaceholderFromHexAddress.tsx b/components/app/molecules/PlaceholderFromHexAddress.tsx deleted file mode 100644 index ca243fe..0000000 --- a/components/app/molecules/PlaceholderFromHexAddress.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// PlaceholderFromHexAddress.tsx -import React from "react"; -import ImageWithPlaceholder from "@/components/app/ImageWithPlaceholder"; -import addressTo3Colors from "@/utils/ImageWithPlaceholder/addressTo3Colors"; -import stringToHex from "@/utils/ImageWithPlaceholder/stringToHex"; -import { SecretString } from "@/types"; - -interface PlaceholderFromHexAddressProps { - userAddress: SecretString; - size?: number; // Changed to a single number for consistency -} - -const PlaceholderFromHexAddress: React.FC = ({ - userAddress, - size = 48, // Default size as a single number, assuming a square for simplicity -}) => { - const hexAddress = stringToHex(userAddress); - const colorsString = addressTo3Colors(hexAddress); - const placeholderUrl = `https://api.dicebear.com/6.x/shapes/svg?seed=${hexAddress}&height=${size}&width=${size}&${colorsString}`; - - return ( - - ); -}; - -export default PlaceholderFromHexAddress; diff --git a/components/app/molecules/PlaceholderImageFromSeed.tsx b/components/app/molecules/PlaceholderImageFromSeed.tsx new file mode 100644 index 0000000..e594180 --- /dev/null +++ b/components/app/molecules/PlaceholderImageFromSeed.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import ImageWithPlaceholder from "@/components/app/ImageWithPlaceholder"; +import { SecretString } from "@/types"; +import generateHexColorsFromSeed from "@/utils/ImageWithPlaceholder/generateHexColorsFromSeed"; + +interface PlaceholderImageFromSeedProps { + seed: SecretString; + size?: number; +} + +const PlaceholderImageFromSeed: React.FC = ({ + seed, + size = 48, +}) => { + const [color1, color2, color3] = generateHexColorsFromSeed(seed, 3); + const colorQueryString = `shape1Color=${color1}&shape2Color=${color2}&shape3Color=${color3}`; + const placeholderUrl = `https://api.dicebear.com/6.x/shapes/svg?seed=${seed}&height=${size}&width=${size}&${colorQueryString}`; + + return ( + + ); +}; + +export default PlaceholderImageFromSeed; diff --git a/components/app/molecules/TokenInput.tsx b/components/app/molecules/TokenInput.tsx deleted file mode 100644 index c77780f..0000000 --- a/components/app/molecules/TokenInput.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { useState } from "react"; -import { TokenInputs, useStore } from "@/store/swapStore"; // Adjust the import path as necessary -import PlaceholderFromHexAddress from "./PlaceholderFromHexAddress"; -import { RxCaretDown } from "react-icons/rx"; -import { Token } from "@/types"; - -interface TokenInputProps { - inputIdentifier: keyof TokenInputs; // This prop specifies which token input state to interact with (e.g., "swap.pay") - maxable?: boolean; - balance: number; // Assuming balance is still passed as a prop -} - -const tokens = [ - { symbol: "sSCRT", address: "secret1k0jntykt7e4g3y88ltc60czgjuqdy4c9e8fzek" }, - { symbol: "SEFI", address: "secret15l9cqgz5uezgydrglaak5ahfac69kmx2qpd6xt" }, - { symbol: "sAAVE", address: "secret1yxwnyk8htvvq25x2z87yj0r5tqpev452fk6h5h" }, -] as Token[]; - -const TokenInput: React.FC = ({ - inputIdentifier, - maxable = false, - balance, -}) => { - const [isModalOpen, setIsModalOpen] = useState(false); - const { tokenInputs, setTokenInputProperty } = useStore(); - - // Extracting the specific token input state based on the inputIdentifier - const { token, amount } = tokenInputs[inputIdentifier]; - - const handleTokenSelect = (selectedToken: Token) => { - setTokenInputProperty(inputIdentifier, "token", selectedToken); - setIsModalOpen(false); - }; - - const handleChange = (event: React.ChangeEvent) => { - const value = event.target.value; - const numValue = parseFloat(value); - - if (!isNaN(numValue) && numValue >= 0 && numValue <= balance) { - setTokenInputProperty(inputIdentifier, "amount", value); - } else if (value === "") { - setTokenInputProperty(inputIdentifier, "amount", ""); - } - }; - - const handleMax = () => { - setTokenInputProperty(inputIdentifier, "amount", balance.toString()); - }; - - return ( -
-
- -
- {balance.toFixed(2)} -
- {maxable && ( - - )} -
setIsModalOpen(true)} - > - - {token.symbol} - -
-
- {isModalOpen && ( -
-
-
    - {tokens.map((token, index) => ( -
  • handleTokenSelect(token)} - > - {token.symbol} -
  • - ))} -
-
-
- )} -
- ); -}; - -export default TokenInput; diff --git a/components/app/molecules/TokenSelectionItem.tsx b/components/app/molecules/TokenSelectionItem.tsx new file mode 100644 index 0000000..17b8cbc --- /dev/null +++ b/components/app/molecules/TokenSelectionItem.tsx @@ -0,0 +1,32 @@ +import { Token } from "@/types"; +import PlaceholderImageFromSeed from "@/components/app/molecules/PlaceholderImageFromSeed"; +import * as Dialog from "@radix-ui/react-dialog"; + +interface TokenSelectionItemProps { + token: Token; + network: string; // Assuming you can provide network information + balance: string; // Assuming you have balance information as a string + handleTokenSelect: (token: Token) => void; +} + +const TokenSelectionItem: React.FC = ({ + token, + network, + balance, + handleTokenSelect, +}) => { + return ( + handleTokenSelect(token)} asChild> +
+ +
+ {token.symbol} + {network} +
+ {balance} +
+
+ ); +}; + +export default TokenSelectionItem; diff --git a/components/app/organisms/SwapForm/SwapForm.tsx b/components/app/organisms/SwapForm/SwapForm.tsx index 9b24800..2792217 100644 --- a/components/app/organisms/SwapForm/SwapForm.tsx +++ b/components/app/organisms/SwapForm/SwapForm.tsx @@ -1,6 +1,6 @@ import React from "react"; import InputLabel from "@/components/app/atoms/InputLabel"; -import TokenInput from "@/components/app/molecules/TokenInput"; +import TokenInput from "@/components/app/organisms/SwapForm/TokenInput"; import SwapButton from "@/components/app/atoms/SwapButton"; import { useStore } from "@/store/swapStore"; // Ensure this path matches the location of your store import DynamicField from "@/components/app/molecules/DynamicField"; diff --git a/components/app/organisms/SwapForm/TokenInput.tsx b/components/app/organisms/SwapForm/TokenInput.tsx new file mode 100644 index 0000000..31baae7 --- /dev/null +++ b/components/app/organisms/SwapForm/TokenInput.tsx @@ -0,0 +1,66 @@ +import React from "react"; +import { useStore } from "@/store/swapStore"; +import PlaceholderImageFromSeed from "../../molecules/PlaceholderImageFromSeed"; +import { RxCaretDown } from "react-icons/rx"; +import { TokenInputs } from "@/types"; +import TokenSelectionModal from "./TokenSelectionModalRadix"; +import MaxButton from "../../atoms/Swap/MaxButton"; +import TokenInputBaseInput from "../../atoms/Swap/TokenInputBaseInput"; +import InputBalanceAffordance from "../../atoms/Swap/TokenInput/InputBalanceAffordance"; +import * as Dialog from "@radix-ui/react-dialog"; + +interface TokenInputProps { + inputIdentifier: keyof TokenInputs; + maxable?: boolean; + balance: number; +} + +const TokenInput: React.FC = ({ + inputIdentifier, + maxable = false, + balance, +}) => { + const { tokenInputs, setTokenInputProperty } = useStore(); + const { token, amount } = tokenInputs[inputIdentifier]; + const [isModalOpen, setIsModalOpen] = React.useState(false); + const handleChange = (event: React.ChangeEvent) => { + const value = event.target.value; + const numValue = parseFloat(value); + + if (!isNaN(numValue) && numValue >= 0 && numValue <= balance) { + setTokenInputProperty(inputIdentifier, "amount", value); + } else if (value === "") { + setTokenInputProperty(inputIdentifier, "amount", ""); + } + }; + + const handleMax = () => { + setTokenInputProperty(inputIdentifier, "amount", balance.toString()); + }; + + return ( + +
+ + + {maxable && } + +
+ + {token.symbol} + +
+
+
+ { + setIsModalOpen(false); + }} + /> +
+ ); +}; + +export default TokenInput; diff --git a/components/app/organisms/SwapForm/TokenSelectionModal.tsx b/components/app/organisms/SwapForm/TokenSelectionModal.tsx new file mode 100644 index 0000000..b97ec55 --- /dev/null +++ b/components/app/organisms/SwapForm/TokenSelectionModal.tsx @@ -0,0 +1,69 @@ +import React, { useState } from "react"; +import { useStore } from "@/store/swapStore"; +import { Token, TokenInputs } from "@/types"; +import { X } from "lucide-react"; +import TokenSelectionItem from "@/components/app/molecules/TokenSelectionItem"; +import TokenSelectionSearchBar from "../../atoms/Swap/TokenSelectionModal/TokenSelectionSearchBar"; + +interface TokenSelectionModalProps { + isOpen: boolean; + onClose: () => void; + inputIdentifier: keyof TokenInputs; +} + +const TokenSelectionModal: React.FC = ({ + isOpen, + onClose, + inputIdentifier, +}) => { + const { setTokenInputProperty } = useStore(); + const [searchTerm, setSearchTerm] = useState(""); + + const tokens = useStore((state) => state.swappableTokens); + + const handleTokenSelect = (selectedToken: Token) => { + setTokenInputProperty(inputIdentifier, "token", selectedToken); + onClose(); + }; + + if (!isOpen) return null; + + return ( +
+
+
+

Select a token

+ +
+ + {/* Recent tokens and tokens list will go here */} +
+ YOUR TOKENS +
+
+ {tokens + .filter((token) => + token.symbol.toLowerCase().includes(searchTerm.toLowerCase()) + ) + .map((token, index) => ( + + ))} +
+
+
+ ); +}; + +export default TokenSelectionModal; diff --git a/components/app/organisms/SwapForm/TokenSelectionModalRadix.tsx b/components/app/organisms/SwapForm/TokenSelectionModalRadix.tsx new file mode 100644 index 0000000..6626c06 --- /dev/null +++ b/components/app/organisms/SwapForm/TokenSelectionModalRadix.tsx @@ -0,0 +1,79 @@ +import React, { useState } from "react"; +import * as Dialog from "@radix-ui/react-dialog"; +import { Cross1Icon } from "@radix-ui/react-icons"; // Assuming usage of Radix Icons for the X icon +import TokenSelectionItem from "@/components/app/molecules/TokenSelectionItem"; +import TokenSelectionSearchBar from "@/components/app/atoms/Swap/TokenSelectionModal/TokenSelectionSearchBar"; +import { useStore } from "@/store/swapStore"; +import { Token, TokenInputs } from "@/types"; + +interface TokenSelectionModalProps { + isOpen: boolean; + onClose: () => void; + inputIdentifier: keyof TokenInputs; +} + +const TokenSelectionModal: React.FC = ({ + isOpen, + onClose, + inputIdentifier, +}) => { + const { setTokenInputProperty } = useStore(); + const [searchTerm, setSearchTerm] = useState(""); + const tokens = useStore((state) => state.swappableTokens); + + const handleTokenSelect = (selectedToken: Token) => { + setTokenInputProperty(inputIdentifier, "token", selectedToken); + onClose(); + }; + + return ( + <> + + + +
+ + Select a token + + + + +
+ + + +
+ YOUR TOKENS +
+ +
+ {tokens + .filter((token) => + token.symbol.toLowerCase().includes(searchTerm.toLowerCase()) + ) + .map((token, index) => ( + // + + // {/* */} + ))} +
+
+ + ); +}; + +export default TokenSelectionModal; diff --git a/package.json b/package.json index 63ecf7b..d44326e 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "react-hook-form": "^7.51.1", "react-icons": "^5.0.1", "react-vega": "^7.6.0", + "seedrandom": "^3.0.5", "tailwind-merge": "^2.2.2", "tailwindcss-animate": "^1.0.7", "vega": "^5.28.0", @@ -40,6 +41,7 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@types/seedrandom": "^3.0.8", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.1.3", diff --git a/pages/_app.tsx b/pages/_app.tsx index dbf5069..cd4f805 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,8 +2,21 @@ import "@radix-ui/themes/styles.css"; import "@/styles/globals.css"; import type { AppProps } from "next/app"; import { Theme } from "@radix-ui/themes"; +import { useEffect } from "react"; +import { getSwappableTokens } from "@/utils/apis/getSwappableTokens"; +import { useStore } from "@/store/swapStore"; export default function App({ Component, pageProps }: AppProps) { + const setSwappableTokens = useStore((state) => state.setSwappableTokens); + + useEffect(() => { + const fetchTokens = async () => { + const tokens = await getSwappableTokens(); + setSwappableTokens(tokens); + }; + + fetchTokens(); + }, [setSwappableTokens]); // Dependency array is empty to ensure this runs once return ( diff --git a/pages/api/getSwappableTokens.ts b/pages/api/getSwappableTokens.ts new file mode 100644 index 0000000..1c85324 --- /dev/null +++ b/pages/api/getSwappableTokens.ts @@ -0,0 +1,24 @@ +import { Token } from "@/types/Token"; +import { NextApiRequest, NextApiResponse } from "next"; + +export default function getSwappableTokens( + req: NextApiRequest, + res: NextApiResponse +) { + const dummyTokens = [ + { + symbol: "sSCRT", + address: "secret1k0jntykt7e4g3y88ltc60czgjuqdy4c9e8fzek", + }, + { + symbol: "SEFI", + address: "secret15l9cqgz5uezgydrglaak5ahfac69kmx2qpd6xt", + }, + { + symbol: "sAAVE", + address: "secret1yxwnyk8htvvq25x2z87yj0r5tqpev452fk6h5h", + }, + ] as Token[]; + + res.status(200).json(dummyTokens); +} diff --git a/pages/app/pools/index.tsx b/pages/app/pools/index.tsx index 3fcdd1d..baf5814 100644 --- a/pages/app/pools/index.tsx +++ b/pages/app/pools/index.tsx @@ -1,5 +1,5 @@ import AppLayout from "@/components/app/compositions/AppLayout"; -import PlaceholderFromHexAddress from "@/components/app/molecules/PlaceholderFromHexAddress"; +import PlaceholderImageFromSeed from "@/components/app/molecules/PlaceholderImageFromSeed"; import { SecretString } from "@/types"; import Link from "next/link"; @@ -53,8 +53,8 @@ export default function PoolsPage() { href={`/app/pool/${pool.userAddress}`} >
-
diff --git a/pages/app/tokens/index.tsx b/pages/app/tokens/index.tsx index ac741e3..6ad712f 100644 --- a/pages/app/tokens/index.tsx +++ b/pages/app/tokens/index.tsx @@ -1,11 +1,11 @@ import AppLayout from "@/components/app/compositions/AppLayout"; -import PlaceholderFromHexAddress from "@/components/app/molecules/PlaceholderFromHexAddress"; +import PlaceholderImageFromSeed from "@/components/app/molecules/PlaceholderImageFromSeed"; import { SecretString } from "@/types"; import Link from "next/link"; const tokens = [ { - userAddress: "0x6545454465153231231231", + userAddress: "secret16545454465153231231231", name: "SCRT", network: "Secret Network", price: "$0.10", @@ -14,7 +14,7 @@ const tokens = [ volume: "$48K", }, { - userAddress: "0xacd6a516c51a651da65c165d1", + userAddress: "secret1acd6a516c51a651da65c165d1", name: "ADMT", network: "Secret Network", price: "$0.20", @@ -53,8 +53,8 @@ export default function TokensPage() { href={`/app/token/${token.userAddress}`} >
-
diff --git a/store/swapStore.ts b/store/swapStore.ts index ee8a4f6..9c8c8a4 100644 --- a/store/swapStore.ts +++ b/store/swapStore.ts @@ -1,46 +1,26 @@ import { create } from "zustand"; -import { Token } from "@/types"; - -interface TokenInputState { - token: Token; - amount: string; -} - -// Extending TokenInputs to hold identifiers for gas and slippage -export interface TokenInputs { - "swap.pay": TokenInputState; - "swap.receive": TokenInputState; -} - -// New structure for shared settings like gas and slippage across forms -interface SharedSettings { - slippage: number; - gas: number; -} - -export interface StoreState { - tokenInputs: TokenInputs; - sharedSettings: SharedSettings; // Shared settings for transactions - setTokenInputProperty: ( - inputIdentifier: keyof TokenInputs, - property: T, - value: TokenInputState[T] - ) => void; - // Generalizing setters for shared settings - setSharedSetting: ( - setting: T, - value: SharedSettings[T] - ) => void; -} +import { + SharedSettings, + StoreState, + Token, + TokenInputState, + TokenInputs, +} from "@/types"; export const useStore = create((set) => ({ tokenInputs: { "swap.pay": { - token: { symbol: "sSCRT", address: "secret1k0jnty" }, + token: { + symbol: "sSCRT", + address: "secret1k0jntykt7e4g3y88ltc60czgjuqdy4c9e8fzek", + }, amount: "", }, "swap.receive": { - token: { symbol: "SEFI", address: "secret15l9" }, + token: { + symbol: "SEFI", + address: "secret15l9cqgz5uezgydrglaak5ahfac69kmx2qpd6xt", + }, amount: "", }, }, @@ -71,4 +51,6 @@ export const useStore = create((set) => ({ ...state, sharedSettings: { ...state.sharedSettings, [setting]: value }, })), + swappableTokens: [], // Add this line to initialize the swappable tokens list + setSwappableTokens: (tokens) => set({ swappableTokens: tokens }), // Method to update the list })); diff --git a/tailwind.config.ts b/tailwind.config.ts index 8256947..dcd4889 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -34,6 +34,7 @@ const config = { }, app: { box: "#30364e", + boxHighlight: "#444a5f", input: "#181b27", selectTrigger: "#242732", buttonDisabled: "#888ea6", diff --git a/types/SecretString.ts b/types/SecretString.ts new file mode 100644 index 0000000..fceb04a --- /dev/null +++ b/types/SecretString.ts @@ -0,0 +1 @@ +export type SecretString = `secret1${string}`; diff --git a/types/Token.ts b/types/Token.ts new file mode 100644 index 0000000..b707cbc --- /dev/null +++ b/types/Token.ts @@ -0,0 +1,6 @@ +import { SecretString } from "./SecretString"; + +export interface Token { + symbol: string; + address: SecretString; +} diff --git a/types/index.ts b/types/index.ts index 13abd35..8af07b0 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,6 +1,3 @@ -export type SecretString = `secret1${string}`; - -export interface Token { - symbol: string; - address: SecretString; -} +export * from "@/types/store"; +export * from "@/types/Token"; +export * from "@/types/SecretString"; diff --git a/types/store/SharedSettings.ts b/types/store/SharedSettings.ts new file mode 100644 index 0000000..0180b66 --- /dev/null +++ b/types/store/SharedSettings.ts @@ -0,0 +1,4 @@ +export interface SharedSettings { + slippage: number; + gas: number; +} diff --git a/types/store/StoreState.ts b/types/store/StoreState.ts new file mode 100644 index 0000000..bf7e31b --- /dev/null +++ b/types/store/StoreState.ts @@ -0,0 +1,20 @@ +import { Token } from "@/types/Token"; +import { SharedSettings } from "@/types/store/SharedSettings"; +import { TokenInputState } from "@/types/store/TokenInputState"; +import { TokenInputs } from "@/types/store/TokenInputs"; + +export interface StoreState { + tokenInputs: TokenInputs; + sharedSettings: SharedSettings; + setTokenInputProperty: ( + inputIdentifier: keyof TokenInputs, + property: T, + value: TokenInputState[T] + ) => void; + setSharedSetting: ( + setting: T, + value: SharedSettings[T] + ) => void; + swappableTokens: Token[]; + setSwappableTokens: (tokens: Token[]) => void; +} diff --git a/types/store/TokenInputState.ts b/types/store/TokenInputState.ts new file mode 100644 index 0000000..d51ad7c --- /dev/null +++ b/types/store/TokenInputState.ts @@ -0,0 +1,6 @@ +import { Token } from "../Token"; + +export interface TokenInputState { + token: Token; + amount: string; +} diff --git a/types/store/TokenInputs.ts b/types/store/TokenInputs.ts new file mode 100644 index 0000000..0f7fec8 --- /dev/null +++ b/types/store/TokenInputs.ts @@ -0,0 +1,6 @@ +import { TokenInputState } from "./TokenInputState"; + +export interface TokenInputs { + "swap.pay": TokenInputState; + "swap.receive": TokenInputState; +} diff --git a/types/store/index.ts b/types/store/index.ts new file mode 100644 index 0000000..2f9f931 --- /dev/null +++ b/types/store/index.ts @@ -0,0 +1,4 @@ +export * from "./SharedSettings"; +export * from "./TokenInputState"; +export * from "./TokenInputs"; +export * from "./StoreState"; diff --git a/utils/ImageWithPlaceholder/addressTo3Colors.tsx b/utils/ImageWithPlaceholder/addressTo3Colors.tsx deleted file mode 100644 index 08d4df7..0000000 --- a/utils/ImageWithPlaceholder/addressTo3Colors.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { SecretString } from "@/types"; - -export default function addressTo3Colors(address: SecretString): string { - const hexColors = address.slice(2); - const color1 = hexColors.slice(0, 6); - const color2 = hexColors.slice(6, 12); - const color3 = hexColors.slice(12, 18); - return `shape1Color=${color1}&shape2Color=${color2}&shape3Color=${color3}`; -} diff --git a/utils/ImageWithPlaceholder/generateHexColorsFromSeed.ts b/utils/ImageWithPlaceholder/generateHexColorsFromSeed.ts new file mode 100644 index 0000000..6d8cfee --- /dev/null +++ b/utils/ImageWithPlaceholder/generateHexColorsFromSeed.ts @@ -0,0 +1,26 @@ +import seedrandom from "seedrandom"; + +/** + * Generates an array of hex colors based on a seed. + * + * @param seed - The seed used to generate the colors. + * @param numberOfColors - The number of colors to generate. Default is 3. + * @returns An array of hex colors. + */ +export default function generateHexColorsFromSeed( + seed: string, + numberOfColors: number = 3 +): string[] { + const rng = seedrandom(seed); + const colors: string[] = []; + + for (let i = 0; i < numberOfColors; i++) { + // Generate a random color + let color = Math.floor(rng() * (0xffffff + 1)).toString(16); + // Pad the string with leading zeros, if necessary, to ensure it has length 6 + color = color.padStart(6, "0"); + colors.push(color); + } + + return colors; +} diff --git a/utils/ImageWithPlaceholder/stringToHex.tsx b/utils/ImageWithPlaceholder/stringToHex.tsx deleted file mode 100644 index 6a8a299..0000000 --- a/utils/ImageWithPlaceholder/stringToHex.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { SecretString } from "@/types"; - -function stringToHex(str: string): SecretString { - return str - .split("") - .map((c) => ("0" + c.charCodeAt(0).toString(16)).slice(-2)) - .join("") as SecretString; -} - -export default stringToHex; diff --git a/utils/apis/getSwappableTokens.ts b/utils/apis/getSwappableTokens.ts new file mode 100644 index 0000000..03211c6 --- /dev/null +++ b/utils/apis/getSwappableTokens.ts @@ -0,0 +1,7 @@ +import { Token } from "@/types"; + +export const getSwappableTokens = async (): Promise => { + const response = await fetch("/api/getSwappableTokens"); + const data: Token[] = await response.json(); + return data; +};