mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-05-02 23:05:10 -04:00
refactor(gui): Seperate background refresh logic (#193)
This commit is contained in:
parent
b409db35d0
commit
d953114c49
9 changed files with 151 additions and 159 deletions
|
@ -4,22 +4,26 @@
|
||||||
// - fetch alerts to be displayed to the user
|
// - fetch alerts to be displayed to the user
|
||||||
// - and to submit feedback
|
// - and to submit feedback
|
||||||
// - fetch currency rates from CoinGecko
|
// - fetch currency rates from CoinGecko
|
||||||
|
|
||||||
import { Alert, ExtendedProviderStatus } from "models/apiModel";
|
import { Alert, ExtendedProviderStatus } from "models/apiModel";
|
||||||
import { store } from "./store/storeRenderer";
|
import { store } from "./store/storeRenderer";
|
||||||
import { setBtcPrice, setXmrBtcRate, setXmrPrice } from "store/features/ratesSlice";
|
import { setBtcPrice, setXmrBtcRate, setXmrPrice } from "store/features/ratesSlice";
|
||||||
import { FiatCurrency } from "store/features/settingsSlice";
|
import { FiatCurrency } from "store/features/settingsSlice";
|
||||||
|
import { setAlerts } from "store/features/alertsSlice";
|
||||||
|
import { registryConnectionFailed, setRegistryProviders } from "store/features/providersSlice";
|
||||||
|
import logger from "utils/logger";
|
||||||
|
|
||||||
const API_BASE_URL = "https://api.unstoppableswap.net";
|
const PUBLIC_REGISTRY_API_BASE_URL = "https://api.unstoppableswap.net";
|
||||||
|
|
||||||
export async function fetchProvidersViaHttp(): Promise<
|
async function fetchProvidersViaHttp(): Promise<
|
||||||
ExtendedProviderStatus[]
|
ExtendedProviderStatus[]
|
||||||
> {
|
> {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/list`);
|
const response = await fetch(`${PUBLIC_REGISTRY_API_BASE_URL}/api/list`);
|
||||||
return (await response.json()) as ExtendedProviderStatus[];
|
return (await response.json()) as ExtendedProviderStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchAlertsViaHttp(): Promise<Alert[]> {
|
async function fetchAlertsViaHttp(): Promise<Alert[]> {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/alerts`);
|
const response = await fetch(`${PUBLIC_REGISTRY_API_BASE_URL}/api/alerts`);
|
||||||
return (await response.json()) as Alert[];
|
return (await response.json()) as Alert[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +35,7 @@ export async function submitFeedbackViaHttp(
|
||||||
feedbackId: string;
|
feedbackId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(`${API_BASE_URL}/api/submit-feedback`, {
|
const response = await fetch(`${PUBLIC_REGISTRY_API_BASE_URL}/api/submit-feedback`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -49,39 +53,29 @@ export async function submitFeedbackViaHttp(
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchCurrencyPrice(currency: string, fiatCurrency: FiatCurrency): Promise<number> {
|
async function fetchCurrencyPrice(currency: string, fiatCurrency: FiatCurrency): Promise<number> {
|
||||||
try {
|
const response = await fetch(
|
||||||
const response = await fetch(
|
`https://api.coingecko.com/api/v3/simple/price?ids=${currency}&vs_currencies=${fiatCurrency.toLowerCase()}`,
|
||||||
`https://api.coingecko.com/api/v3/simple/price?ids=${currency}&vs_currencies=${fiatCurrency.toLowerCase()}`,
|
);
|
||||||
);
|
const data = await response.json();
|
||||||
const data = await response.json();
|
return data[currency][fiatCurrency.toLowerCase()];
|
||||||
return data[currency][fiatCurrency.toLowerCase()];
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error fetching ${currency} price:`, error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchXmrBtcRate(): Promise<number> {
|
async function fetchXmrBtcRate(): Promise<number> {
|
||||||
try {
|
const response = await fetch('https://api.kraken.com/0/public/Ticker?pair=XMRXBT');
|
||||||
const response = await fetch('https://api.kraken.com/0/public/Ticker?pair=XMRXBT');
|
const data = await response.json();
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.error && data.error.length > 0) {
|
|
||||||
throw new Error(`Kraken API error: ${data.error[0]}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = data.result.XXMRXXBT;
|
if (data.error && data.error.length > 0) {
|
||||||
const lastTradePrice = parseFloat(result.c[0]);
|
throw new Error(`Kraken API error: ${data.error[0]}`);
|
||||||
|
|
||||||
return lastTradePrice;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching XMR/BTC rate from Kraken:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = data.result.XXMRXXBT;
|
||||||
|
const lastTradePrice = parseFloat(result.c[0]);
|
||||||
|
|
||||||
|
return lastTradePrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function fetchBtcPrice(fiatCurrency: FiatCurrency): Promise<number> {
|
function fetchBtcPrice(fiatCurrency: FiatCurrency): Promise<number> {
|
||||||
return fetchCurrencyPrice("bitcoin", fiatCurrency);
|
return fetchCurrencyPrice("bitcoin", fiatCurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,21 +89,42 @@ async function fetchXmrPrice(fiatCurrency: FiatCurrency): Promise<number> {
|
||||||
*/
|
*/
|
||||||
export async function updateRates(): Promise<void> {
|
export async function updateRates(): Promise<void> {
|
||||||
const settings = store.getState().settings;
|
const settings = store.getState().settings;
|
||||||
if (!settings.fetchFiatPrices)
|
if (!settings.fetchFiatPrices)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const xmrBtcRate = await fetchXmrBtcRate();
|
const xmrBtcRate = await fetchXmrBtcRate();
|
||||||
store.dispatch(setXmrBtcRate(xmrBtcRate));
|
store.dispatch(setXmrBtcRate(xmrBtcRate));
|
||||||
|
|
||||||
const btcPrice = await fetchBtcPrice(settings.fiatCurrency);
|
const btcPrice = await fetchBtcPrice(settings.fiatCurrency);
|
||||||
store.dispatch(setBtcPrice(btcPrice));
|
store.dispatch(setBtcPrice(btcPrice));
|
||||||
|
|
||||||
const xmrPrice = await fetchXmrPrice(settings.fiatCurrency);
|
const xmrPrice = await fetchXmrPrice(settings.fiatCurrency);
|
||||||
store.dispatch(setXmrPrice(xmrPrice));
|
store.dispatch(setXmrPrice(xmrPrice));
|
||||||
|
|
||||||
console.log(`Fetched rates for ${settings.fiatCurrency}`);
|
logger.info(`Fetched rates for ${settings.fiatCurrency}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching rates:", error);
|
logger.error(error, "Error fetching rates");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update public registry
|
||||||
|
*/
|
||||||
|
export async function updatePublicRegistry(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const providers = await fetchProvidersViaHttp();
|
||||||
|
store.dispatch(setRegistryProviders(providers));
|
||||||
|
} catch (error) {
|
||||||
|
store.dispatch(registryConnectionFailed());
|
||||||
|
logger.error(error, "Error fetching providers");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const alerts = await fetchAlertsViaHttp();
|
||||||
|
store.dispatch(setAlerts(alerts));
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error, "Error fetching alerts");
|
||||||
|
}
|
||||||
|
}
|
87
src-gui/src/renderer/background.ts
Normal file
87
src-gui/src/renderer/background.ts
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import { listen } from "@tauri-apps/api/event";
|
||||||
|
import { TauriSwapProgressEventWrapper, TauriContextStatusEvent, TauriLogEvent, BalanceResponse, TauriDatabaseStateEvent, TauriTimelockChangeEvent, TauriBackgroundRefundEvent } from "models/tauriModel";
|
||||||
|
import { contextStatusEventReceived, receivedCliLog, rpcSetBalance, timelockChangeEventReceived, rpcSetBackgroundRefundState } from "store/features/rpcSlice";
|
||||||
|
import { swapProgressEventReceived } from "store/features/swapSlice";
|
||||||
|
import logger from "utils/logger";
|
||||||
|
import { updatePublicRegistry, updateRates } from "./api";
|
||||||
|
import { checkContextAvailability, getSwapInfo, initializeContext, updateAllNodeStatuses } from "./rpc";
|
||||||
|
import { store } from "./store/storeRenderer";
|
||||||
|
|
||||||
|
// Update the public registry every 5 minutes
|
||||||
|
const PROVIDER_UPDATE_INTERVAL = 5 * 60 * 1_000;
|
||||||
|
|
||||||
|
// Update node statuses every 2 minutes
|
||||||
|
const STATUS_UPDATE_INTERVAL = 2 * 60 * 1_000;
|
||||||
|
|
||||||
|
// Update the exchange rate every 5 minutes
|
||||||
|
const UPDATE_RATE_INTERVAL = 5 * 60 * 1_000;
|
||||||
|
|
||||||
|
function setIntervalImmediate(callback: () => void, interval: number): void {
|
||||||
|
callback();
|
||||||
|
setInterval(callback, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setupBackgroundTasks(): Promise<void> {
|
||||||
|
// // Setup periodic fetch tasks
|
||||||
|
setIntervalImmediate(updatePublicRegistry, PROVIDER_UPDATE_INTERVAL);
|
||||||
|
setIntervalImmediate(updateAllNodeStatuses, STATUS_UPDATE_INTERVAL);
|
||||||
|
setIntervalImmediate(updateRates, UPDATE_RATE_INTERVAL);
|
||||||
|
|
||||||
|
// // Setup Tauri event listeners
|
||||||
|
|
||||||
|
// Check if the context is already available. This is to prevent unnecessary re-initialization
|
||||||
|
if (await checkContextAvailability()) {
|
||||||
|
store.dispatch(contextStatusEventReceived({ type: "Available" }));
|
||||||
|
} else {
|
||||||
|
// Warning: If we reload the page while the Context is being initialized, this function will throw an error
|
||||||
|
initializeContext().catch((e) => {
|
||||||
|
logger.error(e, "Failed to initialize context on page load. This might be because we reloaded the page while the context was being initialized");
|
||||||
|
// Wait a short time before retrying
|
||||||
|
setTimeout(() => {
|
||||||
|
initializeContext().catch((e) => {
|
||||||
|
logger.error(e, "Failed to initialize context even after retry");
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
listen<TauriSwapProgressEventWrapper>("swap-progress-update", (event) => {
|
||||||
|
logger.info("Received swap progress event", event.payload);
|
||||||
|
store.dispatch(swapProgressEventReceived(event.payload));
|
||||||
|
});
|
||||||
|
|
||||||
|
listen<TauriContextStatusEvent>("context-init-progress-update", (event) => {
|
||||||
|
logger.info("Received context init progress event", event.payload);
|
||||||
|
store.dispatch(contextStatusEventReceived(event.payload));
|
||||||
|
});
|
||||||
|
|
||||||
|
listen<TauriLogEvent>("cli-log-emitted", (event) => {
|
||||||
|
logger.info("Received cli log event", event.payload);
|
||||||
|
store.dispatch(receivedCliLog(event.payload));
|
||||||
|
});
|
||||||
|
|
||||||
|
listen<BalanceResponse>("balance-change", (event) => {
|
||||||
|
logger.info("Received balance change event", event.payload);
|
||||||
|
store.dispatch(rpcSetBalance(event.payload.balance));
|
||||||
|
});
|
||||||
|
|
||||||
|
listen<TauriDatabaseStateEvent>("swap-database-state-update", (event) => {
|
||||||
|
logger.info("Received swap database state update event", event.payload);
|
||||||
|
getSwapInfo(event.payload.swap_id);
|
||||||
|
|
||||||
|
// This is ugly but it's the best we can do for now
|
||||||
|
// Sometimes we are too quick to fetch the swap info and the new state is not yet reflected
|
||||||
|
// in the database. So we wait a bit before fetching the new state
|
||||||
|
setTimeout(() => getSwapInfo(event.payload.swap_id), 3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
listen<TauriTimelockChangeEvent>('timelock-change', (event) => {
|
||||||
|
logger.info('Received timelock change event', event.payload);
|
||||||
|
store.dispatch(timelockChangeEventReceived(event.payload));
|
||||||
|
})
|
||||||
|
|
||||||
|
listen<TauriBackgroundRefundEvent>('background-refund', (event) => {
|
||||||
|
logger.info('Received background refund event', event.payload);
|
||||||
|
store.dispatch(rpcSetBackgroundRefundState(event.payload));
|
||||||
|
})
|
||||||
|
}
|
|
@ -11,14 +11,8 @@ import GlobalSnackbarProvider from "./snackbar/GlobalSnackbarProvider";
|
||||||
import UpdaterDialog from "./modal/updater/UpdaterDialog";
|
import UpdaterDialog from "./modal/updater/UpdaterDialog";
|
||||||
import { useSettings } from "store/hooks";
|
import { useSettings } from "store/hooks";
|
||||||
import { themes } from "./theme";
|
import { themes } from "./theme";
|
||||||
import { initEventListeners, updateAllNodeStatuses } from "renderer/rpc";
|
|
||||||
import { fetchAlertsViaHttp, fetchProvidersViaHttp, updateRates } from "renderer/api";
|
|
||||||
import { store } from "renderer/store/storeRenderer";
|
|
||||||
import logger from "utils/logger";
|
|
||||||
import { setAlerts } from "store/features/alertsSlice";
|
|
||||||
import { setRegistryProviders } from "store/features/providersSlice";
|
|
||||||
import { registryConnectionFailed } from "store/features/providersSlice";
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { setupBackgroundTasks } from "renderer/background";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
innerContent: {
|
innerContent: {
|
||||||
|
@ -31,8 +25,7 @@ const useStyles = makeStyles((theme) => ({
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchInitialData();
|
setupBackgroundTasks();
|
||||||
initEventListeners();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const theme = useSettings((s) => s.theme);
|
const theme = useSettings((s) => s.theme);
|
||||||
|
@ -65,48 +58,4 @@ function InnerContent() {
|
||||||
</Routes>
|
</Routes>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchInitialData() {
|
|
||||||
try {
|
|
||||||
const providerList = await fetchProvidersViaHttp();
|
|
||||||
store.dispatch(setRegistryProviders(providerList));
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
{ providerList },
|
|
||||||
"Fetched providers via UnstoppableSwap HTTP API",
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
store.dispatch(registryConnectionFailed());
|
|
||||||
logger.error(e, "Failed to fetch providers via UnstoppableSwap HTTP API");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await updateAllNodeStatuses()
|
|
||||||
} catch (e) {
|
|
||||||
logger.error(e, "Failed to update node statuses")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update node statuses every 2 minutes
|
|
||||||
const STATUS_UPDATE_INTERVAL = 2 * 60 * 1_000;
|
|
||||||
setInterval(updateAllNodeStatuses, STATUS_UPDATE_INTERVAL);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const alerts = await fetchAlertsViaHttp();
|
|
||||||
store.dispatch(setAlerts(alerts));
|
|
||||||
logger.info({ alerts }, "Fetched alerts via UnstoppableSwap HTTP API");
|
|
||||||
} catch (e) {
|
|
||||||
logger.error(e, "Failed to fetch alerts via UnstoppableSwap HTTP API");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await updateRates();
|
|
||||||
logger.info("Fetched XMR/BTC rate");
|
|
||||||
} catch (e) {
|
|
||||||
logger.error(e, "Error retrieving XMR/BTC rate");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the rates every 5 minutes (to respect the coingecko rate limit)
|
|
||||||
const RATE_UPDATE_INTERVAL = 5 * 60 * 1_000;
|
|
||||||
setInterval(updateRates, RATE_UPDATE_INTERVAL);
|
|
||||||
}
|
|
|
@ -24,13 +24,14 @@ import { submitFeedbackViaHttp } from "../../../api";
|
||||||
import LoadingButton from "../../other/LoadingButton";
|
import LoadingButton from "../../other/LoadingButton";
|
||||||
import { PiconeroAmount } from "../../other/Units";
|
import { PiconeroAmount } from "../../other/Units";
|
||||||
import { getLogsOfSwap } from "renderer/rpc";
|
import { getLogsOfSwap } from "renderer/rpc";
|
||||||
|
import logger from "utils/logger";
|
||||||
|
|
||||||
async function submitFeedback(body: string, swapId: string | number, submitDaemonLogs: boolean) {
|
async function submitFeedback(body: string, swapId: string | number, submitDaemonLogs: boolean) {
|
||||||
let attachedBody = "";
|
let attachedBody = "";
|
||||||
|
|
||||||
if (swapId !== 0 && typeof swapId === "string") {
|
if (swapId !== 0 && typeof swapId === "string") {
|
||||||
const swapInfo = store.getState().rpc.state.swapInfos[swapId];
|
const swapInfo = store.getState().rpc.state.swapInfos[swapId];
|
||||||
|
|
||||||
if (swapInfo === undefined) {
|
if (swapInfo === undefined) {
|
||||||
throw new Error(`Swap with id ${swapId} not found`);
|
throw new Error(`Swap with id ${swapId} not found`);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +180,7 @@ export default function FeedbackDialog({
|
||||||
variant: "success",
|
variant: "success",
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to submit feedback: ${e}`);
|
logger.error(`Failed to submit feedback: ${e}`);
|
||||||
enqueueSnackbar(`Failed to submit feedback (${e})`, {
|
enqueueSnackbar(`Failed to submit feedback (${e})`, {
|
||||||
variant: "error",
|
variant: "error",
|
||||||
});
|
});
|
||||||
|
|
|
@ -74,7 +74,7 @@ export default function ProviderInfo({
|
||||||
Maximum swap amount: <SatsAmount amount={provider.maxSwapAmount} />
|
Maximum swap amount: <SatsAmount amount={provider.maxSwapAmount} />
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box className={classes.chipsOuter}>
|
<Box className={classes.chipsOuter}>
|
||||||
<Chip label={provider.testnet ? "Testnet" : "Mainnet"} />
|
{provider.testnet && <Chip label="Testnet" />}
|
||||||
{provider.uptime && (
|
{provider.uptime && (
|
||||||
<Tooltip title="A high uptime (>90%) indicates reliability. Providers with very low uptime may be unreliable and cause swaps to take longer to complete or fail entirely.">
|
<Tooltip title="A high uptime (>90%) indicates reliability. Providers with very low uptime may be unreliable and cause swaps to take longer to complete or fail entirely.">
|
||||||
<Chip label={`${Math.round(provider.uptime * 100)}% uptime`} />
|
<Chip label={`${Math.round(provider.uptime * 100)}% uptime`} />
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Step, StepLabel, Stepper, Typography } from "@material-ui/core";
|
import { Step, StepLabel, Stepper, Typography } from "@material-ui/core";
|
||||||
import { SwapState } from "models/storeModel";
|
import { SwapState } from "models/storeModel";
|
||||||
import { useAppSelector } from "store/hooks";
|
import { useAppSelector } from "store/hooks";
|
||||||
|
import logger from "utils/logger";
|
||||||
|
|
||||||
export enum PathType {
|
export enum PathType {
|
||||||
HAPPY_PATH = "happy path",
|
HAPPY_PATH = "happy path",
|
||||||
|
@ -18,7 +19,7 @@ type PathStep = [type: PathType, step: number, isError: boolean];
|
||||||
function getActiveStep(state: SwapState | null): PathStep | null {
|
function getActiveStep(state: SwapState | null): PathStep | null {
|
||||||
// In case we cannot infer a correct step from the state
|
// In case we cannot infer a correct step from the state
|
||||||
function fallbackStep(reason: string) {
|
function fallbackStep(reason: string) {
|
||||||
console.error(
|
logger.error(
|
||||||
`Unable to choose correct stepper type (reason: ${reason}, state: ${JSON.stringify(state)}`,
|
`Unable to choose correct stepper type (reason: ${reason}, state: ${JSON.stringify(state)}`,
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -59,71 +59,11 @@ export async function fetchSellersAtPresetRendezvousPoints() {
|
||||||
const response = await listSellersAtRendezvousPoint(rendezvousPoint);
|
const response = await listSellersAtRendezvousPoint(rendezvousPoint);
|
||||||
store.dispatch(discoveredProvidersByRendezvous(response.sellers));
|
store.dispatch(discoveredProvidersByRendezvous(response.sellers));
|
||||||
|
|
||||||
console.log(`Discovered ${response.sellers.length} sellers at rendezvous point ${rendezvousPoint} during startup fetch`);
|
logger.log(`Discovered ${response.sellers.length} sellers at rendezvous point ${rendezvousPoint} during startup fetch`);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initEventListeners() {
|
|
||||||
// This operation is in-expensive
|
|
||||||
// We do this in case we miss the context init progress event because the frontend took too long to load
|
|
||||||
// TOOD: Replace this with a more reliable mechanism (such as an event replay mechanism)
|
|
||||||
if (await checkContextAvailability()) {
|
|
||||||
store.dispatch(contextStatusEventReceived({ type: "Available" }));
|
|
||||||
} else {
|
|
||||||
// Warning: If we reload the page while the Context is being initialized, this function will throw an error
|
|
||||||
initializeContext().catch((e) => {
|
|
||||||
logger.error(e, "Failed to initialize context on page load. This might be because we reloaded the page while the context was being initialized");
|
|
||||||
// Wait a short time before retrying
|
|
||||||
setTimeout(() => {
|
|
||||||
initializeContext().catch((e) => {
|
|
||||||
logger.error(e, "Failed to initialize context even after retry");
|
|
||||||
});
|
|
||||||
}, 2000); // 2 second delay
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
listen<TauriSwapProgressEventWrapper>("swap-progress-update", (event) => {
|
|
||||||
console.log("Received swap progress event", event.payload);
|
|
||||||
store.dispatch(swapProgressEventReceived(event.payload));
|
|
||||||
});
|
|
||||||
|
|
||||||
listen<TauriContextStatusEvent>("context-init-progress-update", (event) => {
|
|
||||||
console.log("Received context init progress event", event.payload);
|
|
||||||
store.dispatch(contextStatusEventReceived(event.payload));
|
|
||||||
});
|
|
||||||
|
|
||||||
listen<TauriLogEvent>("cli-log-emitted", (event) => {
|
|
||||||
console.log("Received cli log event", event.payload);
|
|
||||||
store.dispatch(receivedCliLog(event.payload));
|
|
||||||
});
|
|
||||||
|
|
||||||
listen<BalanceResponse>("balance-change", (event) => {
|
|
||||||
console.log("Received balance change event", event.payload);
|
|
||||||
store.dispatch(rpcSetBalance(event.payload.balance));
|
|
||||||
});
|
|
||||||
|
|
||||||
listen<TauriDatabaseStateEvent>("swap-database-state-update", (event) => {
|
|
||||||
console.log("Received swap database state update event", event.payload);
|
|
||||||
getSwapInfo(event.payload.swap_id);
|
|
||||||
|
|
||||||
// This is ugly but it's the best we can do for now
|
|
||||||
// Sometimes we are too quick to fetch the swap info and the new state is not yet reflected
|
|
||||||
// in the database. So we wait a bit before fetching the new state
|
|
||||||
setTimeout(() => getSwapInfo(event.payload.swap_id), 3000);
|
|
||||||
});
|
|
||||||
|
|
||||||
listen<TauriTimelockChangeEvent>('timelock-change', (event) => {
|
|
||||||
console.log('Received timelock change event', event.payload);
|
|
||||||
store.dispatch(timelockChangeEventReceived(event.payload));
|
|
||||||
})
|
|
||||||
|
|
||||||
listen<TauriBackgroundRefundEvent>('background-refund', (event) => {
|
|
||||||
console.log('Received background refund event', event.payload);
|
|
||||||
store.dispatch(rpcSetBackgroundRefundState(event.payload));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function invoke<ARGS, RESPONSE>(
|
async function invoke<ARGS, RESPONSE>(
|
||||||
command: string,
|
command: string,
|
||||||
args: ARGS,
|
args: ARGS,
|
||||||
|
@ -279,7 +219,7 @@ export async function initializeContext() {
|
||||||
monero_node_url: moneroNode,
|
monero_node_url: moneroNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("Initializing context with settings", tauriSettings);
|
logger.info("Initializing context with settings", tauriSettings);
|
||||||
|
|
||||||
await invokeUnsafe<void>("initialize_context", {
|
await invokeUnsafe<void>("initialize_context", {
|
||||||
settings: tauriSettings,
|
settings: tauriSettings,
|
||||||
|
|
|
@ -119,7 +119,6 @@ const alertsSlice = createSlice({
|
||||||
slice.fetchFiatPrices = action.payload;
|
slice.fetchFiatPrices = action.payload;
|
||||||
},
|
},
|
||||||
setFiatCurrency(slice, action: PayloadAction<FiatCurrency>) {
|
setFiatCurrency(slice, action: PayloadAction<FiatCurrency>) {
|
||||||
console.log("setFiatCurrency", action.payload);
|
|
||||||
slice.fiatCurrency = action.payload;
|
slice.fiatCurrency = action.payload;
|
||||||
},
|
},
|
||||||
addNode(slice, action: PayloadAction<{ network: Network, type: Blockchain, node: string }>) {
|
addNode(slice, action: PayloadAction<{ network: Network, type: Blockchain, node: string }>) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function createMainListeners() {
|
||||||
actionCreator: setFiatCurrency,
|
actionCreator: setFiatCurrency,
|
||||||
effect: async () => {
|
effect: async () => {
|
||||||
if (store.getState().settings.fetchFiatPrices) {
|
if (store.getState().settings.fetchFiatPrices) {
|
||||||
console.log("Fiat currency changed, updating rates...");
|
logger.info("Fiat currency changed, updating rates...");
|
||||||
await updateRates();
|
await updateRates();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -46,7 +46,7 @@ export function createMainListeners() {
|
||||||
actionCreator: setFetchFiatPrices,
|
actionCreator: setFetchFiatPrices,
|
||||||
effect: async (action) => {
|
effect: async (action) => {
|
||||||
if (action.payload === true) {
|
if (action.payload === true) {
|
||||||
console.log("Activated fetching fiat prices, updating rates...");
|
logger.info("Activated fetching fiat prices, updating rates...");
|
||||||
await updateRates();
|
await updateRates();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue