2024-01-12 21:05:15 +00:00
|
|
|
import React, {
|
|
|
|
createContext,
|
|
|
|
type Dispatch,
|
|
|
|
useState,
|
|
|
|
type SetStateAction,
|
|
|
|
useEffect,
|
2024-01-15 09:33:47 +00:00
|
|
|
type ReactNode,
|
2024-08-15 14:26:04 +00:00
|
|
|
useContext,
|
|
|
|
useRef,
|
2024-01-12 21:05:15 +00:00
|
|
|
} from 'react';
|
2023-10-27 10:01:59 +00:00
|
|
|
|
|
|
|
import { defaultMaker, type Maker, Garage } from '../models';
|
2023-11-26 18:00:50 +00:00
|
|
|
import { systemClient } from '../services/System';
|
2024-08-15 14:26:04 +00:00
|
|
|
import { type UseAppStoreType, AppContext } from './AppContext';
|
|
|
|
import { type UseFederationStoreType, FederationContext } from './FederationContext';
|
2023-10-27 10:01:59 +00:00
|
|
|
|
2024-01-12 21:05:15 +00:00
|
|
|
export interface GarageContextProviderProps {
|
|
|
|
children: ReactNode;
|
|
|
|
}
|
|
|
|
|
2023-10-27 10:01:59 +00:00
|
|
|
export interface UseGarageStoreType {
|
|
|
|
garage: Garage;
|
|
|
|
maker: Maker;
|
|
|
|
setMaker: Dispatch<SetStateAction<Maker>>;
|
2024-08-15 14:26:04 +00:00
|
|
|
setDelay: Dispatch<SetStateAction<number>>;
|
|
|
|
fetchSlotActiveOrder: () => void;
|
|
|
|
slotUpdatedAt: string;
|
2023-10-27 10:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const initialGarageContext: UseGarageStoreType = {
|
|
|
|
garage: new Garage(),
|
|
|
|
maker: defaultMaker,
|
|
|
|
setMaker: () => {},
|
2024-08-15 14:26:04 +00:00
|
|
|
setDelay: () => {},
|
|
|
|
fetchSlotActiveOrder: () => {},
|
|
|
|
slotUpdatedAt: '',
|
2023-10-27 10:01:59 +00:00
|
|
|
};
|
|
|
|
|
2024-08-15 14:26:04 +00:00
|
|
|
const defaultDelay = 5000;
|
|
|
|
// Refresh delays (ms) according to Order status
|
|
|
|
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'
|
|
|
|
];
|
|
|
|
|
2023-10-27 10:01:59 +00:00
|
|
|
export const GarageContext = createContext<UseGarageStoreType>(initialGarageContext);
|
|
|
|
|
2024-01-12 21:05:15 +00:00
|
|
|
export const GarageContextProvider = ({ children }: GarageContextProviderProps): JSX.Element => {
|
2023-10-27 10:01:59 +00:00
|
|
|
// All garage data structured
|
2024-08-15 14:26:04 +00:00
|
|
|
const { settings, torStatus, open, page } = useContext<UseAppStoreType>(AppContext);
|
|
|
|
const pageRef = useRef(page);
|
|
|
|
const { federation, sortedCoordinators } = useContext<UseFederationStoreType>(FederationContext);
|
2023-10-27 10:01:59 +00:00
|
|
|
const [garage] = useState<Garage>(initialGarageContext.garage);
|
|
|
|
const [maker, setMaker] = useState<Maker>(initialGarageContext.maker);
|
2024-08-15 14:26:04 +00:00
|
|
|
const [slotUpdatedAt, setSlotUpdatedAt] = useState<string>(new Date().toISOString());
|
|
|
|
const [lastOrderCheckAt] = useState<number>(+new Date());
|
|
|
|
const lastOrderCheckAtRef = useRef(lastOrderCheckAt);
|
|
|
|
const [delay, setDelay] = useState<number>(defaultDelay);
|
|
|
|
const [timer, setTimer] = useState<NodeJS.Timer | undefined>(() =>
|
|
|
|
setInterval(() => null, delay),
|
|
|
|
);
|
2023-10-27 10:01:59 +00:00
|
|
|
|
2024-08-15 14:26:04 +00:00
|
|
|
const onSlotUpdated = (): void => {
|
|
|
|
setSlotUpdatedAt(new Date().toISOString());
|
2023-10-27 10:01:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
useEffect(() => {
|
2024-08-15 14:26:04 +00:00
|
|
|
setMaker((maker) => {
|
|
|
|
return { ...maker, coordinator: sortedCoordinators[0] };
|
|
|
|
}); // default MakerForm coordinator is decided via sorted lottery
|
|
|
|
garage.registerHook('onSlotUpdate', onSlotUpdated);
|
|
|
|
clearInterval(timer);
|
|
|
|
fetchSlotActiveOrder();
|
|
|
|
|
|
|
|
return () => clearTimeout(timer);
|
2023-10-27 10:01:59 +00:00
|
|
|
}, []);
|
|
|
|
|
2024-08-15 14:26:04 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (window.NativeRobosats === undefined || torStatus === 'ON' || !settings.useProxy) {
|
|
|
|
const token = garage.getSlot()?.token;
|
|
|
|
if (token) void garage.fetchRobot(federation, token);
|
|
|
|
}
|
|
|
|
}, [settings.network, settings.useProxy, torStatus]);
|
|
|
|
|
2023-11-26 18:00:50 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (window.NativeRobosats !== undefined && !systemClient.loading) {
|
|
|
|
garage.loadSlots();
|
|
|
|
}
|
|
|
|
}, [systemClient.loading]);
|
|
|
|
|
2024-08-15 14:26:04 +00:00
|
|
|
useEffect(() => {
|
|
|
|
pageRef.current = page;
|
|
|
|
}, [page]);
|
|
|
|
|
|
|
|
// use effects to fetchRobots on Profile open
|
|
|
|
useEffect(() => {
|
|
|
|
const slot = garage.getSlot();
|
|
|
|
|
|
|
|
if (open.profile && slot?.hashId && slot?.token) {
|
|
|
|
void garage.fetchRobot(federation, slot?.token); // refresh/update existing robot
|
|
|
|
}
|
|
|
|
}, [open.profile]);
|
|
|
|
|
|
|
|
const fetchSlotActiveOrder: () => void = () => {
|
|
|
|
const slot = garage?.getSlot();
|
|
|
|
if (slot?.activeOrder?.id) {
|
|
|
|
let delay =
|
|
|
|
slot.activeOrder.status >= 0 && slot.activeOrder.status <= 18
|
|
|
|
? statusToDelay[slot.activeOrder.status]
|
|
|
|
: defaultDelay;
|
|
|
|
if (pageRef.current !== 'order') delay = delay * 5;
|
|
|
|
if (+new Date() - lastOrderCheckAtRef.current >= delay) {
|
|
|
|
void slot.fetchActiveOrder(federation).finally(() => {
|
|
|
|
lastOrderCheckAtRef.current = +new Date();
|
|
|
|
resetInterval();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
resetInterval();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
resetInterval();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const resetInterval = (): void => {
|
|
|
|
clearInterval(timer);
|
|
|
|
setDelay(defaultDelay);
|
|
|
|
setTimer(setTimeout(() => fetchSlotActiveOrder(), defaultDelay));
|
|
|
|
};
|
|
|
|
|
2024-01-12 21:05:15 +00:00
|
|
|
return (
|
|
|
|
<GarageContext.Provider
|
|
|
|
value={{
|
|
|
|
garage,
|
|
|
|
maker,
|
|
|
|
setMaker,
|
2024-08-15 14:26:04 +00:00
|
|
|
setDelay,
|
|
|
|
fetchSlotActiveOrder,
|
|
|
|
slotUpdatedAt,
|
2024-01-12 21:05:15 +00:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</GarageContext.Provider>
|
|
|
|
);
|
2023-10-27 10:01:59 +00:00
|
|
|
};
|