robosats/frontend/src/models/Federation.model.ts

128 lines
3.4 KiB
TypeScript
Raw Normal View History

import {
Coordinator,
2023-10-27 11:00:53 +00:00
type Exchange,
type Garage,
type Origin,
type PublicOrder,
type Robot,
type Settings,
defaultExchange,
} from '.';
import defaultFederation from '../../static/federation.json';
2023-10-27 11:00:53 +00:00
import { type CurrentOrder } from '../contexts/FederationContext';
import { updateExchangeInfo } from './Exchange.model';
type FederationHooks = 'onCoordinatorUpdate' | 'onFederationReady';
export class Federation {
constructor() {
this.coordinators = Object.entries(defaultFederation).reduce(
(acc: Record<string, Coordinator>, [key, value]: [string, any]) => {
acc[key] = new Coordinator(value);
return acc;
},
{},
);
this.exchange = {
...defaultExchange,
totalCoordinators: Object.keys(this.coordinators).length,
};
this.book = [];
this.hooks = {
onCoordinatorUpdate: [],
onFederationReady: [],
};
this.loading = true;
}
public coordinators: Record<string, Coordinator>;
public exchange: Exchange;
public book: PublicOrder[];
public loading: boolean;
2023-10-27 11:00:53 +00:00
public hooks: Record<FederationHooks, Array<() => void>>;
// Hooks
registerHook = (hookName: FederationHooks, fn: () => void): void => {
this.hooks[hookName].push(fn);
};
triggerHook = (hookName: FederationHooks): void => {
2023-10-27 11:00:53 +00:00
this.hooks[hookName]?.forEach((fn) => {
fn();
});
};
onCoordinatorSaved = (shortAlias: string) => {
this.book = [...this.book, ...this.getCoordinator(shortAlias).book];
this.loading = false;
this.triggerHook('onCoordinatorUpdate');
if (Object.values(this.coordinators).every((coor) => coor.isUpdated())) {
this.updateExchange();
this.triggerHook('onFederationReady');
}
};
// Setup
start = (origin: Origin, settings: Settings, hostUrl: string): void => {
const onCoordinatorStarted = (shortAlias: string) => {
this.exchange.onlineCoordinators = this.exchange.onlineCoordinators + 1;
this.onCoordinatorSaved(shortAlias);
};
this.loading = true;
2023-10-27 11:00:53 +00:00
Object.values(this.coordinators).forEach(async (coor) => {
await coor.start(origin, settings, hostUrl, onCoordinatorStarted);
});
};
update = (): void => {
this.loading = false;
2023-10-27 11:00:53 +00:00
Object.values(this.coordinators).forEach(async (coor) => {
await coor.update(() => {
this.onCoordinatorSaved(coor.shortAlias);
2023-10-27 11:00:53 +00:00
});
});
};
updateExchange = () => {
this.exchange.info = updateExchangeInfo(this);
};
// Fetchs
fetchRobot = async (garage: Garage, slot: number): Promise<void> => {
Object.values(this.coordinators).forEach((coor) => {
coor.fecthRobot(garage, slot);
});
};
fetchOrder = async (currentOrder: CurrentOrder, robot: Robot): Promise<CurrentOrder | null> => {
if (currentOrder.shortAlias !== null) {
const coordinator = this.coordinators[currentOrder.shortAlias];
if (coordinator && currentOrder.id !== null) {
const newOrber = await coordinator.fetchOrder(currentOrder.id, robot);
return {
...currentOrder,
order: newOrber,
};
}
}
return currentOrder;
};
2023-10-27 11:00:53 +00:00
// Coordinators
getCoordinator = (shortAlias: string): Coordinator => {
return this.coordinators[shortAlias];
};
disableCoordinator = (shortAlias: string) => {
this.coordinators[shortAlias].disable();
};
enableCoordinator = (shortAlias: string) => {
this.coordinators[shortAlias].enable();
};
}
export default Federation;