import { create } from "zustand"; import { IOType, network, SUPPORTED_CHAINS } from "../constants/constants"; // import { // isEVM, // } from "@gardenfi/orderbook"; import type { Asset, Chain } from "@gardenfi/orderbook"; import { API } from "../constants/api"; import axios from "axios"; import { Quote } from "@gardenfi/core"; import type { Strategies } from "@gardenfi/core"; import { generateTokenKey } from "../utils/generateTokenKey"; type AssetConfig = Asset & { disabled?: boolean; }; import BigNumber from "bignumber.js"; // import { getBalanceMulticall } from "../utils/getBalanceMulticall"; // import { getOrderPair } from "../utils/utils"; // import type { Hex } from "viem"; export type Networks = { [chain in Chain]: ChainData & { assetConfig: Omit[] }; }; export type ChainData = { chainId: number; explorer: string; networkLogo: string; networkType: string; name: string; identifier: Chain; disabled: boolean; }; export type FiatData = { chain: Chain; htlc_address: string; token_price: number; }; export type FiatResponse = { status: string; result: FiatData[]; }; export type Assets = Record; export type Chains = Partial>; type AssetInfoState = { allChains: Chains | null; allAssets: Assets | null; assets: Assets | null; chains: Chains | null; fiatData: Record; balances: Record; isLoading: boolean; isAssetSelectorOpen: { isOpen: boolean; type: IOType; }; error: string | null; strategies: { val: Strategies | null; error: string | null; isLoading: boolean; }; setOpenAssetSelector: (type: IOType) => void; CloseAssetSelector: () => void; fetchAndSetAssetsAndChains: () => Promise; fetchAndSetStrategies: () => Promise; // fetchAndSetFiatValues: () => Promise; // fetchAndSetEvmBalances: ( // address: string, // workingRpcs: Record, // fetchOnlySeed?: boolean // ) => Promise; clearBalances: () => void; }; export const assetInfoStore = create((set, get) => ({ assets: null, chains: null, allAssets: null, allChains: null, fiatData: {}, balances: {}, isAssetSelectorOpen: { isOpen: false, type: IOType.input, }, isLoading: false, error: null, strategies: { val: null, error: null, isLoading: false, }, setOpenAssetSelector: (type) => set({ isAssetSelectorOpen: { isOpen: true, type, }, }), CloseAssetSelector: () => set({ isAssetSelectorOpen: { type: get().isAssetSelectorOpen.type, isOpen: false, }, }), fetchAndSetAssetsAndChains: async () => { try { set({ isLoading: true }); const res = await axios.get( API().data.assets(network).toString() ); const assetsData = res.data; const allChains: Chains = {}; const allAssets: Assets = {}; const assets: Assets = {}; const chains: Chains = {}; for (const chainInfo of Object.values(assetsData)) { if (!SUPPORTED_CHAINS.includes(chainInfo.identifier)) continue; allChains[chainInfo.identifier] = { chainId: chainInfo.chainId, explorer: chainInfo.explorer, networkLogo: chainInfo.networkLogo, networkType: chainInfo.networkType, name: chainInfo.name, identifier: chainInfo.identifier, disabled: chainInfo.disabled, }; let totalAssets = 0; for (const asset of chainInfo.assetConfig) { const tokenKey = generateTokenKey( chainInfo.identifier, asset.atomicSwapAddress ); allAssets[tokenKey] = { ...asset, chain: chainInfo.identifier, }; if (!asset.disabled && !chainInfo.disabled) { assets[tokenKey] = allAssets[tokenKey]; totalAssets++; } } if (totalAssets > 0) { chains[chainInfo.identifier] = allChains[chainInfo.identifier]; } } set({ allAssets, allChains, assets, chains }); } catch (error) { console.error("Failed to fetch assets data", error); set({ error: "Failed to fetch assets data" }); } finally { set({ isLoading: false }); } }, fetchAndSetStrategies: async () => { try { const quote = new Quote(API().quote.quote.toString()); set({ strategies: { ...get().strategies, isLoading: true } }); const res = await quote.getStrategies(); if (res.error) return; set({ strategies: { val: res.val, isLoading: false, error: null } }); } catch { set({ strategies: { ...get().strategies, error: "Failed to fetch strategies", isLoading: false, }, }); } }, // fetchAndSetFiatValues: async () => { // try { // const { data } = await axios.get( // API().quote.fiatValues.toString() // ); // const fiatData = data.result.reduce( // (acc, { chain, htlc_address, token_price }) => { // acc[`${chain}_${htlc_address.toLowerCase()}`] = token_price; // return acc; // }, // {} as Record // ); // set({ fiatData }); // } catch { // /*empty*/ // } // }, // fetchAndSetEvmBalances: async ( // address: string, // workingRpcs: Record, // fetchOnlySeed: boolean = false // ) => { // const { assets } = get(); // if (!assets) return; // const tokensByChain = Object.values(assets).reduce( // (acc, asset) => { // if ( // !isEVM(asset.chain) || // (fetchOnlySeed && !asset.symbol.includes("SEED")) // ) // return acc; // if (!acc[asset.chain]) acc[asset.chain] = []; // acc[asset.chain].push(asset.tokenAddress); // return acc; // }, // {} as Record // ); // try { // const balanceResults = await Promise.allSettled( // Object.entries(tokensByChain).map(async ([chain, tokenAddresses]) => { // const chainBalances = await getBalanceMulticall( // tokenAddresses as Hex[], // address as Hex, // chain as EvmChain, // workingRpcs // ); // return Object.entries(chainBalances).reduce( // (acc, [tokenAddress, balance]) => { // acc[getOrderPair(chain, tokenAddress)] = balance; // return acc; // }, // {} as Record // ); // }) // ); // const balances = balanceResults.reduce((acc, result) => { // return result.status === "fulfilled" // ? { ...acc, ...result.value } // : acc; // }, {}); // set({ balances: { ...get().balances, ...balances } }); // } catch { // /*empty*/ // } // }, clearBalances: () => set({ balances: {}, }), }));