mirror of
https://github.com/RoboSats/robosats.git
synced 2025-07-17 16:23:13 +00:00
Improve client performance
This commit is contained in:
@ -4,9 +4,14 @@ import FederationTable from '../../components/FederationTable';
|
|||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
|
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
|
||||||
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
|
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 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 { garage } = useContext<UseGarageStoreType>(GarageContext);
|
||||||
const [newAlias, setNewAlias] = useState<string>('');
|
const [newAlias, setNewAlias] = useState<string>('');
|
||||||
const [newUrl, setNewUrl] = useState<string>('');
|
const [newUrl, setNewUrl] = useState<string>('');
|
||||||
@ -15,6 +20,34 @@ const Coordinators = (): React.JSX.Element => {
|
|||||||
// Regular expression to match a valid .onion URL
|
// Regular expression to match a valid .onion URL
|
||||||
const onionUrlPattern = /^((http|https):\/\/)?[a-zA-Z2-7]{16,56}\.onion$\/?/;
|
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 = () => {
|
const addCoordinator: () => void = () => {
|
||||||
if (federation.getCoordinator(newAlias)) {
|
if (federation.getCoordinator(newAlias)) {
|
||||||
setError(t('Alias already exists'));
|
setError(t('Alias already exists'));
|
||||||
@ -24,7 +57,7 @@ const Coordinators = (): React.JSX.Element => {
|
|||||||
if (!/^((http|https):\/\/)/.test(fullNewUrl)) {
|
if (!/^((http|https):\/\/)/.test(fullNewUrl)) {
|
||||||
fullNewUrl = `http://${newUrl}`;
|
fullNewUrl = `http://${newUrl}`;
|
||||||
}
|
}
|
||||||
addNewCoordinator(newAlias, fullNewUrl);
|
addNewCoordinator(newAlias, garage, fullNewUrl);
|
||||||
garage.syncCoordinator(federation, newAlias);
|
garage.syncCoordinator(federation, newAlias);
|
||||||
setNewAlias('');
|
setNewAlias('');
|
||||||
setNewUrl('');
|
setNewUrl('');
|
||||||
|
@ -343,11 +343,9 @@ const BookTable = ({
|
|||||||
flex: 2,
|
flex: 2,
|
||||||
renderCell: (params: { row: PublicOrder }) => {
|
renderCell: (params: { row: PublicOrder }) => {
|
||||||
const currencyCode = String(currencyDict[params.row.currency.toString()]);
|
const currencyCode = String(currencyDict[params.row.currency.toString()]);
|
||||||
const coordinator =
|
const limits = federation.getLimits(params.row.coordinatorShortAlias);
|
||||||
federation.getCoordinator(params.row.coordinatorShortAlias) ??
|
|
||||||
federation.getCoordinators()[0];
|
|
||||||
const premium = parseFloat(params.row.premium);
|
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);
|
const price = (limitPrice ?? 1) * (1 + premium / 100);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -501,16 +499,13 @@ const BookTable = ({
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
renderCell: (params: { row: PublicOrder }) => {
|
renderCell: (params: { row: PublicOrder }) => {
|
||||||
const coordinator =
|
const limits = federation.getLimits(params.row.coordinatorShortAlias);
|
||||||
federation.getCoordinator(params.row.coordinatorShortAlias) ??
|
|
||||||
federation.getCoordinators()[0];
|
|
||||||
const amount =
|
const amount =
|
||||||
params.row.has_range === true
|
params.row.has_range === true
|
||||||
? parseFloat(params.row.max_amount)
|
? parseFloat(params.row.max_amount)
|
||||||
: parseFloat(params.row.amount);
|
: parseFloat(params.row.amount);
|
||||||
const premium = parseFloat(params.row.premium);
|
const premium = parseFloat(params.row.premium);
|
||||||
const price =
|
const price = (limits[params.row.currency.toString()]?.price ?? 1) * (1 + premium / 100);
|
||||||
(coordinator.limits[params.row.currency.toString()]?.price ?? 1) * (1 + premium / 100);
|
|
||||||
const satoshisNow = (100000000 * amount) / price;
|
const satoshisNow = (100000000 * amount) / price;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -388,7 +388,7 @@ const CoordinatorDialog = ({ open = false, onClose, shortAlias }: Props): React.
|
|||||||
coordinator.shortAlias,
|
coordinator.shortAlias,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
coordinator?.loadInfo();
|
if (!coordinator.info) coordinator?.loadInfo();
|
||||||
}
|
}
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ const FederationTable = ({
|
|||||||
const mobile = windowSize.width < 44;
|
const mobile = windowSize.width < 44;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
federation.loadInfo();
|
||||||
loadRatings();
|
loadRatings();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -240,7 +241,7 @@ const FederationTable = ({
|
|||||||
onClickCoordinator(params.row.shortAlias);
|
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} />
|
<CircularProgress thickness={0.35 * fontSize} size={1.5 * fontSize} />
|
||||||
) : params.row.limits !== undefined ? (
|
) : params.row.limits !== undefined ? (
|
||||||
<Link color='success' />
|
<Link color='success' />
|
||||||
|
@ -86,31 +86,26 @@ const MakerForm = ({
|
|||||||
|
|
||||||
const amountSafeThresholds = [1.03, 0.98];
|
const amountSafeThresholds = [1.03, 0.98];
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
federation
|
|
||||||
.loadInfo()
|
|
||||||
.then(() => {})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Error loading info:', error);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrencyCode(currencyDict[fav.currency === 0 ? 1 : fav.currency]);
|
setCurrencyCode(currencyDict[fav.currency === 0 ? 1 : fav.currency]);
|
||||||
}, [federationUpdatedAt]);
|
}, [federationUpdatedAt]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateCoordinatorInfo();
|
updateCoordinatorInfo();
|
||||||
}, [maker.coordinator, federationUpdatedAt]);
|
}, [maker.coordinator]);
|
||||||
|
|
||||||
const updateCoordinatorInfo = (): void => {
|
const updateCoordinatorInfo = (): void => {
|
||||||
if (maker.coordinator != null) {
|
if (maker.coordinator != null) {
|
||||||
const newLimits = federation.getCoordinator(maker.coordinator)?.limits;
|
const coordinator = federation.getCoordinator(maker.coordinator);
|
||||||
if (newLimits && Object.keys(newLimits).length !== 0) {
|
coordinator.loadInfo();
|
||||||
updateAmountLimits(newLimits, fav.currency, maker.premium);
|
coordinator.loadLimits(() => {
|
||||||
updateCurrentPrice(newLimits, fav.currency, maker.premium);
|
const newLimits = coordinator.limits;
|
||||||
setLimits(newLimits);
|
if (newLimits && Object.keys(newLimits).length !== 0) {
|
||||||
}
|
updateAmountLimits(newLimits, fav.currency, maker.premium);
|
||||||
|
updateCurrentPrice(newLimits, fav.currency, maker.premium);
|
||||||
|
setLimits(newLimits);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,8 +102,7 @@ const SelectCoordinator: React.FC<SelectCoordinatorProps> = ({
|
|||||||
flipHorizontally={false}
|
flipHorizontally={false}
|
||||||
small={true}
|
small={true}
|
||||||
/>
|
/>
|
||||||
{(coordinator?.limits === undefined ||
|
{(coordinator?.loadingInfo || coordinator?.loadingLimits) && (
|
||||||
Object.keys(coordinator?.limits).length === 0) && (
|
|
||||||
<CircularProgress
|
<CircularProgress
|
||||||
size={49}
|
size={49}
|
||||||
thickness={5}
|
thickness={5}
|
||||||
|
@ -4,8 +4,6 @@ import { Federation, Settings } from '../models';
|
|||||||
|
|
||||||
import { AppContext, type UseAppStoreType } from './AppContext';
|
import { AppContext, type UseAppStoreType } from './AppContext';
|
||||||
import { GarageContext, type UseGarageStoreType } from './GarageContext';
|
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 {
|
export interface CurrentOrderIdProps {
|
||||||
id: number | null;
|
id: number | null;
|
||||||
@ -18,18 +16,16 @@ export interface FederationContextProviderProps {
|
|||||||
|
|
||||||
export interface UseFederationStoreType {
|
export interface UseFederationStoreType {
|
||||||
federation: Federation;
|
federation: Federation;
|
||||||
coordinatorUpdatedAt: string;
|
|
||||||
federationUpdatedAt: string;
|
federationUpdatedAt: string;
|
||||||
addNewCoordinator: (alias: string, url: string) => void;
|
setFederationUpdatedAt: (federationUpdatedAt: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialFederation = new Federation('onion', new Settings(), '');
|
const initialFederation = new Federation('onion', new Settings(), '');
|
||||||
|
|
||||||
export const initialFederationContext: UseFederationStoreType = {
|
export const initialFederationContext: UseFederationStoreType = {
|
||||||
federation: initialFederation,
|
federation: initialFederation,
|
||||||
coordinatorUpdatedAt: '',
|
|
||||||
federationUpdatedAt: '',
|
federationUpdatedAt: '',
|
||||||
addNewCoordinator: () => {},
|
setFederationUpdatedAt: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FederationContext = createContext<UseFederationStoreType>(initialFederationContext);
|
export const FederationContext = createContext<UseFederationStoreType>(initialFederationContext);
|
||||||
@ -37,13 +33,10 @@ export const FederationContext = createContext<UseFederationStoreType>(initialFe
|
|||||||
export const FederationContextProvider = ({
|
export const FederationContextProvider = ({
|
||||||
children,
|
children,
|
||||||
}: FederationContextProviderProps): React.JSX.Element => {
|
}: FederationContextProviderProps): React.JSX.Element => {
|
||||||
const { settings, page, origin, hostUrl, open, torStatus, client, fav } =
|
const { settings, page, origin, hostUrl, torStatus, client, fav } =
|
||||||
useContext<UseAppStoreType>(AppContext);
|
useContext<UseAppStoreType>(AppContext);
|
||||||
const { setMaker, garage } = useContext<UseGarageStoreType>(GarageContext);
|
const { setMaker } = useContext<UseGarageStoreType>(GarageContext);
|
||||||
const [federation] = useState(initialFederationContext.federation);
|
const [federation] = useState(initialFederationContext.federation);
|
||||||
const [coordinatorUpdatedAt, setCoordinatorUpdatedAt] = useState<string>(
|
|
||||||
new Date().toISOString(),
|
|
||||||
);
|
|
||||||
const [federationUpdatedAt, setFederationUpdatedAt] = useState<string>(new Date().toISOString());
|
const [federationUpdatedAt, setFederationUpdatedAt] = useState<string>(new Date().toISOString());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -61,54 +54,16 @@ export const FederationContextProvider = ({
|
|||||||
}
|
}
|
||||||
}, [settings.network, settings.useProxy, torStatus, settings.connection]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
if (page === 'offers') void federation.loadBook();
|
if (page === 'offers') void federation.loadBook();
|
||||||
}, [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]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FederationContext.Provider
|
<FederationContext.Provider
|
||||||
value={{
|
value={{
|
||||||
federation,
|
federation,
|
||||||
coordinatorUpdatedAt,
|
|
||||||
federationUpdatedAt,
|
federationUpdatedAt,
|
||||||
addNewCoordinator,
|
setFederationUpdatedAt,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Coordinator,
|
Coordinator,
|
||||||
type Exchange,
|
type Exchange,
|
||||||
|
LimitList,
|
||||||
type Origin,
|
type Origin,
|
||||||
type PublicOrder,
|
type PublicOrder,
|
||||||
type Settings,
|
type Settings,
|
||||||
@ -90,7 +91,7 @@ export class Federation {
|
|||||||
coordinators.forEach((c) => c.updateUrl(origin, settings, hostUrl));
|
coordinators.forEach((c) => c.updateUrl(origin, settings, hostUrl));
|
||||||
this.roboPool.updateRelays(hostUrl, Object.values(this.coordinators));
|
this.roboPool.updateRelays(hostUrl, Object.values(this.coordinators));
|
||||||
|
|
||||||
void this.loadLimits();
|
coordinators[0].loadLimits();
|
||||||
|
|
||||||
if (this.connection === 'nostr') {
|
if (this.connection === 'nostr') {
|
||||||
this.loadBookNostr(coordinator !== 'any');
|
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> => {
|
loadBook = async (): Promise<void> => {
|
||||||
if (this.connection !== 'api') return;
|
if (this.connection !== 'api') return;
|
||||||
|
|
||||||
@ -229,6 +216,18 @@ export class Federation {
|
|||||||
this.triggerHook('onFederationUpdate');
|
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
|
// Coordinators
|
||||||
getCoordinators = (): Coordinator[] => {
|
getCoordinators = (): Coordinator[] => {
|
||||||
return Object.values(this.coordinators);
|
return Object.values(this.coordinators);
|
||||||
|
Reference in New Issue
Block a user