diff --git a/frontend/src/components/SettingsForm/index.tsx b/frontend/src/components/SettingsForm/index.tsx index 7d1f149d..1624675b 100644 --- a/frontend/src/components/SettingsForm/index.tsx +++ b/frontend/src/components/SettingsForm/index.tsx @@ -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); }} > diff --git a/frontend/src/contexts/FederationContext.tsx b/frontend/src/contexts/FederationContext.tsx index 4ba69a1d..dc146e0d 100644 --- a/frontend/src/contexts/FederationContext.tsx +++ b/frontend/src/contexts/FederationContext.tsx @@ -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(AppContext); const { setMaker, garage, setBadOrder } = useContext(GarageContext); - const [federation, setFederation] = useState(initialFederationContext.federation); + const [federation] = useState(new Federation(origin, settings, hostUrl)); const sortedCoordinators = useMemo(() => federationLottery(federation), []); const [coordinatorUpdatedAt, setCoordinatorUpdatedAt] = useState( 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]); diff --git a/frontend/src/models/Coordinator.model.ts b/frontend/src/models/Coordinator.model.ts index 7ba2be53..e8d8bcf0 100644 --- a/frontend/src/models/Coordinator.model.ts +++ b/frontend/src/models/Coordinator.model.ts @@ -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 => { - 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 => { + 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 => { @@ -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; diff --git a/frontend/src/models/Federation.model.ts b/frontend/src/models/Federation.model.ts index 4b26623c..7f72531e 100644 --- a/frontend/src/models/Federation.model.ts +++ b/frontend/src/models/Federation.model.ts @@ -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, [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; @@ -69,38 +78,10 @@ export class Federation { this.triggerHook('onFederationUpdate'); }; - // Setup - start = async (origin: Origin, settings: Settings, hostUrl: string): Promise => { - 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 => { 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 => { - this.loading = true; - for (const coor of Object.values(this.coordinators)) { - await coor.updateUrl(settings, origin, hostUrl); - } - this.loading = false; }; update = async (): Promise => { @@ -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(); }); } diff --git a/frontend/src/services/Native/index.d.ts b/frontend/src/services/Native/index.d.ts index e93edd55..e7dc6f68 100644 --- a/frontend/src/services/Native/index.d.ts +++ b/frontend/src/services/Native/index.d.ts @@ -15,7 +15,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; diff --git a/frontend/src/services/api/ApiNativeClient/index.ts b/frontend/src/services/api/ApiNativeClient/index.ts index bea3a46f..9ab27d91 100644 --- a/frontend/src/services/api/ApiNativeClient/index.ts +++ b/frontend/src/services/api/ApiNativeClient/index.ts @@ -90,41 +90,6 @@ class ApiNativeClient implements ApiClient { headers: this.getHeaders(auth), }).then(this.parseResponse); }; - - public fileImageUrl: (baseUrl: string, path: string) => Promise = 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((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; diff --git a/frontend/src/services/api/index.ts b/frontend/src/services/api/index.ts index b9ac94d8..d0013324 100644 --- a/frontend/src/services/api/index.ts +++ b/frontend/src/services/api/index.ts @@ -11,7 +11,6 @@ export interface ApiClient { put: (baseUrl: string, path: string, body: object, auth?: Auth) => Promise; get: (baseUrl: string, path: string, auth?: Auth) => Promise; delete: (baseUrl: string, path: string, auth?: Auth) => Promise; - fileImageUrl?: (baseUrl: string, path: string) => Promise; } export const apiClient: ApiClient = diff --git a/mobile/App.tsx b/mobile/App.tsx index 5d6b5769..b80d1e8a 100644 --- a/mobile/App.tsx +++ b/mobile/App.tsx @@ -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') { diff --git a/mobile/android/app/src/main/java/com/robosats/modules/TorModule.java b/mobile/android/app/src/main/java/com/robosats/modules/TorModule.java index ff60f9d0..0705c347 100644 --- a/mobile/android/app/src/main/java/com/robosats/modules/TorModule.java +++ b/mobile/android/app/src/main/java/com/robosats/modules/TorModule.java @@ -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 +"}");