Skip to content

Commit

Permalink
Add logic hook with context-to-context logics
Browse files Browse the repository at this point in the history
  • Loading branch information
Reckless-Satoshi committed Jan 11, 2024
1 parent 8af3eda commit c8e0bcc
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 99 deletions.
2 changes: 2 additions & 0 deletions frontend/src/basic/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -32,6 +33,7 @@ const Main: React.FC = () => {
const { settings, page, slideDirection, setOpen, windowSize, navbarHeight } =
useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
useLogic();

return (
<Router>
Expand Down
105 changes: 6 additions & 99 deletions frontend/src/contexts/FederationContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -50,6 +25,7 @@ export interface fetchRobotProps {
export interface UseFederationStoreType {
federation: Federation;
sortedCoordinators: string[];
delay: number;
setDelay: Dispatch<SetStateAction<number>>;
coordinatorUpdatedAt: string;
federationUpdatedAt: string;
Expand All @@ -58,6 +34,7 @@ export interface UseFederationStoreType {
export const initialFederationContext: UseFederationStoreType = {
federation: new Federation(),
sortedCoordinators: [],
delay: 5000,
setDelay: () => {},
coordinatorUpdatedAt: '',
federationUpdatedAt: '',
Expand All @@ -66,10 +43,8 @@ export const initialFederationContext: UseFederationStoreType = {
export const FederationContext = createContext<UseFederationStoreType>(initialFederationContext);

export const useFederationStore = (): UseFederationStoreType => {
const { settings, page, origin, hostUrl, open, torStatus } =
useContext<UseAppStoreType>(AppContext);
const { setMaker, garage, setBadOrder, robotUpdatedAt } =
useContext<UseGarageStoreType>(GarageContext);
const { settings, origin, hostUrl, torStatus } = useContext<UseAppStoreType>(AppContext);
const { setMaker } = useContext<UseGarageStoreType>(GarageContext);
const [federation, setFederation] = useState(initialFederationContext.federation);
const sortedCoordinators = useMemo(() => {
const sortedCoordinators = federationLottery(federation);
Expand All @@ -83,10 +58,7 @@ export const useFederationStore = (): UseFederationStoreType => {
);
const [federationUpdatedAt, setFederationUpdatedAt] = useState<string>(new Date().toISOString());

const [delay, setDelay] = useState<number>(defaultDelay);
const [timer, setTimer] = useState<NodeJS.Timer | undefined>(() =>
setInterval(() => null, delay),
);
const [delay, setDelay] = useState<number>(5000);

useEffect(() => {
// On bitcoin network change we reset book, limits and federation info and fetch everything again
Expand All @@ -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,
Expand Down
105 changes: 105 additions & 0 deletions frontend/src/contexts/LogicHook.tsx
Original file line number Diff line number Diff line change
@@ -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<UseAppStoreType>(AppContext);
const { federation, delay, setDelay } = useContext<UseFederationStoreType>(FederationContext);
const { garage, setBadOrder } = useContext<UseGarageStoreType>(GarageContext);

const [timer, setTimer] = useState<NodeJS.Timer | undefined>(() =>
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;

0 comments on commit c8e0bcc

Please sign in to comment.