mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 19:06:26 +00:00
WIP
This commit is contained in:
parent
49c2469bb1
commit
560def2966
@ -1,5 +1,5 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { Button, Grid, List, ListItem, Paper, TextField, Typography } from '@mui/material';
|
||||
import { Box, Button, Grid, List, ListItem, Paper, TextField, Typography } from '@mui/material';
|
||||
import SettingsForm from '../../components/SettingsForm';
|
||||
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
|
||||
import FederationTable from '../../components/FederationTable';
|
||||
@ -49,52 +49,60 @@ const SettingsPage = (): JSX.Element => {
|
||||
}}
|
||||
>
|
||||
<Grid container>
|
||||
<Grid item>
|
||||
<Grid item xs={12}>
|
||||
<SettingsForm />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid item xs={12}>
|
||||
<FederationTable maxHeight={18} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid item xs={12}>
|
||||
<Typography align='center' component='h2' variant='subtitle2' color='secondary'>
|
||||
{error}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<List>
|
||||
<ListItem>
|
||||
<TextField
|
||||
id='outlined-basic'
|
||||
label={t('Alias')}
|
||||
variant='outlined'
|
||||
size='small'
|
||||
value={newAlias}
|
||||
onChange={(e) => {
|
||||
setNewAlias(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
id='outlined-basic'
|
||||
label={t('URL')}
|
||||
variant='outlined'
|
||||
size='small'
|
||||
value={newUrl}
|
||||
onChange={(e) => {
|
||||
setNewUrl(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
sx={{ maxHeight: 38 }}
|
||||
disabled={false}
|
||||
onClick={addCoordinator}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
size='small'
|
||||
type='submit'
|
||||
>
|
||||
{t('Add')}
|
||||
</Button>
|
||||
</ListItem>
|
||||
</List>
|
||||
<Grid item xs={12}>
|
||||
<List>
|
||||
<ListItem>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<TextField
|
||||
id='outlined-basic'
|
||||
label={t('Alias')}
|
||||
variant='outlined'
|
||||
size='small'
|
||||
value={newAlias}
|
||||
onChange={(e) => {
|
||||
setNewAlias(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<TextField
|
||||
id='outlined-basic'
|
||||
label={t('URL')}
|
||||
variant='outlined'
|
||||
size='small'
|
||||
value={newUrl}
|
||||
onChange={(e) => {
|
||||
setNewUrl(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Button
|
||||
sx={{ maxHeight: 38 }}
|
||||
disabled={false}
|
||||
onClick={addCoordinator}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
size='small'
|
||||
type='submit'
|
||||
>
|
||||
{t('Add')}
|
||||
</Button>
|
||||
</Box>
|
||||
</ListItem>
|
||||
</List>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
);
|
||||
|
@ -938,8 +938,11 @@ const BookTable = ({
|
||||
setPaymentMethods,
|
||||
},
|
||||
loadingOverlay: {
|
||||
variant: loadingPercentage === 0 ? 'indeterminate' : 'determinate',
|
||||
value: loadingPercentage,
|
||||
variant:
|
||||
federation.exchange.loadingCache || loadingPercentage === 0
|
||||
? 'indeterminate'
|
||||
: 'determinate',
|
||||
value: federation.exchange.loadingCache ? 1 : loadingPercentage,
|
||||
},
|
||||
}}
|
||||
paginationModel={paginationModel}
|
||||
|
@ -68,13 +68,22 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
useEffect(() => {
|
||||
if (Object.values(federation.book).length > 0) {
|
||||
const enriched = Object.values(federation.book).map((order) => {
|
||||
// We need to transform all currencies to the same base (ex. USD), we don't have the exchange rate
|
||||
// for EUR -> USD, but we know the rate of both to BTC, so we get advantage of it and apply a
|
||||
// simple rule of three
|
||||
if (order.coordinatorShortAlias != null) {
|
||||
if (order.coordinatorShortAlias != null && order.currency) {
|
||||
const limits = federation.getCoordinator(order.coordinatorShortAlias).limits;
|
||||
const price = limits[currencyCode] ? limits[currencyCode].price : 0;
|
||||
order.base_amount = (order.price * price) / price;
|
||||
|
||||
const originalPrice =
|
||||
(limits[order.currency].price ?? 0) * (1 + parseFloat(order.premium) / 100);
|
||||
const currencyPrice =
|
||||
(limits[currencyCode].price ?? 0) * (1 + parseFloat(order.premium) / 100);
|
||||
|
||||
const originalAmount =
|
||||
order.has_range && order.max_amount
|
||||
? parseFloat(order.max_amount)
|
||||
: parseFloat(order.amount);
|
||||
const currencyAmount = (currencyPrice * originalAmount) / originalPrice;
|
||||
|
||||
order.base_price = currencyPrice;
|
||||
order.satoshis_now = (100000000 * currencyAmount) / currencyPrice;
|
||||
}
|
||||
return order;
|
||||
});
|
||||
@ -89,8 +98,8 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
}, [enrichedOrders, xRange]);
|
||||
|
||||
useEffect(() => {
|
||||
if (xType === 'base_amount') {
|
||||
const prices: number[] = enrichedOrders.map((order) => order?.base_amount ?? 0);
|
||||
if (xType === 'base_price') {
|
||||
const prices: number[] = enrichedOrders.map((order) => order?.base_price ?? 0);
|
||||
|
||||
const medianValue = ~~matchMedian(prices);
|
||||
const maxValue = prices.sort((a, b) => b - a).slice(0, 1)[0] ?? 1500;
|
||||
@ -114,9 +123,9 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
|
||||
const generateSeries: () => void = () => {
|
||||
const sortedOrders: PublicOrder[] =
|
||||
xType === 'base_amount'
|
||||
xType === 'base_price'
|
||||
? enrichedOrders.sort(
|
||||
(order1, order2) => (order1?.base_amount ?? 0) - (order2?.base_amount ?? 0),
|
||||
(order1, order2) => (order1?.base_price ?? 0) - (order2?.base_price ?? 0),
|
||||
)
|
||||
: enrichedOrders.sort((order1, order2) => order1.premium - order2.premium);
|
||||
|
||||
@ -152,16 +161,17 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
let serie: Datum[] = [];
|
||||
orders.forEach((order) => {
|
||||
const lastSumOrders = sumOrders;
|
||||
|
||||
sumOrders += (order.satoshis_now ?? 0) / 100000000;
|
||||
const datum: Datum[] = [
|
||||
{
|
||||
// Vertical Line
|
||||
x: xType === 'base_amount' ? order.base_amount : order.premium,
|
||||
x: xType === 'base_price' ? order.base_price : order.premium,
|
||||
y: lastSumOrders,
|
||||
},
|
||||
{
|
||||
// PublicOrder Point
|
||||
x: xType === 'base_amount' ? order.base_amount : order.premium,
|
||||
x: xType === 'base_price' ? order.base_price : order.premium,
|
||||
y: sumOrders,
|
||||
order,
|
||||
},
|
||||
@ -226,7 +236,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
};
|
||||
|
||||
const formatAxisX = (value: number): string => {
|
||||
if (xType === 'base_amount') {
|
||||
if (xType === 'base_price') {
|
||||
return value.toString();
|
||||
}
|
||||
return `${value}%`;
|
||||
@ -285,7 +295,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
{t('Premium')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
<MenuItem value={'base_amount'}>
|
||||
<MenuItem value={'base_price'}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
{t('Price')}
|
||||
</div>
|
||||
@ -306,7 +316,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Box justifyContent='center'>
|
||||
{xType === 'base_amount'
|
||||
{xType === 'base_price'
|
||||
? `${center} ${String(currencyDict[currencyCode])}`
|
||||
: `${String(center.toPrecision(3))}%`}
|
||||
</Box>
|
||||
@ -339,14 +349,14 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
axisBottom={{
|
||||
tickSize: 5,
|
||||
tickRotation:
|
||||
xType === 'base_amount' ? (width < 40 ? 45 : 0) : width < 25 ? 45 : 0,
|
||||
xType === 'base_price' ? (width < 40 ? 45 : 0) : width < 25 ? 45 : 0,
|
||||
format: formatAxisX,
|
||||
}}
|
||||
margin={{
|
||||
left: 4.64 * em,
|
||||
right: 0.714 * em,
|
||||
bottom:
|
||||
xType === 'base_amount'
|
||||
xType === 'base_price'
|
||||
? width < 40
|
||||
? 2.7 * em
|
||||
: 1.78 * em
|
||||
|
@ -23,21 +23,23 @@ import {
|
||||
DarkMode,
|
||||
SettingsOverscan,
|
||||
Link,
|
||||
AccountBalance,
|
||||
AttachMoney,
|
||||
QrCode,
|
||||
SettingsInputAntenna,
|
||||
Dns,
|
||||
} from '@mui/icons-material';
|
||||
import { systemClient } from '../../services/System';
|
||||
import { TorIcon } from '../Icons';
|
||||
import SwapCalls from '@mui/icons-material/SwapCalls';
|
||||
import { apiClient } from '../../services/api';
|
||||
import Nostr from '../Icons/Nostr';
|
||||
|
||||
interface SettingsFormProps {
|
||||
dense?: boolean;
|
||||
}
|
||||
|
||||
const SettingsForm = ({ dense = false }: SettingsFormProps): JSX.Element => {
|
||||
const { fav, setFav, settings, setSettings, client } = useContext<UseAppStoreType>(AppContext);
|
||||
const { settings, setSettings, client } = useContext<UseAppStoreType>(AppContext);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const fontSizes = [
|
||||
@ -49,8 +51,8 @@ const SettingsForm = ({ dense = false }: SettingsFormProps): JSX.Element => {
|
||||
];
|
||||
|
||||
return (
|
||||
<Grid container spacing={1}>
|
||||
<Grid item>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<List dense={dense}>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
@ -196,22 +198,22 @@ const SettingsForm = ({ dense = false }: SettingsFormProps): JSX.Element => {
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<AccountBalance />
|
||||
<SettingsInputAntenna />
|
||||
</ListItemIcon>
|
||||
<ToggleButtonGroup
|
||||
sx={{ width: '100%' }}
|
||||
exclusive={true}
|
||||
value={fav.mode}
|
||||
onChange={(e, mode) => {
|
||||
setFav({ ...fav, mode, currency: mode === 'fiat' ? 0 : 1000 });
|
||||
value={settings.connection}
|
||||
onChange={(_e, connection) => {
|
||||
setSettings({ ...settings, connection });
|
||||
systemClient.setItem('settings_connection', connection);
|
||||
}}
|
||||
>
|
||||
<ToggleButton value='fiat' color='primary'>
|
||||
<AttachMoney />
|
||||
{t('Fiat')}
|
||||
<ToggleButton value='api' color='primary' sx={{ flexGrow: 1 }}>
|
||||
{t('API')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value='swap' color='secondary'>
|
||||
<SwapCalls />
|
||||
{t('Swaps')}
|
||||
<ToggleButton value='nostr' color='secondary' sx={{ flexGrow: 1 }}>
|
||||
{t('nostr')}
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</ListItem>
|
||||
@ -221,17 +223,18 @@ const SettingsForm = ({ dense = false }: SettingsFormProps): JSX.Element => {
|
||||
<Link />
|
||||
</ListItemIcon>
|
||||
<ToggleButtonGroup
|
||||
sx={{ width: '100%' }}
|
||||
exclusive={true}
|
||||
value={settings.network}
|
||||
onChange={(e, network) => {
|
||||
onChange={(_e, network) => {
|
||||
setSettings({ ...settings, network });
|
||||
systemClient.setItem('settings_network', network);
|
||||
}}
|
||||
>
|
||||
<ToggleButton value='mainnet' color='primary'>
|
||||
<ToggleButton value='mainnet' color='primary' sx={{ flexGrow: 1 }}>
|
||||
{t('Mainnet')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value='testnet' color='secondary'>
|
||||
<ToggleButton value='testnet' color='secondary' sx={{ flexGrow: 1 }}>
|
||||
{t('Testnet')}
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
|
@ -14,7 +14,7 @@ import { federationLottery } from '../utils';
|
||||
|
||||
import { AppContext, type UseAppStoreType } from './AppContext';
|
||||
import { GarageContext, type UseGarageStoreType } from './GarageContext';
|
||||
import { type Origin, type Origins } from '../models/Coordinator.model';
|
||||
import Coordinator, { type Origin, type Origins } from '../models/Coordinator.model';
|
||||
|
||||
export interface CurrentOrderIdProps {
|
||||
id: number | null;
|
||||
@ -68,10 +68,14 @@ export const FederationContextProvider = ({
|
||||
useEffect(() => {
|
||||
if (client !== 'mobile' || torStatus === 'ON' || !settings.useProxy) {
|
||||
void federation.updateUrl(origin, settings, hostUrl);
|
||||
void federation.update();
|
||||
void federation.updateMeta();
|
||||
}
|
||||
}, [settings.network, settings.useProxy, torStatus]);
|
||||
|
||||
useEffect(() => {
|
||||
federation.setConnection(settings.connection);
|
||||
}, [settings.connection]);
|
||||
|
||||
const addNewCoordinator: (alias: string, url: string) => void = (alias, url) => {
|
||||
if (!federation.coordinators[alias]) {
|
||||
const attributes: Record<any, any> = {
|
||||
@ -91,8 +95,8 @@ export const FederationContextProvider = ({
|
||||
attributes.testnet = origins;
|
||||
}
|
||||
federation.addCoordinator(origin, settings, hostUrl, attributes);
|
||||
const newCoordinator = federation.coordinators[alias];
|
||||
newCoordinator.update(() => {
|
||||
const newCoordinator: Coordinator = federation.coordinators[alias];
|
||||
newCoordinator.updateMeta(() => {
|
||||
setCoordinatorUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
garage.syncCoordinator(federation, alias);
|
||||
|
@ -5,7 +5,7 @@ export interface PublicOrder {
|
||||
type: number;
|
||||
currency: number | null;
|
||||
amount: string;
|
||||
base_amount?: number;
|
||||
base_price?: number;
|
||||
has_range: boolean;
|
||||
min_amount: string | null;
|
||||
max_amount: string | null;
|
||||
|
@ -182,12 +182,11 @@ export class Coordinator {
|
||||
}
|
||||
};
|
||||
|
||||
update = async (onUpdate: (shortAlias: string) => void = () => {}): Promise<void> => {
|
||||
updateMeta = async (onUpdate: (shortAlias: string) => void = () => {}): Promise<void> => {
|
||||
const onDataLoad = (): void => {
|
||||
if (this.isUpdated()) onUpdate(this.shortAlias);
|
||||
};
|
||||
|
||||
// this.loadBook(onDataLoad);
|
||||
this.loadLimits(onDataLoad);
|
||||
this.loadInfo(onDataLoad);
|
||||
};
|
||||
@ -198,8 +197,8 @@ export class Coordinator {
|
||||
});
|
||||
};
|
||||
|
||||
generateAllMakerAvatars = async (data: [PublicOrder]): Promise<void> => {
|
||||
for (const order of data) {
|
||||
generateAllMakerAvatars = async (): Promise<void> => {
|
||||
for (const order of Object.values(this.book)) {
|
||||
void roboidentitiesClient.generateRobohash(order.maker_hash_id, 'small');
|
||||
}
|
||||
};
|
||||
@ -209,30 +208,29 @@ export class Coordinator {
|
||||
if (this.url === '') return;
|
||||
if (this.loadingBook) return;
|
||||
|
||||
// this.loadingBook = true;
|
||||
// this.book = [];
|
||||
this.loadingBook = true;
|
||||
this.book = {};
|
||||
|
||||
// apiClient
|
||||
// .get(this.url, `${this.basePath}/api/book/`)
|
||||
// .then((data) => {
|
||||
// if (!data?.not_found) {
|
||||
// this.book = (data as PublicOrder[]).map((order) => {
|
||||
// order.coordinatorShortAlias = this.shortAlias;
|
||||
// return order;
|
||||
// });
|
||||
// void this.generateAllMakerAvatars(data);
|
||||
// onDataLoad();
|
||||
// } else {
|
||||
// this.book = [];
|
||||
// onDataLoad();
|
||||
// }
|
||||
// })
|
||||
// .catch((e) => {
|
||||
// console.log(e);
|
||||
// })
|
||||
// .finally(() => {
|
||||
// this.loadingBook = false;
|
||||
// });
|
||||
apiClient
|
||||
.get(this.url, `${this.basePath}/api/book/`)
|
||||
.then((data) => {
|
||||
if (!data?.not_found) {
|
||||
this.book = (data as PublicOrder[]).reduce<Record<string, PublicOrder>>((book, order) => {
|
||||
order.coordinatorShortAlias = this.shortAlias;
|
||||
return { ...book, [this.shortAlias + order.id]: order };
|
||||
}, {});
|
||||
void this.generateAllMakerAvatars();
|
||||
onDataLoad();
|
||||
} else {
|
||||
onDataLoad();
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {
|
||||
this.loadingBook = false;
|
||||
});
|
||||
};
|
||||
|
||||
loadLimits = (onDataLoad: () => void = () => {}): void => {
|
||||
@ -289,7 +287,7 @@ export class Coordinator {
|
||||
|
||||
enable = (onEnabled: () => void = () => {}): void => {
|
||||
this.enabled = true;
|
||||
void this.update(() => {
|
||||
void this.updateMeta(() => {
|
||||
onEnabled();
|
||||
});
|
||||
};
|
||||
|
@ -63,6 +63,7 @@ export interface Exchange {
|
||||
enabledCoordinators: number;
|
||||
onlineCoordinators: number;
|
||||
loadingCoordinators: number;
|
||||
loadingCache: number;
|
||||
totalCoordinators: number;
|
||||
}
|
||||
|
||||
@ -80,6 +81,7 @@ export const defaultExchange: Exchange = {
|
||||
enabledCoordinators: 0,
|
||||
onlineCoordinators: 0,
|
||||
loadingCoordinators: 0,
|
||||
loadingCache: 0,
|
||||
totalCoordinators: 0,
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { SimplePool } from 'nostr-tools';
|
||||
import { SimplePool, VerifiedEvent, Event } from 'nostr-tools';
|
||||
import {
|
||||
Coordinator,
|
||||
type Exchange,
|
||||
@ -13,6 +13,7 @@ import { getHost } from '../utils';
|
||||
import { coordinatorDefaultValues } from './Coordinator.model';
|
||||
import { updateExchangeInfo } from './Exchange.model';
|
||||
import eventToPublicOrder from '../utils/nostr';
|
||||
import { SubCloser } from 'nostr-tools/lib/types/pool';
|
||||
|
||||
type FederationHooks = 'onFederationUpdate';
|
||||
|
||||
@ -57,32 +58,49 @@ export class Federation {
|
||||
return Object.values(coor.testnet).includes(url);
|
||||
});
|
||||
if (tesnetHost) settings.network = 'testnet';
|
||||
this.connection = null;
|
||||
|
||||
const relays = [
|
||||
'ws://4t4jxmivv6uqej6xzx2jx3fxh75gtt65v3szjoqmc4ugdlhipzdat6yd.onion/nostr',
|
||||
// 'ws://ngdk7ocdzmz5kzsysa3om6du7ycj2evxp2f2olfkyq37htx3gllwp2yd.onion/nostr'
|
||||
];
|
||||
this.relayPool.trustedRelayURLs = new Set<string>(relays);
|
||||
}
|
||||
|
||||
public coordinators: Record<string, Coordinator>;
|
||||
public exchange: Exchange;
|
||||
public book: Record<string, PublicOrder>;
|
||||
public loading: boolean;
|
||||
public connection: 'api' | 'nostr' | null;
|
||||
|
||||
public hooks: Record<FederationHooks, Array<() => void>>;
|
||||
|
||||
public relayPool: SimplePool = new SimplePool();
|
||||
public relaySubscriptions: SubCloser[] = [];
|
||||
|
||||
setConnection = (connection: 'api' | 'nostr'): void => {
|
||||
this.connection = connection;
|
||||
|
||||
if (this.connection === 'nostr') {
|
||||
this.connectNostr();
|
||||
} else {
|
||||
this.relayPool.close(Array.from(this.relayPool.trustedRelayURLs));
|
||||
this.updateBook();
|
||||
}
|
||||
};
|
||||
|
||||
connectNostr = (): void => {
|
||||
this.loading = true;
|
||||
this.book = {};
|
||||
|
||||
const relays = ['ws://satstraoq35jffvkgpfoqld32nzw2siuvowanruindbfojowpwsjdgad.onion/nostr'];
|
||||
|
||||
this.exchange.loadingCoordinators = relays.length;
|
||||
this.exchange.loadingCache = this.relayPool.trustedRelayURLs.size;
|
||||
|
||||
const authors = Object.values(defaultFederation)
|
||||
.map((f) => f.nostrHexPubkey)
|
||||
.filter((item) => item !== undefined);
|
||||
|
||||
this.relayPool.trustedRelayURLs = new Set<string>(relays);
|
||||
this.relayPool.subscribeMany(
|
||||
relays,
|
||||
const sub = this.relayPool.subscribeMany(
|
||||
Array.from(this.relayPool.trustedRelayURLs),
|
||||
[
|
||||
{
|
||||
authors,
|
||||
@ -93,7 +111,6 @@ export class Federation {
|
||||
{
|
||||
onevent: (event) => {
|
||||
const { dTag, publicOrder } = eventToPublicOrder(event);
|
||||
|
||||
if (publicOrder) {
|
||||
this.book[dTag] = publicOrder;
|
||||
} else {
|
||||
@ -101,19 +118,20 @@ export class Federation {
|
||||
}
|
||||
},
|
||||
oneose: () => {
|
||||
this.exchange.loadingCoordinators = this.exchange.loadingCoordinators - 1;
|
||||
this.loading = this.exchange.loadingCoordinators > 0;
|
||||
this.exchange.loadingCache = this.exchange.loadingCache - 1;
|
||||
this.loading = this.exchange.loadingCache > 0 && this.exchange.loadingCoordinators > 0;
|
||||
this.updateExchange();
|
||||
this.triggerHook('onFederationUpdate');
|
||||
},
|
||||
onclose: () => {
|
||||
this.exchange.loadingCoordinators = this.exchange.loadingCoordinators - 1;
|
||||
this.loading = this.exchange.loadingCoordinators > 0;
|
||||
this.exchange.loadingCache = this.exchange.loadingCache - 1;
|
||||
this.loading = this.exchange.loadingCache > 0 && this.exchange.loadingCoordinators > 0;
|
||||
this.updateExchange();
|
||||
this.triggerHook('onFederationUpdate');
|
||||
},
|
||||
},
|
||||
);
|
||||
this.relaySubscriptions.push(sub);
|
||||
};
|
||||
|
||||
addCoordinator = (
|
||||
@ -144,15 +162,17 @@ export class Federation {
|
||||
};
|
||||
|
||||
onCoordinatorSaved = (): void => {
|
||||
// this.book = Object.values(this.coordinators).reduce<Record<string, PublicOrder>>(
|
||||
// (book, coordinator) => {
|
||||
// return { ...book, ...coordinator.book };
|
||||
// },
|
||||
// {},
|
||||
// );
|
||||
if (this.connection === 'api') {
|
||||
this.book = Object.values(this.coordinators).reduce<Record<string, PublicOrder>>(
|
||||
(book, coordinator) => {
|
||||
return { ...book, ...coordinator.book };
|
||||
},
|
||||
{},
|
||||
);
|
||||
}
|
||||
this.exchange.loadingCoordinators =
|
||||
this.exchange.loadingCoordinators < 1 ? 0 : this.exchange.loadingCoordinators - 1;
|
||||
this.loading = this.exchange.loadingCoordinators > 0;
|
||||
this.loading = this.exchange.loadingCache > 0 && this.exchange.loadingCoordinators > 0;
|
||||
this.updateExchange();
|
||||
this.triggerHook('onFederationUpdate');
|
||||
};
|
||||
@ -166,7 +186,7 @@ export class Federation {
|
||||
systemClient.setCookie('federation', JSON.stringify(federationUrls));
|
||||
};
|
||||
|
||||
update = async (): Promise<void> => {
|
||||
updateMeta = async (): Promise<void> => {
|
||||
this.loading = true;
|
||||
this.exchange.info = {
|
||||
num_public_buy_orders: 0,
|
||||
@ -182,10 +202,8 @@ export class Federation {
|
||||
this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
|
||||
this.updateEnabledCoordinators();
|
||||
|
||||
this.connectNostr();
|
||||
|
||||
for (const coor of Object.values(this.coordinators)) {
|
||||
void coor.update(() => {
|
||||
void coor.updateMeta(() => {
|
||||
this.exchange.onlineCoordinators = this.exchange.onlineCoordinators + 1;
|
||||
this.onCoordinatorSaved();
|
||||
});
|
||||
@ -193,16 +211,18 @@ export class Federation {
|
||||
};
|
||||
|
||||
updateBook = async (): Promise<void> => {
|
||||
// this.loading = true;
|
||||
// this.book = [];
|
||||
// this.triggerHook('onFederationUpdate');
|
||||
// this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
|
||||
// for (const coor of Object.values(this.coordinators)) {
|
||||
// void coor.updateBook(() => {
|
||||
// this.onCoordinatorSaved();
|
||||
// this.triggerHook('onFederationUpdate');
|
||||
// });
|
||||
// }
|
||||
if (this.connection !== 'api') return;
|
||||
|
||||
this.loading = true;
|
||||
this.book = {};
|
||||
this.triggerHook('onFederationUpdate');
|
||||
this.exchange.loadingCoordinators = Object.keys(this.coordinators).length;
|
||||
for (const coor of Object.values(this.coordinators)) {
|
||||
void coor.updateBook(() => {
|
||||
this.onCoordinatorSaved();
|
||||
this.triggerHook('onFederationUpdate');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
updateExchange = (): void => {
|
||||
|
@ -42,6 +42,9 @@ class BaseSettings {
|
||||
? 'en'
|
||||
: i18n.resolvedLanguage.substring(0, 2);
|
||||
|
||||
const connection = systemClient.getItem('settings_connection');
|
||||
this.connection = connection && connection !== '' ? connection : 'api';
|
||||
|
||||
const networkCookie = systemClient.getItem('settings_network');
|
||||
this.network = networkCookie && networkCookie !== '' ? networkCookie : 'mainnet';
|
||||
this.host = getHost();
|
||||
@ -63,6 +66,7 @@ class BaseSettings {
|
||||
public language?: Language;
|
||||
public freezeViewports: boolean = false;
|
||||
public network: 'mainnet' | 'testnet' = 'mainnet';
|
||||
public connection: 'api' | 'nostr' = 'api';
|
||||
public host?: string;
|
||||
public unsafeClient: boolean = false;
|
||||
public selfhostedClient: boolean = false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Event } from 'nostr-tools';
|
||||
import { PublicOrder } from '../models';
|
||||
import { Federation, PublicOrder } from '../models';
|
||||
import { fromUnixTime } from 'date-fns';
|
||||
import Geohash from 'latlon-geohash';
|
||||
import currencyDict from '../../static/assets/currencies.json';
|
||||
@ -93,8 +93,6 @@ const eventToPublicOrder = (event: Event): { dTag: string; publicOrder: PublicOr
|
||||
}
|
||||
});
|
||||
|
||||
// price = limitsList[index].price * (1 + premium / 100);
|
||||
|
||||
return { dTag: dTag[1], publicOrder };
|
||||
};
|
||||
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "La teva última ordre #{{orderID}}",
|
||||
"finished order": "Ordre finalitzada",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Fosc",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Clar",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Intercanvis",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connectat a la xarxa TOR",
|
||||
"Connecting to TOR network": "Connectant a la xarxa TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Tvá poslední nabídka #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Deine letzte Order #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Your last order #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Tu última orden #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Oscuro",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Claro",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Conectado a la red TOR",
|
||||
"Connecting to TOR network": "Conectando a la red TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Zure azken eskaera #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Votre dernière commande #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Sombre",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Échanges",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connecté au réseau TOR",
|
||||
"Connecting to TOR network": "Connexion au réseau TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Il tuo ultimo ordine #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Scuro",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Chiaro",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connesso alla rete TOR",
|
||||
"Connecting to TOR network": "Connessione alla rete TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "前回のオーダー #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "ダーク",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "フィアット",
|
||||
"Light": "ライト",
|
||||
"Mainnet": "メインネット",
|
||||
"Swaps": "スワップ",
|
||||
"Testnet": "テストネット",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "TORネットワークに接続しました",
|
||||
"Connecting to TOR network": "TORネットワークに接続中",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Your last order #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Sua última ordem #{{orderID}}",
|
||||
"finished order": "ordem finalizada",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Conectado à rede TOR",
|
||||
"Connecting to TOR network": "Conectando à rede TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Ваш последний ордер #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Темный",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Фиат",
|
||||
"Light": "Светлый",
|
||||
"Mainnet": "Основная сеть",
|
||||
"Swaps": "Обмен",
|
||||
"Testnet": "Тестовая сеть",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Подключено к сети TOR",
|
||||
"Connecting to TOR network": "Подключение к сети TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Din senaste order #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "Amri yako ya mwisho #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Giza",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Nuru",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Kuunganishwa kwa mtandao wa TOR",
|
||||
"Connecting to TOR network": "Kuunganisha kwa mtandao wa TOR",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "รายการล่าสุดของคุณ #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "Dark",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "Fiat",
|
||||
"Light": "Light",
|
||||
"Mainnet": "Mainnet",
|
||||
"Swaps": "Swaps",
|
||||
"Testnet": "Testnet",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "你的上一笔交易 #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "深色",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "法币",
|
||||
"Light": "浅色",
|
||||
"Mainnet": "主网",
|
||||
"Swaps": "交换",
|
||||
"Testnet": "测试网",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "已连线 TOR 网络",
|
||||
"Connecting to TOR network": "正在连线 TOR 网络",
|
||||
|
@ -490,14 +490,14 @@
|
||||
"Your last order #{{orderID}}": "你的上一筆交易 #{{orderID}}",
|
||||
"finished order": "finished order",
|
||||
"#43": "Phrases in components/SettingsForm/index.tsx",
|
||||
"API": "API",
|
||||
"Build-in": "Build-in",
|
||||
"Dark": "深色",
|
||||
"Disabled": "Disabled",
|
||||
"Fiat": "法幣",
|
||||
"Light": "淺色",
|
||||
"Mainnet": "主網",
|
||||
"Swaps": "交換",
|
||||
"Testnet": "測試網",
|
||||
"nostr": "nostr",
|
||||
"#44": "Phrases in components/TorConnection/index.tsx",
|
||||
"Connected to TOR network": "已連線 TOR 網絡",
|
||||
"Connecting to TOR network": "正在連線 TOR 網絡",
|
||||
|
@ -93,6 +93,7 @@ const App = () => {
|
||||
loadCookie('settings_mode');
|
||||
loadCookie('settings_light_qr');
|
||||
loadCookie('settings_network');
|
||||
loadCookie('settings_connection');
|
||||
loadCookie('settings_use_proxy').then((useProxy) => {
|
||||
SystemModule.useProxy(useProxy ?? 'true');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user