This commit is contained in:
koalasat 2024-10-11 15:57:42 +02:00
parent 49c2469bb1
commit 560def2966
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
29 changed files with 229 additions and 178 deletions

View File

@ -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>
);

View File

@ -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}

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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();
});
};

View File

@ -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,
};

View File

@ -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 => {

View File

@ -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;

View File

@ -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 };
};

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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ネットワークに接続中",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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 网络",

View File

@ -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 網絡",

View File

@ -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');
});