More fixes

This commit is contained in:
Reckless_Satoshi 2023-11-02 14:15:18 +00:00 committed by Reckless_Satoshi
parent 4eb46f1e16
commit 7f78f69df6
20 changed files with 113 additions and 100 deletions

View File

@ -835,7 +835,7 @@ const BookTable = ({
<Grid item xs={6}>
<IconButton
onClick={() => {
federation.update();
void federation.update();
}}
>
<Refresh />

View File

@ -81,7 +81,7 @@ const Map = ({
}
eventHandlers={{
click: (_event: LeafletMouseEvent) => {
order?.id && onOrderClicked(order.id);
order?.id != null && onOrderClicked(order.id);
},
}}
>
@ -111,7 +111,7 @@ const Map = ({
return (
<MarkerClusterGroup showCoverageOnHover={true} disableClusteringAtZoom={14}>
{orders.map((order) => {
if (!order?.latitude || !order?.longitude) return <></>;
if (!(order?.latitude != null) || !(order?.longitude != null)) return <></>;
return RobotMarker(order.id, [order.latitude, order.longitude], order.type ?? 0, order);
})}
</MarkerClusterGroup>

View File

@ -82,7 +82,9 @@ const TakeButton = ({
}, [orderUpdatedAt, takeAmount, info]);
const currencyCode: string =
garage.getOrder()?.currency === 1000 ? 'Sats' : currencies[`${garage.getOrder()?.currency}`];
garage.getOrder()?.currency === 1000
? 'Sats'
: currencies[`${Number(garage.getOrder()?.currency)}`];
const InactiveMakerDialog = function (): JSX.Element {
return (
@ -188,7 +190,7 @@ const TakeButton = ({
}, [takeAmount, orderUpdatedAt]);
const takeOrderButton = function (): JSX.Element {
if (garage.getOrder()?.has_range) {
if (garage.getOrder()?.has_range === true) {
return (
<Box
sx={{
@ -315,7 +317,7 @@ const TakeButton = ({
};
const takeOrder = function (): void {
if (!focusedCoordinator) return;
if (!(focusedCoordinator != null)) return;
setLoadingTake(true);
const { url } = federation

View File

@ -36,7 +36,7 @@ import { PaymentStringAsIcons } from '../../components/PaymentMethods';
import { FlagWithProps, SendReceiveIcon } from '../Icons';
import LinearDeterminate from './LinearDeterminate';
import type { Order, Coordinator } from '../../models';
import type Coordinator from '../../models';
import { statusBadgeColor, pn, amountToString, computeSats } from '../../utils';
import TakeButton from './TakeButton';
import { F2fMapDialog } from '../Dialogs';
@ -291,7 +291,7 @@ const OrderDetails = ({
/>
</ListItemAvatar>
<ListItemText
primary={`${currentOrder.order?.maker_nick} (${
primary={`${String(currentOrder.order?.maker_nick)} (${
currentOrder.order?.type === 1
? t(currentOrder.order?.currency === 1000 ? 'Swapping Out' : 'Seller')
: t(currentOrder.order?.currency === 1000 ? 'Swapping In' : 'Buyer')
@ -301,12 +301,15 @@ const OrderDetails = ({
</ListItem>
<Collapse
in={currentOrder.order?.is_participant && currentOrder.order?.taker_nick !== 'None'}
in={
currentOrder.order?.is_participant === true &&
currentOrder.order?.taker_nick !== 'None'
}
>
<Divider />
<ListItem>
<ListItemText
primary={`${currentOrder.order?.taker_nick} (${
primary={`${String(currentOrder.order?.taker_nick)} (${
currentOrder.order?.type === 1
? t(currentOrder.order?.currency === 1000 ? 'Swapping In' : 'Buyer')
: t(currentOrder.order?.currency === 1000 ? 'Swapping Out' : 'Seller')
@ -422,7 +425,7 @@ const OrderDetails = ({
: t('Accepted payment methods')
}
/>
{currentOrder.order?.payment_method.includes('Cash F2F') && (
{currentOrder.order?.payment_method.includes('Cash F2F') === true && (
<ListItemIcon>
<Tooltip enterTouchDelay={0} title={t('F2F location')}>
<div>
@ -457,14 +460,16 @@ const OrderDetails = ({
/>
) : null}
{currentOrder.order?.price_now === undefined && currentOrder.order?.is_explicit ? (
{currentOrder.order?.price_now === undefined &&
currentOrder.order?.is_explicit === true ? (
<ListItemText
primary={pn(currentOrder.order?.satoshis)}
secondary={t('Amount of Satoshis')}
/>
) : null}
{currentOrder.order?.price_now === undefined && !currentOrder.order?.is_explicit ? (
{currentOrder.order?.price_now === undefined &&
!(currentOrder.order?.is_explicit === true) ? (
<ListItemText
primary={`${parseFloat(Number(currentOrder.order?.premium).toFixed(2))}%`}
secondary={t('Premium over market price')}
@ -537,7 +542,7 @@ const OrderDetails = ({
<></>
)}
{!currentOrder.order?.is_participant ? (
{!(currentOrder.order?.is_participant === true) ? (
<Grid item xs={12}>
<TakeButton
baseUrl={baseUrl}

View File

@ -66,7 +66,7 @@ const RobotAvatar: React.FC<Props> = ({
if (window.NativeRobosats === undefined) {
setAvatarSrc(`${baseUrl}${path}${nickname}${small ? '.small' : ''}.webp`);
setNicknameReady(true);
} else if (focusedCoordinator) {
} else if (focusedCoordinator != null) {
setNicknameReady(true);
const { url } = federation
.getCoordinator(focusedCoordinator)

View File

@ -1,4 +1,4 @@
import React, { useContext, useEffect, useMemo, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import {
Tooltip,
@ -66,7 +66,7 @@ const RobotInfo: React.FC<Props> = ({ robot, slotIndex, coordinator, onClose }:
};
useEffect(() => {
handleWebln();
void handleWebln();
}, []);
const handleWeblnInvoiceClicked = async (e: MouseEvent<HTMLButtonElement, MouseEvent>): void => {
@ -87,10 +87,10 @@ const RobotInfo: React.FC<Props> = ({ robot, slotIndex, coordinator, onClose }:
const robot = garage.getRobot(slotIndex);
if (robot.encPrivKey && robot.token) {
if (robot.encPrivKey != null && robot.token != null) {
void signCleartextMessage(rewardInvoice, robot.encPrivKey, robot.token).then(
(signedInvoice) => {
coordinator.fetchReward(signedInvoice, garage, slotIndex).then((data) => {
void coordinator.fetchReward(signedInvoice, garage, slotIndex).then((data) => {
setBadInvoice(data.bad_invoice ?? '');
setShowRewardsSpinner(false);
setWithdrawn(data.successful_withdrawal);
@ -103,7 +103,7 @@ const RobotInfo: React.FC<Props> = ({ robot, slotIndex, coordinator, onClose }:
};
const setStealthInvoice = (wantsStealth: boolean): void => {
coordinator.fetchStealth(wantsStealth, garage, slotIndex);
void coordinator.fetchStealth(wantsStealth, garage, slotIndex);
};
return (

View File

@ -22,12 +22,13 @@ const CancelButton = ({
const { t } = useTranslation();
const showCancelButton =
(order?.is_maker && [0, 1, 2].includes(order?.status)) ||
(order?.is_maker === true && [0, 1, 2].includes(order?.status)) ??
[3, 6, 7].includes(order?.status ?? -1);
const showCollabCancelButton = [8, 9].includes(order?.status ?? -1) && !order?.asked_for_cancel;
const showCollabCancelButton =
[8, 9].includes(order?.status ?? -1) && !(order?.asked_for_cancel === true);
const noConfirmation =
(order?.is_maker && [0, 1, 2].includes(order?.status ?? -1)) ||
(order?.is_taker && order?.status === 3);
(order?.is_maker === true && [0, 1, 2].includes(order?.status ?? -1)) ??
(order?.is_taker === true && order?.status === 3);
return (
<Box>

View File

@ -10,11 +10,11 @@ interface CollabCancelAlertProps {
const CollabCancelAlert = ({ order }: CollabCancelAlertProps): JSX.Element => {
const { t } = useTranslation();
let text = '';
if (order?.pending_cancel) {
if (order?.pending_cancel === true) {
text = t('{{nickname}} is asking for a collaborative cancel', {
nickname: order?.is_maker ? order?.taker_nick : order?.maker_nick,
});
} else if (order?.asked_for_cancel) {
} else if (order?.asked_for_cancel === true) {
text = t('You asked for a collaborative cancellation');
}

View File

@ -8,7 +8,6 @@ import {
DialogContentText,
Button,
} from '@mui/material';
import { type Order } from '../../../models';
import { LoadingButton } from '@mui/lab';
interface ConfirmUndoFiatSentDialogProps {

View File

@ -1,10 +1,11 @@
import React, { useEffect, useLayoutEffect, useState } from 'react';
import React, { useEffect, useLayoutEffect, useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { Button, TextField, Grid, Paper, Typography } from '@mui/material';
import { encryptMessage, decryptMessage } from '../../../../pgp';
import { AuditPGPDialog } from '../../../Dialogs';
import { websocketClient, type WebsocketConnection } from '../../../../services/Websocket';
import { type Robot } from '../../../../models';
import { GarageContext, type UseGarageStoreType } from '../../../../contexts/GarageContext';
// Icons
import CircularProgress from '@mui/material/CircularProgress';

View File

@ -58,6 +58,7 @@ interface loadingButtonsProps {
cancel: boolean;
fiatSent: boolean;
fiatReceived: boolean;
undoFiatSent: boolean;
submitInvoice: boolean;
submitAddress: boolean;
submitStatement: boolean;
@ -70,6 +71,7 @@ const noLoadingButtons: loadingButtonsProps = {
cancel: false,
fiatSent: false,
fiatReceived: false,
undoFiatSent: false,
submitInvoice: false,
submitAddress: false,
submitStatement: false,
@ -167,7 +169,7 @@ const TradeBox = ({
void apiClient
.post(
url,
`/api/order/?order_id=${currentOrder.id}`,
`/api/order/?order_id=${Number(currentOrder.id)}`,
{
action,
invoice,
@ -234,7 +236,7 @@ const TradeBox = ({
const updateInvoice = function (invoice: string): void {
const robot = garage.getRobot();
if (robot !== null && robot.encPrivKey && robot.token) {
if (robot?.encPrivKey != null && robot?.token != null) {
setLoadingButtons({ ...noLoadingButtons, submitInvoice: true });
void signCleartextMessage(invoice, robot.encPrivKey, robot.token).then((signedInvoice) => {
submitAction({
@ -249,7 +251,7 @@ const TradeBox = ({
const updateAddress = function (): void {
const robot = garage.getRobot();
if (robot !== null && robot.encPrivKey && robot.token) {
if (robot?.encPrivKey != null && robot?.token != null) {
setLoadingButtons({ ...noLoadingButtons, submitAddress: true });
void signCleartextMessage(onchain.address, robot.encPrivKey, robot.token).then(
(signedAddress) => {
@ -287,6 +289,7 @@ const TradeBox = ({
});
// If Webln implements locked payments compatibility, this logic might be simplier
if (webln === undefined) {
console.log('WebLN dialog will not be shown');
} else if (order.is_maker && order.status === 0) {
webln.sendPayment(order.bond_invoice);
setWaitingWebln(true);
@ -324,7 +327,7 @@ const TradeBox = ({
useEffect(() => {
if (currentOrder.order !== null && currentOrder.order.status !== lastOrderStatus) {
setLastOrderStatus(currentOrder.order.status);
handleWebln(currentOrder.order);
void handleWebln(currentOrder.order);
}
// FIXME this should trigger with current order, not garage order
}, [orderUpdatedAt]);

View File

@ -16,27 +16,29 @@ import { AppContext, type UseAppStoreType } from './AppContext';
import { GarageContext, type UseGarageStoreType } from './GarageContext';
// Refresh delays (ms) according to Order status
const statusToDelay = [
3000, // 'Waiting for maker bond'
35000, // 'Public'
180000, // 'Paused'
3000, // 'Waiting for taker bond'
999999, // 'Cancelled'
999999, // 'Expired'
8000, // 'Waiting for trade collateral and buyer invoice'
8000, // 'Waiting only for seller trade collateral'
8000, // 'Waiting only for buyer invoice'
10000, // 'Sending fiat - In chatroom'
10000, // 'Fiat sent - In chatroom'
100000, // 'In dispute'
999999, // 'Collaboratively cancelled'
10000, // 'Sending satoshis to buyer'
60000, // 'Sucessful trade'
30000, // 'Failed lightning network routing'
300000, // 'Wait for dispute resolution'
300000, // 'Maker lost dispute'
300000, // 'Taker lost dispute'
];
// FIXME statusToDelay is never used. On order received, we should setDelay according to new received status.
// const statusToDelay = [
// 3000, // 'Waiting for maker bond'
// 35000, // 'Public'
// 180000, // 'Paused'
// 3000, // 'Waiting for taker bond'
// 999999, // 'Cancelled'
// 999999, // 'Expired'
// 8000, // 'Waiting for trade collateral and buyer invoice'
// 8000, // 'Waiting only for seller trade collateral'
// 8000, // 'Waiting only for buyer invoice'
// 10000, // 'Sending fiat - In chatroom'
// 10000, // 'Fiat sent - In chatroom'
// 100000, // 'In dispute'
// 999999, // 'Collaboratively cancelled'
// 10000, // 'Sending satoshis to buyer'
// 60000, // 'Sucessful trade'
// 30000, // 'Failed lightning network routing'
// 300000, // 'Wait for dispute resolution'
// 300000, // 'Maker lost dispute'
// 300000, // 'Taker lost dispute'
// ];
export interface fetchRobotProps {
coordinator?: Coordinator;
@ -128,14 +130,14 @@ export const useFederationStore = (): UseFederationStoreType => {
newFed.registerHook('onCoordinatorUpdate', () => {
setFederationUpdatedAt(new Date().toISOString());
});
newFed.start(origin, settings, hostUrl);
void newFed.start(origin, settings, hostUrl);
return newFed;
});
}, [settings.network, torStatus]);
const fetchCurrentOrder = () => {
const fetchCurrentOrder = (): void => {
if (currentOrder.id != null && (page === 'order' || badOrder === undefined)) {
federation.fetchOrder(currentOrder, garage.getRobot());
void federation.fetchOrder(currentOrder, garage.getRobot());
}
};
@ -157,14 +159,14 @@ export const useFederationStore = (): UseFederationStoreType => {
if (robot !== null) {
if (open.profile && robot?.avatarLoaded) {
federation.fetchRobot(garage, garage.currentSlot); // refresh/update existing robot
void federation.fetchRobot(garage, garage.currentSlot); // refresh/update existing robot
} else if (
!robot.avatarLoaded &&
robot.token !== undefined &&
robot.encPrivKey !== undefined &&
robot.pubKey !== undefined
) {
federation.fetchRobot(garage, garage.currentSlot); // create new robot with existing token and keys (on network and coordinator change)
void federation.fetchRobot(garage, garage.currentSlot); // create new robot with existing token and keys (on network and coordinator change)
}
}
}, [open.profile, hostUrl, robotUpdatedAt]);

View File

@ -1,4 +1,3 @@
import { sha256 } from 'js-sha256';
import {
type Robot,
type LimitList,
@ -8,9 +7,8 @@ import {
type Garage,
} from '.';
import { apiClient } from '../services/api';
import { hexToBase91, validateTokenEntropy } from '../utils';
import { validateTokenEntropy } from '../utils';
import { compareUpdateLimit } from './Limit.model';
import { signCleartextMessage } from '../pgp';
export interface Contact {
nostr?: string | undefined;
@ -132,7 +130,7 @@ export class Coordinator {
hostUrl: string,
onStarted: (shortAlias: string) => void = () => {},
): Promise<void> => {
if (!this.enabled) return;
if (this.enabled !== true) return;
if (settings.selfhostedClient && this.shortAlias !== 'local') {
this.url = hostUrl;
@ -142,13 +140,13 @@ export class Coordinator {
this.basePath = '';
}
this.update(() => {
void this.update(() => {
onStarted(this.shortAlias);
});
};
update = async (onUpdate: (shortAlias: string) => void = () => {}): Promise<void> => {
const onDataLoad = () => {
const onDataLoad = (): void => {
if (this.isUpdated()) onUpdate(this.shortAlias);
};
@ -157,7 +155,7 @@ export class Coordinator {
this.loadInfo(onDataLoad);
};
loadBook = (onDataLoad: () => void = () => {}) => {
loadBook = (onDataLoad: () => void = () => {}): void => {
if (this.loadingBook) return;
this.loadingBook = true;
@ -181,7 +179,7 @@ export class Coordinator {
});
};
loadLimits = (onDataLoad: () => void = () => {}) => {
loadLimits = (onDataLoad: () => void = () => {}): void => {
if (this.loadingLimits) return;
this.loadingLimits = true;
@ -208,7 +206,7 @@ export class Coordinator {
});
};
loadInfo = (onDataLoad: () => void = () => {}) => {
loadInfo = (onDataLoad: () => void = () => {}): void => {
if (this.loadingInfo) return;
this.loadingInfo = true;
@ -227,25 +225,25 @@ export class Coordinator {
});
};
enable = (onEnabled: () => void = () => {}) => {
enable = (onEnabled: () => void = () => {}): void => {
this.enabled = true;
this.update(() => {
void this.update(() => {
onEnabled();
});
};
disable = () => {
disable = (): void => {
this.enabled = false;
this.info = undefined;
this.limits = {};
this.book = [];
};
isUpdated = () => {
isUpdated = (): boolean => {
return !((this.loadingBook === this.loadingInfo) === this.loadingLimits);
};
getBaseUrl = () => {
getBaseUrl = (): string => {
return this.url + this.basePath;
};
@ -265,7 +263,7 @@ export class Coordinator {
fecthRobot = async (garage: Garage, index: number): Promise<Robot | null> => {
const robot = garage?.getRobot(index);
if (!robot?.token) return null;
if (robot?.token == null) return null;
const authHeaders = robot.getAuthHeaders();
@ -313,7 +311,7 @@ export class Coordinator {
};
fetchOrder = async (orderId: number, robot: Robot): Promise<Order | null> => {
if (!robot.token) return null;
if (!(robot.token != null)) return null;
const authHeaders = robot.getAuthHeaders();
@ -340,7 +338,7 @@ export class Coordinator {
}> => {
const robot = garage.getRobot(index);
if (!robot?.token || !robot.encPrivKey) return null;
if (!(robot?.token != null) || !(robot.encPrivKey != null)) return null;
const data = await apiClient.post(
this.url,
@ -352,7 +350,7 @@ export class Coordinator {
);
const newRobot = {
...robot,
earnedRewards: data?.successful_withdrawal ? 0 : robot.earnedRewards,
earnedRewards: data?.successful_withdrawal === true ? 0 : robot.earnedRewards,
};
garage.updateRobot(newRobot, index);
@ -362,7 +360,7 @@ export class Coordinator {
fetchStealth = async (wantsStealth: boolean, garage: Garage, index: number): Promise<null> => {
const robot = garage?.getRobot(index);
if (!robot?.token || !robot.encPrivKey) return null;
if (!(robot?.token != null) || !(robot.encPrivKey != null)) return null;
await apiClient.post(
this.url,

View File

@ -45,7 +45,7 @@ export const updateExchangeInfo = (federation: Federation): ExchangeInfo => {
highestVersion = getHigherVer(highestVersion, coordinator.info.version);
aggregations.forEach((key: any) => {
info[key] = info[key] + Number(coordinator.info[key]);
info[key] = Number(info[key]) + Number(coordinator.info[key]);
});
}
return null;

View File

@ -53,7 +53,7 @@ export class Federation {
});
};
onCoordinatorSaved = (shortAlias: string) => {
onCoordinatorSaved = (shortAlias: string): void => {
this.book = [...this.book, ...this.getCoordinator(shortAlias).book];
this.loading = false;
this.triggerHook('onCoordinatorUpdate');
@ -64,46 +64,48 @@ export class Federation {
};
// Setup
start = (origin: Origin, settings: Settings, hostUrl: string): void => {
const onCoordinatorStarted = (shortAlias: string) => {
start = async (origin: Origin, settings: Settings, hostUrl: string): Promise<void> => {
const onCoordinatorStarted = (shortAlias: string): void => {
this.exchange.onlineCoordinators = this.exchange.onlineCoordinators + 1;
this.onCoordinatorSaved(shortAlias);
};
this.loading = true;
Object.values(this.coordinators).forEach(async (coor) => {
// Object.values(this.coordinators).forEach(async (coor) => {
for (const coor of Object.values(this.coordinators)) {
await coor.start(origin, settings, hostUrl, onCoordinatorStarted);
});
}
};
update = (): void => {
update = async (): Promise<void> => {
this.loading = false;
Object.values(this.coordinators).forEach(async (coor) => {
// Object.values(this.coordinators).forEach(async (coor) => {
for (const coor of Object.values(this.coordinators)) {
await coor.update(() => {
this.onCoordinatorSaved(coor.shortAlias);
});
});
}
};
updateExchange = () => {
updateExchange = (): void => {
this.exchange.info = updateExchangeInfo(this);
};
// Fetchs
fetchRobot = async (garage: Garage, slot: number): Promise<void> => {
Object.values(this.coordinators).forEach((coor) => {
coor.fecthRobot(garage, slot);
void coor.fecthRobot(garage, slot);
});
};
fetchOrder = async (currentOrder: CurrentOrder, robot: Robot): Promise<CurrentOrder | null> => {
if (currentOrder.shortAlias !== null) {
const coordinator = this.coordinators[currentOrder.shortAlias];
if (coordinator && currentOrder.id !== null) {
const newOrber = await coordinator.fetchOrder(currentOrder.id, robot);
if (coordinator != null && currentOrder.id !== null) {
const newOrder = await coordinator.fetchOrder(currentOrder.id, robot);
return {
...currentOrder,
order: newOrber,
order: newOrder,
};
}
}
@ -115,12 +117,12 @@ export class Federation {
return this.coordinators[shortAlias];
};
disableCoordinator = (shortAlias: string) => {
disableCoordinator = (shortAlias: string): void => {
this.coordinators[shortAlias].disable();
this.triggerHook('onCoordinatorUpdate');
};
enableCoordinator = (shortAlias: string) => {
enableCoordinator = (shortAlias: string): void => {
this.coordinators[shortAlias].enable(() => {
this.triggerHook('onCoordinatorUpdate');
});

View File

@ -93,7 +93,7 @@ class Garage {
index = this.currentSlot,
) => {
const robot = this.getSlot(index).robot;
if (robot) {
if (robot != null) {
robot.update(attributes);
this.triggerHook('onRobotUpdate');
this.save();

View File

@ -1,5 +1,5 @@
import { sha256 } from 'js-sha256';
import { hexToBase91, validateTokenEntropy } from '../utils';
import { hexToBase91 } from '../utils';
interface AuthHeaders {
tokenSHA256: string;
@ -14,7 +14,7 @@ class Robot {
if (garageRobot != null) {
this.token = garageRobot?.token ?? undefined;
this.tokenSHA256 =
garageRobot?.tokenSHA256 ?? (this.token ? hexToBase91(sha256(this.token)) : '');
garageRobot?.tokenSHA256 ?? (this.token != null ? hexToBase91(sha256(this.token)) : '');
this.pubKey = garageRobot?.pubKey ?? undefined;
this.encPrivKey = garageRobot?.encPrivKey ?? undefined;
}
@ -40,7 +40,7 @@ class Robot {
public copiedToken: boolean = false;
public avatarLoaded: boolean = false;
update = (attributes: Record<string, any>) => {
update = (attributes: Record<string, any>): void => {
Object.assign(this, attributes);
};

View File

@ -44,7 +44,7 @@ const BookWidget = React.forwardRef(function Component(
/>
</Paper>
);
}, [book, layout, windowSize, fav]);
}, [layout, windowSize, fav, federation.book]);
});
export default BookWidget;

View File

@ -40,7 +40,7 @@ const DepthChartWidget = React.forwardRef(function Component(
/>
</Paper>
);
}, [fav.currency, book, limits, exchange, layout]);
}, [fav.currency, layout, federation.exchange]);
});
export default DepthChartWidget;

View File

@ -27,7 +27,7 @@ const MakerWidget = React.forwardRef(function Component(
<MakerForm />
</Paper>
);
}, [maker, limits, fav]);
}, [maker, fav, federation]);
});
export default MakerWidget;