Improve client performance

This commit is contained in:
koalasat
2025-07-10 18:23:45 +02:00
parent fb73c963f0
commit cd031149de
8 changed files with 73 additions and 96 deletions

View File

@ -4,9 +4,14 @@ import FederationTable from '../../components/FederationTable';
import { t } from 'i18next';
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
import { Garage } from '../../models';
import { Origin, Origins } from '../../models/Coordinator.model';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
const Coordinators = (): React.JSX.Element => {
const { federation, addNewCoordinator } = useContext<UseFederationStoreType>(FederationContext);
const { settings, origin, hostUrl } = useContext<UseAppStoreType>(AppContext);
const { federation, setFederationUpdatedAt } =
useContext<UseFederationStoreType>(FederationContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const [newAlias, setNewAlias] = useState<string>('');
const [newUrl, setNewUrl] = useState<string>('');
@ -15,6 +20,34 @@ const Coordinators = (): React.JSX.Element => {
// Regular expression to match a valid .onion URL
const onionUrlPattern = /^((http|https):\/\/)?[a-zA-Z2-7]{16,56}\.onion$\/?/;
const addNewCoordinator: (alias: string, garage: Garage, url: string) => void = (
alias,
garage,
url,
) => {
if (!federation.getCoordinator(alias)) {
const attributes: object = {
longAlias: alias,
shortAlias: alias,
federated: false,
enabled: true,
};
const origins: Origins = {
clearnet: undefined,
onion: url as Origin,
i2p: undefined,
};
if (settings.network === 'mainnet') {
attributes.mainnet = origins;
} else {
attributes.testnet = origins;
}
federation.addCoordinator(origin, settings, hostUrl, attributes);
garage.syncCoordinator(federation, alias);
setFederationUpdatedAt(new Date().toISOString());
}
};
const addCoordinator: () => void = () => {
if (federation.getCoordinator(newAlias)) {
setError(t('Alias already exists'));
@ -24,7 +57,7 @@ const Coordinators = (): React.JSX.Element => {
if (!/^((http|https):\/\/)/.test(fullNewUrl)) {
fullNewUrl = `http://${newUrl}`;
}
addNewCoordinator(newAlias, fullNewUrl);
addNewCoordinator(newAlias, garage, fullNewUrl);
garage.syncCoordinator(federation, newAlias);
setNewAlias('');
setNewUrl('');

View File

@ -343,11 +343,9 @@ const BookTable = ({
flex: 2,
renderCell: (params: { row: PublicOrder }) => {
const currencyCode = String(currencyDict[params.row.currency.toString()]);
const coordinator =
federation.getCoordinator(params.row.coordinatorShortAlias) ??
federation.getCoordinators()[0];
const limits = federation.getLimits(params.row.coordinatorShortAlias);
const premium = parseFloat(params.row.premium);
const limitPrice = coordinator.limits[params.row.currency.toString()]?.price;
const limitPrice = limits[params.row.currency.toString()]?.price;
const price = (limitPrice ?? 1) * (1 + premium / 100);
return (
@ -501,16 +499,13 @@ const BookTable = ({
type: 'number',
flex: 1,
renderCell: (params: { row: PublicOrder }) => {
const coordinator =
federation.getCoordinator(params.row.coordinatorShortAlias) ??
federation.getCoordinators()[0];
const limits = federation.getLimits(params.row.coordinatorShortAlias);
const amount =
params.row.has_range === true
? parseFloat(params.row.max_amount)
: parseFloat(params.row.amount);
const premium = parseFloat(params.row.premium);
const price =
(coordinator.limits[params.row.currency.toString()]?.price ?? 1) * (1 + premium / 100);
const price = (limits[params.row.currency.toString()]?.price ?? 1) * (1 + premium / 100);
const satoshisNow = (100000000 * amount) / price;
return (

View File

@ -388,7 +388,7 @@ const CoordinatorDialog = ({ open = false, onClose, shortAlias }: Props): React.
coordinator.shortAlias,
);
}
coordinator?.loadInfo();
if (!coordinator.info) coordinator?.loadInfo();
}
}, [open]);

View File

@ -57,6 +57,7 @@ const FederationTable = ({
const mobile = windowSize.width < 44;
useEffect(() => {
federation.loadInfo();
loadRatings();
}, []);
@ -240,7 +241,7 @@ const FederationTable = ({
onClickCoordinator(params.row.shortAlias);
}}
>
{Boolean(params.row.loadingLimits) && Boolean(params.row.enabled) ? (
{Boolean(params.row.loadingInfo) && Boolean(params.row.enabled) ? (
<CircularProgress thickness={0.35 * fontSize} size={1.5 * fontSize} />
) : params.row.limits !== undefined ? (
<Link color='success' />

View File

@ -86,31 +86,26 @@ const MakerForm = ({
const amountSafeThresholds = [1.03, 0.98];
useEffect(() => {
federation
.loadInfo()
.then(() => {})
.catch((error) => {
console.error('Error loading info:', error);
});
}, []);
useEffect(() => {
setCurrencyCode(currencyDict[fav.currency === 0 ? 1 : fav.currency]);
}, [federationUpdatedAt]);
useEffect(() => {
updateCoordinatorInfo();
}, [maker.coordinator, federationUpdatedAt]);
}, [maker.coordinator]);
const updateCoordinatorInfo = (): void => {
if (maker.coordinator != null) {
const newLimits = federation.getCoordinator(maker.coordinator)?.limits;
if (newLimits && Object.keys(newLimits).length !== 0) {
updateAmountLimits(newLimits, fav.currency, maker.premium);
updateCurrentPrice(newLimits, fav.currency, maker.premium);
setLimits(newLimits);
}
const coordinator = federation.getCoordinator(maker.coordinator);
coordinator.loadInfo();
coordinator.loadLimits(() => {
const newLimits = coordinator.limits;
if (newLimits && Object.keys(newLimits).length !== 0) {
updateAmountLimits(newLimits, fav.currency, maker.premium);
updateCurrentPrice(newLimits, fav.currency, maker.premium);
setLimits(newLimits);
}
});
}
};

View File

@ -102,8 +102,7 @@ const SelectCoordinator: React.FC<SelectCoordinatorProps> = ({
flipHorizontally={false}
small={true}
/>
{(coordinator?.limits === undefined ||
Object.keys(coordinator?.limits).length === 0) && (
{(coordinator?.loadingInfo || coordinator?.loadingLimits) && (
<CircularProgress
size={49}
thickness={5}

View File

@ -4,8 +4,6 @@ import { Federation, Settings } from '../models';
import { AppContext, type UseAppStoreType } from './AppContext';
import { GarageContext, type UseGarageStoreType } from './GarageContext';
import type Coordinator from '../models/Coordinator.model';
import { type Origin, type Origins } from '../models/Coordinator.model';
export interface CurrentOrderIdProps {
id: number | null;
@ -18,18 +16,16 @@ export interface FederationContextProviderProps {
export interface UseFederationStoreType {
federation: Federation;
coordinatorUpdatedAt: string;
federationUpdatedAt: string;
addNewCoordinator: (alias: string, url: string) => void;
setFederationUpdatedAt: (federationUpdatedAt: string) => void;
}
const initialFederation = new Federation('onion', new Settings(), '');
export const initialFederationContext: UseFederationStoreType = {
federation: initialFederation,
coordinatorUpdatedAt: '',
federationUpdatedAt: '',
addNewCoordinator: () => {},
setFederationUpdatedAt: () => {},
};
export const FederationContext = createContext<UseFederationStoreType>(initialFederationContext);
@ -37,13 +33,10 @@ export const FederationContext = createContext<UseFederationStoreType>(initialFe
export const FederationContextProvider = ({
children,
}: FederationContextProviderProps): React.JSX.Element => {
const { settings, page, origin, hostUrl, open, torStatus, client, fav } =
const { settings, page, origin, hostUrl, torStatus, client, fav } =
useContext<UseAppStoreType>(AppContext);
const { setMaker, garage } = useContext<UseGarageStoreType>(GarageContext);
const { setMaker } = useContext<UseGarageStoreType>(GarageContext);
const [federation] = useState(initialFederationContext.federation);
const [coordinatorUpdatedAt, setCoordinatorUpdatedAt] = useState<string>(
new Date().toISOString(),
);
const [federationUpdatedAt, setFederationUpdatedAt] = useState<string>(new Date().toISOString());
useEffect(() => {
@ -61,54 +54,16 @@ export const FederationContextProvider = ({
}
}, [settings.network, settings.useProxy, torStatus, settings.connection]);
const addNewCoordinator: (alias: string, url: string) => void = (alias, url) => {
if (!federation.getCoordinator(alias)) {
const attributes: object = {
longAlias: alias,
shortAlias: alias,
federated: false,
enabled: true,
};
const origins: Origins = {
clearnet: undefined,
onion: url as Origin,
i2p: undefined,
};
if (settings.network === 'mainnet') {
attributes.mainnet = origins;
} else {
attributes.testnet = origins;
}
federation.addCoordinator(origin, settings, hostUrl, attributes);
const newCoordinator: Coordinator = federation.getCoordinator(alias);
newCoordinator.loadLimits(() => {
setCoordinatorUpdatedAt(new Date().toISOString());
});
garage.syncCoordinator(federation, alias);
setFederationUpdatedAt(new Date().toISOString());
}
};
useEffect(() => {
if (page === 'offers') void federation.loadBook();
}, [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]);
return (
<FederationContext.Provider
value={{
federation,
coordinatorUpdatedAt,
federationUpdatedAt,
addNewCoordinator,
setFederationUpdatedAt,
}}
>
{children}

View File

@ -1,6 +1,7 @@
import {
Coordinator,
type Exchange,
LimitList,
type Origin,
type PublicOrder,
type Settings,
@ -90,7 +91,7 @@ export class Federation {
coordinators.forEach((c) => c.updateUrl(origin, settings, hostUrl));
this.roboPool.updateRelays(hostUrl, Object.values(this.coordinators));
void this.loadLimits();
coordinators[0].loadLimits();
if (this.connection === 'nostr') {
this.loadBookNostr(coordinator !== 'any');
@ -194,20 +195,6 @@ export class Federation {
}
};
loadLimits = async (): Promise<void> => {
this.loading = true;
this.exchange.onlineCoordinators = 0;
this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
this.updateEnabledCoordinators();
for (const coor of Object.values(this.coordinators)) {
coor.loadLimits(() => {
this.exchange.onlineCoordinators = this.exchange.onlineCoordinators + 1;
this.onCoordinatorSaved();
});
}
};
loadBook = async (): Promise<void> => {
if (this.connection !== 'api') return;
@ -229,6 +216,18 @@ export class Federation {
this.triggerHook('onFederationUpdate');
};
getLimits = (shortAlias: string): LimitList => {
console.log('shortAlias', shortAlias);
let limits = this.coordinators[shortAlias]?.limits || {};
console.log('limits pre', Object.keys(limits).length);
if (Object.keys(limits).length === 0) {
limits = this.getCoordinators()[0]?.limits;
}
console.log('limits', Object.keys(limits).length);
return limits;
};
// Coordinators
getCoordinators = (): Coordinator[] => {
return Object.values(this.coordinators);