mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 19:06:26 +00:00
Improve Federation start order
This commit is contained in:
parent
52c20099b6
commit
7128ac7157
@ -226,7 +226,6 @@ const SettingsForm = ({ dense = false }: SettingsFormProps): JSX.Element => {
|
||||
value={settings.network}
|
||||
onChange={(e, network) => {
|
||||
setSettings({ ...settings, network });
|
||||
void federation.updateUrls(origin, { ...settings, network }, hostUrl);
|
||||
systemClient.setItem('settings_network', network);
|
||||
}}
|
||||
>
|
||||
|
@ -9,7 +9,7 @@ import React, {
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
|
||||
import { type Order, Federation } from '../models';
|
||||
import { type Order, Federation, Settings } from '../models';
|
||||
|
||||
import { federationLottery } from '../utils';
|
||||
|
||||
@ -62,7 +62,7 @@ export interface UseFederationStoreType {
|
||||
}
|
||||
|
||||
export const initialFederationContext: UseFederationStoreType = {
|
||||
federation: new Federation(),
|
||||
federation: new Federation('onion', new Settings(), ''),
|
||||
sortedCoordinators: [],
|
||||
setDelay: () => {},
|
||||
currentOrderId: { id: null, shortAlias: null },
|
||||
@ -80,7 +80,7 @@ export const FederationContextProvider = ({
|
||||
const { settings, page, origin, hostUrl, open, torStatus } =
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
const { setMaker, garage, setBadOrder } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const [federation, setFederation] = useState(initialFederationContext.federation);
|
||||
const [federation] = useState(new Federation(origin, settings, hostUrl));
|
||||
const sortedCoordinators = useMemo(() => federationLottery(federation), []);
|
||||
const [coordinatorUpdatedAt, setCoordinatorUpdatedAt] = useState<string>(
|
||||
new Date().toISOString(),
|
||||
@ -102,20 +102,19 @@ export const FederationContextProvider = ({
|
||||
setMaker((maker) => {
|
||||
return { ...maker, coordinator: sortedCoordinators[0] };
|
||||
}); // default MakerForm coordinator is decided via sorted lottery
|
||||
federation.registerHook('onFederationUpdate', () => {
|
||||
setFederationUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
federation.registerHook('onCoordinatorUpdate', () => {
|
||||
setCoordinatorUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// On bitcoin network change we reset book, limits and federation info and fetch everything again
|
||||
if (window.NativeRobosats === undefined || torStatus === 'ON') {
|
||||
const newFed = initialFederationContext.federation;
|
||||
newFed.registerHook('onFederationUpdate', () => {
|
||||
setFederationUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
newFed.registerHook('onCoordinatorUpdate', () => {
|
||||
setCoordinatorUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
void newFed.start(origin, settings, hostUrl);
|
||||
setFederation(newFed);
|
||||
void federation.updateUrl(origin, settings, hostUrl);
|
||||
void federation.update();
|
||||
}
|
||||
}, [settings.network, torStatus]);
|
||||
|
||||
|
@ -97,7 +97,7 @@ function calculateSizeLimit(inputDate: Date): number {
|
||||
}
|
||||
|
||||
export class Coordinator {
|
||||
constructor(value: any) {
|
||||
constructor(value: any, origin: Origin, settings: Settings, hostUrl: string) {
|
||||
const established = new Date(value.established);
|
||||
this.longAlias = value.longAlias;
|
||||
this.shortAlias = value.shortAlias;
|
||||
@ -115,6 +115,8 @@ export class Coordinator {
|
||||
this.testnetNodesPubkeys = value.testnetNodesPubkeys;
|
||||
this.url = '';
|
||||
this.basePath = '';
|
||||
|
||||
this.updateUrl(origin, settings, hostUrl);
|
||||
}
|
||||
|
||||
// These properties are loaded from federation.json
|
||||
@ -145,22 +147,7 @@ export class Coordinator {
|
||||
public loadingLimits: boolean = false;
|
||||
public loadingRobot: boolean = true;
|
||||
|
||||
start = async (
|
||||
origin: Origin,
|
||||
settings: Settings,
|
||||
hostUrl: string,
|
||||
onUpdate: (shortAlias: string) => void = () => {},
|
||||
): Promise<void> => {
|
||||
if (this.enabled !== true) return;
|
||||
void this.updateUrl(settings, origin, hostUrl, onUpdate);
|
||||
};
|
||||
|
||||
updateUrl = async (
|
||||
settings: Settings,
|
||||
origin: Origin,
|
||||
hostUrl: string,
|
||||
onUpdate: (shortAlias: string) => void = () => {},
|
||||
): Promise<void> => {
|
||||
updateUrl = (origin: Origin, settings: Settings, hostUrl: string): void => {
|
||||
if (settings.selfhostedClient && this.shortAlias !== 'local') {
|
||||
this.url = hostUrl;
|
||||
this.basePath = `/${settings.network}/${this.shortAlias}`;
|
||||
@ -168,9 +155,6 @@ export class Coordinator {
|
||||
this.url = String(this[settings.network][origin]);
|
||||
this.basePath = '';
|
||||
}
|
||||
void this.update(() => {
|
||||
onUpdate(this.shortAlias);
|
||||
});
|
||||
};
|
||||
|
||||
update = async (onUpdate: (shortAlias: string) => void = () => {}): Promise<void> => {
|
||||
@ -205,7 +189,6 @@ export class Coordinator {
|
||||
apiClient
|
||||
.get(this.url, `${this.basePath}/api/book/`)
|
||||
.then((data) => {
|
||||
console.log('BOOK', data);
|
||||
if (!data?.not_found) {
|
||||
this.book = (data as PublicOrder[]).map((order) => {
|
||||
order.coordinatorShortAlias = this.shortAlias;
|
||||
|
@ -14,14 +14,14 @@ import { updateExchangeInfo } from './Exchange.model';
|
||||
type FederationHooks = 'onCoordinatorUpdate' | 'onFederationUpdate';
|
||||
|
||||
export class Federation {
|
||||
constructor() {
|
||||
constructor(origin: Origin, settings: Settings, hostUrl: string) {
|
||||
this.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);
|
||||
acc[key] = new Coordinator(value, origin, settings, hostUrl);
|
||||
return acc;
|
||||
}
|
||||
},
|
||||
@ -36,7 +36,16 @@ export class Federation {
|
||||
onCoordinatorUpdate: [],
|
||||
onFederationUpdate: [],
|
||||
};
|
||||
|
||||
this.loading = true;
|
||||
this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
|
||||
|
||||
const host = getHost();
|
||||
const url = `${window.location.protocol}//${host}`;
|
||||
const tesnetHost = Object.values(this.coordinators).find((coor) => {
|
||||
return Object.values(coor.testnet).includes(url);
|
||||
});
|
||||
if (tesnetHost) settings.network = 'testnet';
|
||||
}
|
||||
|
||||
public coordinators: Record<string, Coordinator>;
|
||||
@ -69,38 +78,10 @@ export class Federation {
|
||||
this.triggerHook('onFederationUpdate');
|
||||
};
|
||||
|
||||
// Setup
|
||||
start = async (origin: Origin, settings: Settings, hostUrl: string): Promise<void> => {
|
||||
const onCoordinatorStarted = (): void => {
|
||||
this.exchange.onlineCoordinators = this.exchange.onlineCoordinators + 1;
|
||||
this.onCoordinatorSaved();
|
||||
};
|
||||
|
||||
this.loading = true;
|
||||
this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
|
||||
|
||||
const host = getHost();
|
||||
const url = `${window.location.protocol}//${host}`;
|
||||
const tesnetHost = Object.values(this.coordinators).find((coor) => {
|
||||
return Object.values(coor.testnet).includes(url);
|
||||
});
|
||||
if (tesnetHost) settings.network = 'testnet';
|
||||
|
||||
updateUrl = async (origin: Origin, settings: Settings, hostUrl: string): Promise<void> => {
|
||||
for (const coor of Object.values(this.coordinators)) {
|
||||
if (coor.enabled) {
|
||||
await coor.start(origin, settings, hostUrl, onCoordinatorStarted);
|
||||
coor.updateUrl(origin, settings, hostUrl);
|
||||
}
|
||||
}
|
||||
this.updateEnabledCoordinators();
|
||||
};
|
||||
|
||||
// On Testnet/Mainnet change
|
||||
updateUrls = async (origin: Origin, settings: Settings, hostUrl: string): Promise<void> => {
|
||||
this.loading = true;
|
||||
for (const coor of Object.values(this.coordinators)) {
|
||||
await coor.updateUrl(settings, origin, hostUrl);
|
||||
}
|
||||
this.loading = false;
|
||||
};
|
||||
|
||||
update = async (): Promise<void> => {
|
||||
@ -115,9 +96,12 @@ export class Federation {
|
||||
lifetime_volume: 0,
|
||||
version: { major: 0, minor: 0, patch: 0 },
|
||||
};
|
||||
this.exchange.onlineCoordinators = 0;
|
||||
this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
|
||||
this.updateEnabledCoordinators();
|
||||
for (const coor of Object.values(this.coordinators)) {
|
||||
await coor.update(() => {
|
||||
this.exchange.onlineCoordinators = this.exchange.onlineCoordinators + 1;
|
||||
this.onCoordinatorSaved();
|
||||
});
|
||||
}
|
||||
|
2
frontend/src/services/Native/index.d.ts
vendored
2
frontend/src/services/Native/index.d.ts
vendored
@ -14,7 +14,7 @@ export interface ReactNativeWebView {
|
||||
export interface NativeWebViewMessageHttp {
|
||||
id?: number;
|
||||
category: 'http';
|
||||
type: 'post' | 'get' | 'put' | 'delete' | 'xhr';
|
||||
type: 'post' | 'get' | 'put' | 'delete';
|
||||
path: string;
|
||||
baseUrl: string;
|
||||
headers?: object;
|
||||
|
@ -90,41 +90,6 @@ class ApiNativeClient implements ApiClient {
|
||||
headers: this.getHeaders(auth),
|
||||
}).then(this.parseResponse);
|
||||
};
|
||||
|
||||
public fileImageUrl: (baseUrl: string, path: string) => Promise<string | undefined> = async (
|
||||
baseUrl,
|
||||
path,
|
||||
) => {
|
||||
if (path === '') {
|
||||
return await Promise.resolve('');
|
||||
}
|
||||
|
||||
if (this.assetsCache[path] != null) {
|
||||
return await Promise.resolve(this.assetsCache[path]);
|
||||
} else if (this.assetsPromises.has(path)) {
|
||||
return await this.assetsPromises.get(path);
|
||||
}
|
||||
|
||||
this.assetsPromises.set(
|
||||
path,
|
||||
new Promise<string>((resolve, reject) => {
|
||||
window.NativeRobosats?.postMessage({
|
||||
category: 'http',
|
||||
type: 'xhr',
|
||||
baseUrl,
|
||||
path,
|
||||
})
|
||||
.then((fileB64: { b64Data: string }) => {
|
||||
this.assetsCache[path] = `data:image/png;base64,${fileB64.b64Data}`;
|
||||
this.assetsPromises.delete(path);
|
||||
resolve(this.assetsCache[path]);
|
||||
})
|
||||
.catch(reject);
|
||||
}),
|
||||
);
|
||||
|
||||
return await this.assetsPromises.get(path);
|
||||
};
|
||||
}
|
||||
|
||||
export default ApiNativeClient;
|
||||
|
@ -11,7 +11,6 @@ export interface ApiClient {
|
||||
put: (baseUrl: string, path: string, body: object, auth?: Auth) => Promise<object | undefined>;
|
||||
get: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined>;
|
||||
delete: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined>;
|
||||
fileImageUrl?: (baseUrl: string, path: string) => Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export const apiClient: ApiClient =
|
||||
|
@ -23,7 +23,6 @@ const App = () => {
|
||||
useEffect(() => {
|
||||
TorModule.start();
|
||||
DeviceEventEmitter.addListener('TorStatus', (payload) => {
|
||||
console.log(payload.torStatus);
|
||||
if (payload.torStatus === 'OFF') TorModule.restart();
|
||||
injectMessage({
|
||||
category: 'system',
|
||||
@ -119,14 +118,6 @@ const App = () => {
|
||||
})
|
||||
.catch((e) => onCatch(data.id, e))
|
||||
.finally(TorModule.getTorStatus);
|
||||
} else if (data.type === 'xhr') {
|
||||
torClient
|
||||
.request(data.baseUrl, data.path)
|
||||
.then((response: object) => {
|
||||
injectMessageResolve(data.id, response);
|
||||
})
|
||||
.catch((e) => onCatch(data.id, e))
|
||||
.finally(TorModule.getTorStatus);
|
||||
}
|
||||
} else if (data.category === 'system') {
|
||||
if (data.type === 'init') {
|
||||
|
@ -85,7 +85,7 @@ public class TorModule extends ReactContextBaseJavaModule {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
if (response.code() != 200) {
|
||||
if (response.code() != 200 && response.code() != 201) {
|
||||
Log.d("RobosatsError", "Request error code: " + response.code());
|
||||
} else if (response.isSuccessful()) {
|
||||
promise.resolve("{\"json\":" + body + ", \"headers\": " + headersJson +"}");
|
||||
|
Loading…
Reference in New Issue
Block a user