Federation coordinators list refactor

This commit is contained in:
koalasat 2024-10-18 12:36:26 +02:00
parent 3edd9280a5
commit 1695745cac
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
12 changed files with 53 additions and 56 deletions

View File

@ -25,7 +25,7 @@ const MakerPage = (): JSX.Element => {
const matches = useMemo(() => {
return filterOrders({
orders: Object.values(federation.book),
federation,
baseFilter: {
currency: fav.currency === 0 ? 1 : fav.currency,
type: fav.type,

View File

@ -26,7 +26,7 @@ import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageCon
const RobotPage = (): JSX.Element => {
const { torStatus, windowSize, settings, page, client } = useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const { federation, sortedCoordinators } = useContext<UseFederationStoreType>(FederationContext);
const { federation } = useContext<UseFederationStoreType>(FederationContext);
const { t } = useTranslation();
const params = useParams();
const urlToken = settings.selfhostedClient ? params.token : null;
@ -64,7 +64,7 @@ const RobotPage = (): JSX.Element => {
setInputToken(token);
genKey(token)
.then((key) => {
garage.createRobot(token, sortedCoordinators, {
garage.createRobot(token, Object.keys(federation.coordinators), {
token,
pubKey: key.publicKeyArmored,
encPrivKey: key.encryptedPrivateKeyArmored,

View File

@ -350,8 +350,9 @@ const BookControl = ({
<FlagWithProps code='ANY' />
</div>
</MenuItem>
{Object.values(federation.coordinators).map((coordinator) =>
coordinator.enabled ? (
{Object.values(federation.coordinators)
.filter((coord) => coord.enabled)
.map((coordinator) => (
<MenuItem
key={coordinator.shortAlias}
value={coordinator.shortAlias}
@ -367,10 +368,7 @@ const BookControl = ({
/>
</div>
</MenuItem>
) : (
<></>
),
)}
))}
</Select>
</Grid>
</>

View File

@ -895,7 +895,7 @@ const BookTable = ({
const filteredOrders = useMemo(() => {
return showControls
? filterOrders({
orders,
federation,
baseFilter: fav,
paymentMethods,
})

View File

@ -21,8 +21,7 @@ const FederationTable = ({
fillContainer = false,
}: FederationTableProps): JSX.Element => {
const { t } = useTranslation();
const { federation, sortedCoordinators, federationUpdatedAt } =
useContext<UseFederationStoreType>(FederationContext);
const { federation, federationUpdatedAt } = useContext<UseFederationStoreType>(FederationContext);
const { setOpen, settings } = useContext<UseAppStoreType>(AppContext);
const theme = useTheme();
const [pageSize, setPageSize] = useState<number>(0);
@ -214,14 +213,6 @@ const FederationTable = ({
}
};
const reorderedCoordinators = useMemo(() => {
return sortedCoordinators.reduce((coordinators, key) => {
coordinators[key] = federation.coordinators[key];
return coordinators;
}, {});
}, [settings.network, federationUpdatedAt]);
return (
<Box
sx={
@ -235,7 +226,7 @@ const FederationTable = ({
localeText={localeText}
rowHeight={3.714 * theme.typography.fontSize}
headerHeight={3.25 * theme.typography.fontSize}
rows={Object.values(reorderedCoordinators)}
rows={Object.values(federation.coordinators)}
getRowId={(params: Coordinator) => params.shortAlias}
columns={columns}
checkboxSelection={false}

View File

@ -26,7 +26,7 @@ const SelectCoordinator: React.FC<SelectCoordinatorProps> = ({
setCoordinator,
}) => {
const { setOpen } = useContext<UseAppStoreType>(AppContext);
const { federation, sortedCoordinators } = useContext<UseFederationStoreType>(FederationContext);
const { federation } = useContext<UseFederationStoreType>(FederationContext);
const theme = useTheme();
const { t } = useTranslation();
@ -109,18 +109,20 @@ const SelectCoordinator: React.FC<SelectCoordinatorProps> = ({
onChange={handleCoordinatorChange}
disableUnderline
>
{sortedCoordinators.map((shortAlias: string): JSX.Element | null => {
let row: JSX.Element | null = null;
const item = federation.getCoordinator(shortAlias);
if (item.enabled === true) {
row = (
<MenuItem key={shortAlias} value={shortAlias}>
<Typography>{item.longAlias}</Typography>
</MenuItem>
);
}
return row;
})}
{Object.keys(federation.coordinators).map(
(shortAlias: string): JSX.Element | null => {
let row: JSX.Element | null = null;
const item = federation.getCoordinator(shortAlias);
if (item.enabled === true) {
row = (
<MenuItem key={shortAlias} value={shortAlias}>
<Typography>{item.longAlias}</Typography>
</MenuItem>
);
}
return row;
},
)}
</Select>
</Grid>
</Grid>

View File

@ -27,7 +27,6 @@ export interface FederationContextProviderProps {
export interface UseFederationStoreType {
federation: Federation;
sortedCoordinators: string[];
coordinatorUpdatedAt: string;
federationUpdatedAt: string;
addNewCoordinator: (alias: string, url: string) => void;
@ -35,7 +34,6 @@ export interface UseFederationStoreType {
export const initialFederationContext: UseFederationStoreType = {
federation: new Federation('onion', new Settings(), ''),
sortedCoordinators: [],
coordinatorUpdatedAt: '',
federationUpdatedAt: '',
addNewCoordinator: () => {},
@ -50,7 +48,6 @@ export const FederationContextProvider = ({
useContext<UseAppStoreType>(AppContext);
const { setMaker, garage } = useContext<UseGarageStoreType>(GarageContext);
const [federation] = useState(new Federation(origin, settings, hostUrl));
const [sortedCoordinators, setSortedCoordinators] = useState(federationLottery(federation));
const [coordinatorUpdatedAt, setCoordinatorUpdatedAt] = useState<string>(
new Date().toISOString(),
);
@ -58,7 +55,7 @@ export const FederationContextProvider = ({
useEffect(() => {
setMaker((maker) => {
return { ...maker, coordinator: sortedCoordinators[0] };
return { ...maker, coordinator: Object.keys(federation.coordinators)[0] };
}); // default MakerForm coordinator is decided via sorted lottery
federation.registerHook('onFederationUpdate', () => {
setFederationUpdatedAt(new Date().toISOString());
@ -122,7 +119,6 @@ export const FederationContextProvider = ({
<FederationContext.Provider
value={{
federation,
sortedCoordinators,
coordinatorUpdatedAt,
federationUpdatedAt,
addNewCoordinator,

View File

@ -66,7 +66,7 @@ export const GarageContextProvider = ({ children }: GarageContextProviderProps):
// All garage data structured
const { settings, torStatus, open, page, client } = useContext<UseAppStoreType>(AppContext);
const pageRef = useRef(page);
const { federation, sortedCoordinators } = useContext<UseFederationStoreType>(FederationContext);
const { federation } = useContext<UseFederationStoreType>(FederationContext);
const [garage] = useState<Garage>(initialGarageContext.garage);
const [maker, setMaker] = useState<Maker>(initialGarageContext.maker);
const [slotUpdatedAt, setSlotUpdatedAt] = useState<string>(new Date().toISOString());
@ -83,7 +83,7 @@ export const GarageContextProvider = ({ children }: GarageContextProviderProps):
useEffect(() => {
setMaker((maker) => {
return { ...maker, coordinator: sortedCoordinators[0] };
return { ...maker, coordinator: Object.keys(federation.coordinators)[0] };
}); // default MakerForm coordinator is decided via sorted lottery
garage.registerHook('onSlotUpdate', onSlotUpdated);
clearInterval(timer);

View File

@ -126,7 +126,7 @@ export class Coordinator {
this.longAlias = value.longAlias;
this.shortAlias = value.shortAlias;
this.description = value.description;
this.federated = value.federated;
this.federated = value.federated ?? false;
this.motto = value.motto;
this.color = value.color;
this.size_limit = value.badges.isFounder ? 21 * 100000000 : calculateSizeLimit(established);

View File

@ -1,4 +1,3 @@
import { SimplePool, VerifiedEvent, Event } from 'nostr-tools';
import {
Coordinator,
type Exchange,
@ -9,7 +8,7 @@ import {
} from '.';
import defaultFederation from '../../static/federation.json';
import { systemClient } from '../services/System';
import { getHost } from '../utils';
import { federationLottery, getHost } from '../utils';
import { coordinatorDefaultValues } from './Coordinator.model';
import { updateExchangeInfo } from './Exchange.model';
import eventToPublicOrder from '../utils/nostr';
@ -20,19 +19,25 @@ type FederationHooks = 'onFederationUpdate';
export class Federation {
constructor(origin: Origin, settings: Settings, hostUrl: string) {
this.coordinators = Object.entries(defaultFederation).reduce(
const coordinators = Object.entries(defaultFederation).reduce(
(acc: Record<string, Coordinator>, [key, value]: [string, any]) => {
if (getHost() !== '127.0.0.1:8000' && key === 'local') {
// Do not add `Local Dev` unless it is running on localhost
return acc;
} else {
acc[key] = new Coordinator(value, origin, settings, hostUrl);
acc[key].federated = true;
return acc;
}
},
{},
);
this.coordinators = {};
federationLottery().forEach((alias) => {
if (coordinators[alias]) this.coordinators[alias] = coordinators[alias];
});
this.exchange = {
...defaultExchange,
totalCoordinators: Object.keys(this.coordinators).length,
@ -42,10 +47,10 @@ export class Federation {
onFederationUpdate: [],
};
Object.keys(defaultFederation).forEach((key) => {
Object.keys(this.coordinators).forEach((key) => {
if (key !== 'local' || getHost() === '127.0.0.1:8000') {
// Do not add `Local Dev` unless it is running on localhost
this.addCoordinator(origin, settings, hostUrl, defaultFederation[key]);
this.addCoordinator(origin, settings, hostUrl, this.coordinators[key]);
}
});

View File

@ -11,14 +11,14 @@
// donate to the development fund. This is the only way envisioned to incentivize
// donations to the development fund.
import { type Federation } from '../models';
import defaultFederation from '../../static/federation.json';
export default function federationLottery(federation: Federation): string[] {
export default function federationLottery(): string[] {
// Create an array to store the coordinator short aliases and their corresponding weights (chance)
const coordinatorChance: Array<{ shortAlias: string; chance: number }> = [];
// Convert the `federation` object into an array of {shortAlias, chance}
Object.values(federation.coordinators).forEach((coor) => {
Object.values(defaultFederation).forEach((coor) => {
const chance = coor.badges.donatesToDevFund > 50 ? 50 : coor.badges?.donatesToDevFund;
coordinatorChance.push({ shortAlias: coor.shortAlias, chance });
});

View File

@ -1,4 +1,4 @@
import { type PublicOrder, type Favorites } from '../models';
import { type PublicOrder, type Favorites, Federation } from '../models';
interface AmountFilter {
amount: string;
@ -8,9 +8,9 @@ interface AmountFilter {
}
interface FilterOrders {
orders: PublicOrder[];
federation: Federation;
baseFilter: Favorites;
premium: number | null;
premium?: number | null;
amountFilter?: AmountFilter | null;
paymentMethods?: string[];
}
@ -60,13 +60,17 @@ const filterByPremium = function (order: PublicOrder, premium: number): boolean
};
const filterOrders = function ({
orders,
federation,
baseFilter,
premium = null,
paymentMethods = [],
amountFilter = null,
}: FilterOrders): PublicOrder[] {
const filteredOrders = orders.filter((order) => {
const enabledCoordinators = Object.values(federation.coordinators)
.filter((coord) => coord.enabled)
.map((coord) => coord.shortAlias);
const filteredOrders = Object.values(federation.book).filter((order) => {
const coordinatorCheck = enabledCoordinators.includes(order.coordinatorShortAlias ?? '');
const typeChecks = order.type === baseFilter.type || baseFilter.type == null;
const modeChecks = baseFilter.mode === 'fiat' ? !(order.currency === 1000) : true;
const premiumChecks = premium !== null ? filterByPremium(order, premium) : true;
@ -77,6 +81,7 @@ const filterOrders = function ({
const hostChecks =
baseFilter.coordinator !== 'any' ? filterByHost(order, baseFilter.coordinator) : true;
return (
coordinatorCheck &&
typeChecks &&
modeChecks &&
premiumChecks &&