From c8e0bcca214470e391eae03c2993c951654bd7f9 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Thu, 11 Jan 2024 10:19:11 +0000 Subject: [PATCH] Add logic hook with context-to-context logics --- frontend/src/basic/Main.tsx | 2 + frontend/src/contexts/FederationContext.ts | 105 ++------------------- frontend/src/contexts/LogicHook.tsx | 105 +++++++++++++++++++++ 3 files changed, 113 insertions(+), 99 deletions(-) create mode 100644 frontend/src/contexts/LogicHook.tsx diff --git a/frontend/src/basic/Main.tsx b/frontend/src/basic/Main.tsx index b87d564a9..22b4ccbe5 100644 --- a/frontend/src/basic/Main.tsx +++ b/frontend/src/basic/Main.tsx @@ -9,6 +9,7 @@ import Notifications from '../components/Notifications'; import { useTranslation } from 'react-i18next'; import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext'; +import useLogic from '../contexts/LogicHook'; const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter; @@ -32,6 +33,7 @@ const Main: React.FC = () => { const { settings, page, slideDirection, setOpen, windowSize, navbarHeight } = useContext(AppContext); const { garage } = useContext(GarageContext); + useLogic(); return ( diff --git a/frontend/src/contexts/FederationContext.ts b/frontend/src/contexts/FederationContext.ts index 43aa84c20..cc124c5a3 100644 --- a/frontend/src/contexts/FederationContext.ts +++ b/frontend/src/contexts/FederationContext.ts @@ -14,31 +14,6 @@ import { federationLottery } from '../utils'; import { AppContext, type UseAppStoreType } from './AppContext'; import { GarageContext, type UseGarageStoreType } from './GarageContext'; - -// Refresh delays (ms) according to Order status -const defaultDelay = 5000; -const statusToDelay = [ - 3000, // 'Waiting for maker bond' - 35000, // 'Public' - 180000, // 'Paused' - 3000, // 'Waiting for taker bond' - 999999, // 'Cancelled' - 999999, // 'Expired' - 8000, // 'Waiting for trade collateral and buyer invoice' - 8000, // 'Waiting only for seller trade collateral' - 8000, // 'Waiting only for buyer invoice' - 10000, // 'Sending fiat - In chatroom' - 10000, // 'Fiat sent - In chatroom' - 100000, // 'In dispute' - 999999, // 'Collaboratively cancelled' - 10000, // 'Sending satoshis to buyer' - 60000, // 'Sucessful trade' - 30000, // 'Failed lightning network routing' - 300000, // 'Wait for dispute resolution' - 300000, // 'Maker lost dispute' - 300000, // 'Taker lost dispute' -]; - export interface fetchRobotProps { coordinator?: Coordinator; newKeys?: { encPrivKey: string; pubKey: string }; @@ -50,6 +25,7 @@ export interface fetchRobotProps { export interface UseFederationStoreType { federation: Federation; sortedCoordinators: string[]; + delay: number; setDelay: Dispatch>; coordinatorUpdatedAt: string; federationUpdatedAt: string; @@ -58,6 +34,7 @@ export interface UseFederationStoreType { export const initialFederationContext: UseFederationStoreType = { federation: new Federation(), sortedCoordinators: [], + delay: 5000, setDelay: () => {}, coordinatorUpdatedAt: '', federationUpdatedAt: '', @@ -66,10 +43,8 @@ export const initialFederationContext: UseFederationStoreType = { export const FederationContext = createContext(initialFederationContext); export const useFederationStore = (): UseFederationStoreType => { - const { settings, page, origin, hostUrl, open, torStatus } = - useContext(AppContext); - const { setMaker, garage, setBadOrder, robotUpdatedAt } = - useContext(GarageContext); + const { settings, origin, hostUrl, torStatus } = useContext(AppContext); + const { setMaker } = useContext(GarageContext); const [federation, setFederation] = useState(initialFederationContext.federation); const sortedCoordinators = useMemo(() => { const sortedCoordinators = federationLottery(federation); @@ -83,10 +58,7 @@ export const useFederationStore = (): UseFederationStoreType => { ); const [federationUpdatedAt, setFederationUpdatedAt] = useState(new Date().toISOString()); - const [delay, setDelay] = useState(defaultDelay); - const [timer, setTimer] = useState(() => - setInterval(() => null, delay), - ); + const [delay, setDelay] = useState(5000); useEffect(() => { // On bitcoin network change we reset book, limits and federation info and fetch everything again @@ -101,75 +73,10 @@ export const useFederationStore = (): UseFederationStoreType => { setFederation(newFed); }, [settings.network, torStatus]); - console.log('On FederationContext "page" is:', page); - const onOrderReceived = (order: Order): void => { - let newDelay = defaultDelay; - if (order?.bad_request) { - newDelay = 99999999; - console.log('bad request on order, new delay', newDelay); - setBadOrder(order.bad_request); - garage.updateOrder(null); - } - if (order?.id) { - newDelay = - order.status >= 0 && order.status <= 18 - ? page === 'order' - ? statusToDelay[order.status] - : statusToDelay[order.status] * 5 // If user is not looking at "order" tab, refresh less often. - : 99999999; - console.log('has order id, new delay is', newDelay); - garage.updateOrder(order); - setBadOrder(undefined); - } - console.log('page:', page, 'Why remains as initial page?'); - console.log('setting delay!', newDelay); - setDelay(newDelay); - setTimer(setTimeout(fetchCurrentOrder, newDelay)); - }; - - const fetchCurrentOrder: () => void = () => { - const slot = garage?.getSlot(); - const robot = slot?.getRobot(); - if (slot?.token && slot?.activeShortAlias && robot?.activeOrderId) { - const coordinator = federation.getCoordinator(slot.activeShortAlias); - void coordinator?.fetchOrder(robot.activeOrderId, robot, slot.token).then((order) => { - onOrderReceived(order as Order); - }); - } else { - console.log('Hit no order, delay', defaultDelay); - setTimer(setTimeout(fetchCurrentOrder, defaultDelay)); - } - }; - - useEffect(() => { - clearInterval(timer); - fetchCurrentOrder(); - setDelay(defaultDelay); - return () => { - clearInterval(timer); - }; - }, [coordinatorUpdatedAt, federationUpdatedAt]); - - useEffect(() => { - if (page === 'offers') void federation.updateBook(); - }, [page]); - - useEffect(() => { - const slot = garage.getSlot(); - const robot = slot?.getRobot(); - - if (robot && garage.currentSlot) { - if (open.profile && Boolean(slot?.hashId) && slot?.token) { - void federation.fetchRobot(garage, slot?.token); // refresh/update existing robot - } else if (slot?.token && robot.encPrivKey && robot.pubKey) { - void federation.fetchRobot(garage, slot.token); // create new robot with existing token and keys (on network and coordinator change) - } - } - }, [open.profile, hostUrl, robotUpdatedAt]); - return { federation, sortedCoordinators, + delay, setDelay, coordinatorUpdatedAt, federationUpdatedAt, diff --git a/frontend/src/contexts/LogicHook.tsx b/frontend/src/contexts/LogicHook.tsx new file mode 100644 index 000000000..3e2633441 --- /dev/null +++ b/frontend/src/contexts/LogicHook.tsx @@ -0,0 +1,105 @@ +import React, { useContext, useState, useEffect } from 'react'; +import { type UseAppStoreType, AppContext } from './AppContext'; + +import { GarageContext, type UseGarageStoreType } from './GarageContext'; +import { FederationContext, UseFederationStoreType } from './FederationContext'; +import { Order } from '../models'; + +const statusToDelay = [ + 3000, // 'Waiting for maker bond' + 35000, // 'Public' + 180000, // 'Paused' + 3000, // 'Waiting for taker bond' + 999999, // 'Cancelled' + 999999, // 'Expired' + 8000, // 'Waiting for trade collateral and buyer invoice' + 8000, // 'Waiting only for seller trade collateral' + 8000, // 'Waiting only for buyer invoice' + 10000, // 'Sending fiat - In chatroom' + 10000, // 'Fiat sent - In chatroom' + 100000, // 'In dispute' + 999999, // 'Collaboratively cancelled' + 10000, // 'Sending satoshis to buyer' + 60000, // 'Sucessful trade' + 30000, // 'Failed lightning network routing' + 300000, // 'Wait for dispute resolution' + 300000, // 'Maker lost dispute' + 300000, // 'Taker lost dispute' +]; + +const useLogic = () => { + const { page, open } = useContext(AppContext); + const { federation, delay, setDelay } = useContext(FederationContext); + const { garage, setBadOrder } = useContext(GarageContext); + + const [timer, setTimer] = useState(() => + setInterval(() => null, delay), + ); + + const onOrderReceived = (order: Order): void => { + let newDelay = 5000; + if (order?.bad_request) { + newDelay = 99999999; + console.log('bad request on order, new delay', newDelay); + setBadOrder(order.bad_request); + garage.updateOrder(null); + } + if (order?.id) { + newDelay = + order.status >= 0 && order.status <= 18 + ? page === 'order' + ? statusToDelay[order.status] + : statusToDelay[order.status] * 5 // If user is not looking at "order" tab, refresh less often. + : 99999999; + console.log('has order id, new delay is', newDelay); + garage.updateOrder(order); + setBadOrder(undefined); + } + console.log('page:', page, 'Why remains as initial page?'); + console.log('setting delay!', newDelay); + setDelay(newDelay); + setTimer(setTimeout(fetchCurrentOrder, newDelay)); + }; + + const fetchCurrentOrder: () => void = () => { + const slot = garage?.getSlot(); + const robot = slot?.getRobot(); + if (slot?.token && slot?.activeShortAlias && robot?.activeOrderId) { + const coordinator = federation.getCoordinator(slot.activeShortAlias); + void coordinator?.fetchOrder(robot.activeOrderId, robot, slot.token).then((order) => { + onOrderReceived(order as Order); + }); + } else { + console.log('Hit no order, delay', 5000); + setTimer(setTimeout(fetchCurrentOrder, 5000)); + } + }; + + useEffect(() => { + clearInterval(timer); + fetchCurrentOrder(); + setDelay(5000); + return () => { + clearInterval(timer); + }; + }, [page]); + + useEffect(() => { + if (page === 'offers') void federation.updateBook(); + }, [page]); + + useEffect(() => { + const slot = garage.getSlot(); + const robot = slot?.getRobot(); + + if (robot && garage.currentSlot) { + if (open.profile && Boolean(slot?.hashId) && slot?.token) { + void federation.fetchRobot(garage, slot?.token); // refresh/update existing robot + } else if (slot?.token && robot.encPrivKey && robot.pubKey) { + void federation.fetchRobot(garage, slot.token); // create new robot with existing token and keys (on network and coordinator change) + } + } + }, [open.profile]); +}; + +export default useLogic;