mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-05-03 07:14:51 -04:00
feat(gui): Display provider spread to user (#124)
This commit is contained in:
parent
1acb597a34
commit
584cc41411
4 changed files with 60 additions and 3 deletions
|
@ -58,10 +58,30 @@ async function fetchCurrencyUsdPrice(currency: string): Promise<number> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchXmrBtcRate(): Promise<number> {
|
||||||
|
try {
|
||||||
|
const response = await fetch('https://api.kraken.com/0/public/Ticker?pair=XMRXBT');
|
||||||
|
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;
|
||||||
|
const lastTradePrice = parseFloat(result.c[0]);
|
||||||
|
|
||||||
|
return lastTradePrice;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching XMR/BTC rate from Kraken:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function fetchBtcPrice(): Promise<number> {
|
export async function fetchBtcPrice(): Promise<number> {
|
||||||
return fetchCurrencyUsdPrice("bitcoin");
|
return fetchCurrencyUsdPrice("bitcoin");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchXmrPrice(): Promise<number> {
|
export async function fetchXmrPrice(): Promise<number> {
|
||||||
return fetchCurrencyUsdPrice("monero");
|
return fetchCurrencyUsdPrice("monero");
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import { satsToBtc, secondsToDays } from "utils/conversionUtils";
|
import { satsToBtc, secondsToDays } from "utils/conversionUtils";
|
||||||
import { isProviderOutdated } from 'utils/multiAddrUtils';
|
import { isProviderOutdated } from 'utils/multiAddrUtils';
|
||||||
import WarningIcon from '@material-ui/icons/Warning';
|
import WarningIcon from '@material-ui/icons/Warning';
|
||||||
|
import { useAppSelector } from "store/hooks";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
content: {
|
content: {
|
||||||
|
@ -25,6 +26,24 @@ const useStyles = makeStyles((theme) => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function ProviderSpreadChip({ provider }: { provider: ExtendedProviderStatus }) {
|
||||||
|
const xmrBtcPrice = useAppSelector(s => s.rates?.xmrBtcRate);
|
||||||
|
|
||||||
|
if (xmrBtcPrice === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const providerPrice = satsToBtc(provider.price);
|
||||||
|
const spread = ((providerPrice - xmrBtcPrice) / xmrBtcPrice) * 100;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title="The spread is the difference between the provider's exchange rate and the market rate. A high spread indicates that the provider is charging more than the market rate.">
|
||||||
|
<Chip label={`Spread: ${spread.toFixed(2)} %`} />
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export default function ProviderInfo({
|
export default function ProviderInfo({
|
||||||
provider,
|
provider,
|
||||||
}: {
|
}: {
|
||||||
|
@ -78,6 +97,7 @@ export default function ProviderInfo({
|
||||||
<Chip label="Outdated" icon={<WarningIcon />} color="primary" />
|
<Chip label="Outdated" icon={<WarningIcon />} color="primary" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
<ProviderSpreadChip provider={provider} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,12 +6,13 @@ import {
|
||||||
registryConnectionFailed,
|
registryConnectionFailed,
|
||||||
setRegistryProviders,
|
setRegistryProviders,
|
||||||
} from "store/features/providersSlice";
|
} from "store/features/providersSlice";
|
||||||
import { setBtcPrice, setXmrPrice } from "store/features/ratesSlice";
|
import { setBtcPrice, setXmrBtcRate, setXmrPrice } from "store/features/ratesSlice";
|
||||||
import logger from "../utils/logger";
|
import logger from "../utils/logger";
|
||||||
import {
|
import {
|
||||||
fetchAlertsViaHttp,
|
fetchAlertsViaHttp,
|
||||||
fetchBtcPrice,
|
fetchBtcPrice,
|
||||||
fetchProvidersViaHttp,
|
fetchProvidersViaHttp,
|
||||||
|
fetchXmrBtcRate,
|
||||||
fetchXmrPrice,
|
fetchXmrPrice,
|
||||||
} from "./api";
|
} from "./api";
|
||||||
import App from "./components/App";
|
import App from "./components/App";
|
||||||
|
@ -64,6 +65,14 @@ async function fetchInitialData() {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e, "Error retrieving fiat prices");
|
logger.error(e, "Error retrieving fiat prices");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const xmrBtcRate = await fetchXmrBtcRate();
|
||||||
|
store.dispatch(setXmrBtcRate(xmrBtcRate));
|
||||||
|
logger.info({ xmrBtcRate }, "Fetched XMR/BTC rate");
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(e, "Error retrieving XMR/BTC rate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchInitialData();
|
fetchInitialData();
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
export interface RatesState {
|
export interface RatesState {
|
||||||
|
// USD price of 1 BTC
|
||||||
btcPrice: number | null;
|
btcPrice: number | null;
|
||||||
|
// USD price of 1 XMR
|
||||||
xmrPrice: number | null;
|
xmrPrice: number | null;
|
||||||
|
// XMR/BTC exchange rate
|
||||||
|
xmrBtcRate: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: RatesState = {
|
const initialState: RatesState = {
|
||||||
btcPrice: null,
|
btcPrice: null,
|
||||||
xmrPrice: null,
|
xmrPrice: null,
|
||||||
|
xmrBtcRate: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ratesSlice = createSlice({
|
const ratesSlice = createSlice({
|
||||||
|
@ -20,9 +25,12 @@ const ratesSlice = createSlice({
|
||||||
setXmrPrice: (state, action: PayloadAction<number>) => {
|
setXmrPrice: (state, action: PayloadAction<number>) => {
|
||||||
state.xmrPrice = action.payload;
|
state.xmrPrice = action.payload;
|
||||||
},
|
},
|
||||||
|
setXmrBtcRate: (state, action: PayloadAction<number>) => {
|
||||||
|
state.xmrBtcRate = action.payload;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setBtcPrice, setXmrPrice } = ratesSlice.actions;
|
export const { setBtcPrice, setXmrPrice, setXmrBtcRate } = ratesSlice.actions;
|
||||||
|
|
||||||
export default ratesSlice.reducer;
|
export default ratesSlice.reducer;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue