mango-ui-v2/hooks/useHydrateStore.tsx

135 lines
4.3 KiB
TypeScript
Raw Normal View History

2021-04-06 15:11:42 -07:00
import { useEffect } from 'react'
import { Market } from '@project-serum/serum'
2021-04-29 08:08:36 -07:00
import { AccountInfo } from '@solana/web3.js'
2021-04-06 15:11:42 -07:00
import useConnection from './useConnection'
import useMangoStore from '../stores/useMangoStore'
2021-04-12 21:40:26 -07:00
import useSerumStore from '../stores/useSerumStore'
2021-04-07 08:44:22 -07:00
import useMarketList from './useMarketList'
2021-04-12 21:40:26 -07:00
import useInterval from './useInterval'
const SECONDS = 1000
2021-04-29 08:08:36 -07:00
const _SLOW_REFRESH_INTERVAL = 60 * SECONDS
2021-04-07 08:44:22 -07:00
const mangoGroupMarketsSelector = (s) => s.selectedMangoGroup.markets
const websocketConnectionSelector = (s) => s.connection.websocket
2021-04-06 15:11:42 -07:00
const useHydrateStore = () => {
const setMangoStore = useMangoStore((s) => s.set)
2021-04-12 21:40:26 -07:00
const setSerumStore = useSerumStore((s) => s.set)
2021-04-07 08:44:22 -07:00
const marketsForSelectedMangoGroup = useMangoStore(mangoGroupMarketsSelector)
const websocketConnection = useMangoStore(websocketConnectionSelector)
2021-04-14 23:16:36 -07:00
const actions = useMangoStore((s) => s.actions)
2021-04-29 08:08:36 -07:00
const { connection } = useConnection()
2021-04-07 08:44:22 -07:00
const { marketList } = useMarketList()
2021-04-06 15:11:42 -07:00
2021-04-14 23:16:36 -07:00
useEffect(() => {
2021-04-24 19:10:28 -07:00
actions.fetchAllMangoGroups()
2021-04-14 23:16:36 -07:00
actions.fetchMangoGroup()
}, [actions])
useInterval(() => {
actions.fetchMangoGroup()
2021-04-29 08:08:36 -07:00
}, 60 * SECONDS)
2021-04-07 08:44:22 -07:00
// load all markets for mangoGroup
useEffect(() => {
Promise.all(
marketList.map((mkt) => {
return Market.load(connection, mkt.address, {}, mkt.programId)
})
).then((markets) => {
setMangoStore((state) => {
2021-04-29 08:08:36 -07:00
state.selectedMarket.current = markets[0]
2021-04-07 08:44:22 -07:00
markets.forEach((market) => {
state.selectedMangoGroup.markets[market.publicKey.toString()] = market
2021-04-29 08:08:36 -07:00
const bidAcctAddress = market['_decoded'].bids.toString()
if (!(bidAcctAddress in state.accountInfos)) {
state.accountInfos[bidAcctAddress] = null
}
2021-04-29 08:08:36 -07:00
const askAcctAddress = market['_decoded'].asks.toString()
if (!(askAcctAddress in state.accountInfos)) {
state.accountInfos[askAcctAddress] = null
}
2021-04-07 08:44:22 -07:00
})
})
})
}, [marketList])
2021-04-14 23:16:36 -07:00
// hydrate orderbook with all markets in mango group
2021-04-07 08:44:22 -07:00
useEffect(() => {
const subscriptionIds = Object.entries(marketsForSelectedMangoGroup).map(
([, market]) => {
let previousBidInfo: AccountInfo<Buffer> | null = null
let previousAskInfo: AccountInfo<Buffer> | null = null
return [
websocketConnection.onAccountChange(
2021-04-07 08:44:22 -07:00
// @ts-ignore
market._decoded.bids,
(info) => {
if (
!previousBidInfo ||
!previousBidInfo.data.equals(info.data) ||
previousBidInfo.lamports !== info.lamports
) {
previousBidInfo = info
setMangoStore((state) => {
// @ts-ignore
const pkString = market._decoded.bids.toString()
state.accountInfos[pkString] = previousBidInfo
})
}
}
),
websocketConnection.onAccountChange(
2021-04-07 08:44:22 -07:00
// @ts-ignore
market._decoded.asks,
(info) => {
if (
!previousAskInfo ||
!previousAskInfo.data.equals(info.data) ||
previousAskInfo.lamports !== info.lamports
) {
previousAskInfo = info
setMangoStore((state) => {
// @ts-ignore
const pkString = market._decoded.asks.toString()
2021-04-07 08:44:22 -07:00
state.accountInfos[pkString] = previousAskInfo
})
}
}
),
]
}
)
console.log('subscription ids', subscriptionIds)
2021-04-06 15:11:42 -07:00
2021-04-07 08:44:22 -07:00
return () => {
for (const id of subscriptionIds.flat()) {
websocketConnection.removeAccountChangeListener(id)
2021-04-07 08:44:22 -07:00
}
}
}, [marketsForSelectedMangoGroup])
2021-04-12 21:40:26 -07:00
2021-04-14 23:16:36 -07:00
// fetch filled trades for selected market
2021-04-12 21:40:26 -07:00
useInterval(() => {
async function fetchFills() {
2021-04-29 07:38:28 -07:00
const market = useMangoStore.getState().selectedMarket.current
2021-04-12 21:40:26 -07:00
if (!market || !connection) {
return null
}
try {
const loadedFills = await market.loadFills(connection, 10000)
setSerumStore((state) => {
state.fills = loadedFills
})
} catch (err) {
console.log('Error fetching fills:', err)
}
}
fetchFills()
2021-04-12 21:40:26 -07:00
}, _SLOW_REFRESH_INTERVAL)
2021-04-06 15:11:42 -07:00
}
export default useHydrateStore