import { useCallback, useEffect } from 'react' import { AccountInfo } from '@solana/web3.js' import useMangoStore, { DEFAULT_CONNECTION, WEBSOCKET_CONNECTION, } from '../stores/useMangoStore' import useInterval from './useInterval' import useOrderbook from './useOrderbook' const SECONDS = 1000 const _SLOW_REFRESH_INTERVAL = 10 * SECONDS const useHydrateStore = () => { const setMangoStore = useMangoStore((s) => s.set) const actions = useMangoStore((s) => s.actions) const markets = useMangoStore((s) => s.selectedMangoGroup.markets) const marketConfig = useMangoStore((s) => s.selectedMarket.config) const selectedMarket = useMangoStore((s) => s.selectedMarket.current) useOrderbook() useEffect(() => { actions.fetchMangoGroup() }, [actions]) useInterval(() => { actions.fetchMangoGroup() }, 60 * SECONDS) useEffect(() => { setMangoStore((state) => { state.selectedMarket.current = markets[marketConfig.publicKey.toString()] }) }, [marketConfig, markets, setMangoStore]) // hydrate orderbook with all markets in mango group useEffect(() => { let previousBidInfo: AccountInfo | null = null let previousAskInfo: AccountInfo | null = null if (!marketConfig) return const bidSubscriptionId = WEBSOCKET_CONNECTION.onAccountChange( marketConfig.bidsKey, (info, context) => { const lastSlot = useMangoStore.getState().connection.slot if ( !previousBidInfo || !previousBidInfo.data.equals(info.data) || (previousBidInfo.lamports !== info.lamports && context.slot > lastSlot) ) { previousBidInfo = info setMangoStore((state) => { state.accountInfos[marketConfig.bidsKey.toString()] = previousBidInfo }) } } ) const askSubscriptionId = WEBSOCKET_CONNECTION.onAccountChange( marketConfig.asksKey, (info) => { if ( !previousAskInfo || !previousAskInfo.data.equals(info.data) || previousAskInfo.lamports !== info.lamports ) { previousAskInfo = info setMangoStore((state) => { state.accountInfos[marketConfig.asksKey.toString()] = previousAskInfo }) } } ) return () => { WEBSOCKET_CONNECTION.removeAccountChangeListener(bidSubscriptionId) WEBSOCKET_CONNECTION.removeAccountChangeListener(askSubscriptionId) } }, [selectedMarket]) // fetch filled trades for selected market const fetchFills = useCallback(async () => { if (!selectedMarket) { return null } try { const loadedFills = await selectedMarket.loadFills( DEFAULT_CONNECTION, 10000 ) setMangoStore((state) => { state.selectedMarket.fills = loadedFills }) } catch (err) { console.log('Error fetching fills:', err) } }, [selectedMarket, setMangoStore]) useInterval(() => { fetchFills() }, _SLOW_REFRESH_INTERVAL) useEffect(() => { fetchFills() }, [fetchFills]) } export default useHydrateStore