diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json
index d0024c93..4993d733 100644
--- a/frontend/.eslintrc.json
+++ b/frontend/.eslintrc.json
@@ -26,6 +26,7 @@
"react-hooks/exhaustive-deps": "off",
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
+ "@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/naming-convention": [
"error",
{
diff --git a/frontend/src/basic/NavBar/NavBar.tsx b/frontend/src/basic/NavBar/NavBar.tsx
index 34cbbfaf..a6794ef2 100644
--- a/frontend/src/basic/NavBar/NavBar.tsx
+++ b/frontend/src/basic/NavBar/NavBar.tsx
@@ -166,7 +166,7 @@ const NavBar = (): JSX.Element => {
value='order'
disabled={
!Boolean(slot?.hashId) ||
- !(slot?.getRobot(slot?.activeShortAlias ?? '')?.activeOrderId != null)
+ !Boolean(slot?.getRobot(slot?.activeShortAlias ?? '')?.activeOrderId)
}
icon={}
iconPosition='start'
diff --git a/frontend/src/basic/OrderPage/index.tsx b/frontend/src/basic/OrderPage/index.tsx
index 64f425b0..cf290be5 100644
--- a/frontend/src/basic/OrderPage/index.tsx
+++ b/frontend/src/basic/OrderPage/index.tsx
@@ -56,9 +56,9 @@ const OrderPage = (): JSX.Element => {
.then((order) => {
if (order?.bad_request !== undefined) {
setBadOrder(order.bad_request);
- } else if (order?.id != null) {
+ } else if (Boolean(order?.id)) {
setCurrentOrder(order);
- if (order.is_participant) {
+ if (order?.is_participant) {
garage.updateOrder(order);
}
}
@@ -82,23 +82,25 @@ const OrderPage = (): JSX.Element => {
navigate('/robot');
};
- const orderDetailsSpace =
- currentOrder != null ? (
- {
- navigate('/robot');
- }}
- />
- ) : (
- <>>
- );
+ const orderDetailsSpace = currentOrder ? (
+ {
+ navigate('/robot');
+ }}
+ />
+ ) : (
+ <>>
+ );
- const tradeBoxSpace =
- currentOrder != null ? : <>>;
+ const tradeBoxSpace = currentOrder ? (
+
+ ) : (
+ <>>
+ );
return (
diff --git a/frontend/src/basic/RobotPage/Onboarding.tsx b/frontend/src/basic/RobotPage/Onboarding.tsx
index 323dc4c5..6e11be3c 100644
--- a/frontend/src/basic/RobotPage/Onboarding.tsx
+++ b/frontend/src/basic/RobotPage/Onboarding.tsx
@@ -164,7 +164,7 @@ const Onboarding = ({
- {robot?.found === true && slot?.lastShortAlias != null ? (
+ {robot?.found && Boolean(slot?.lastShortAlias) ? (
{t('Welcome back!')}
diff --git a/frontend/src/basic/RobotPage/TokenInput.tsx b/frontend/src/basic/RobotPage/TokenInput.tsx
index 83f226c0..192d8fad 100644
--- a/frontend/src/basic/RobotPage/TokenInput.tsx
+++ b/frontend/src/basic/RobotPage/TokenInput.tsx
@@ -71,7 +71,7 @@ const TokenInput = ({
{
systemClient.copyToClipboard(inputToken);
setShowCopied(true);
diff --git a/frontend/src/components/Dialogs/Coordinator.tsx b/frontend/src/components/Dialogs/Coordinator.tsx
index 288094b4..8a3b977d 100644
--- a/frontend/src/components/Dialogs/Coordinator.tsx
+++ b/frontend/src/components/Dialogs/Coordinator.tsx
@@ -414,12 +414,14 @@ const CoordinatorDialog = ({ open = false, onClose, network, shortAlias }: Props
>
)}
- {coordinator?.info?.notice_severity != null &&
+ {Boolean(coordinator?.info?.notice_severity) &&
coordinator?.info?.notice_severity !== 'none' && (
-
+
{t('Coordinator Notice')}
-
+
)}
@@ -478,13 +480,13 @@ const CoordinatorDialog = ({ open = false, onClose, network, shortAlias }: Props
)}
- {coordinator?.loadingInfo ? (
+ {Boolean(coordinator?.loadingInfo) ? (
- ) : coordinator?.info !== undefined ? (
+ ) : Boolean(coordinator?.info) ? (
- {coordinator?.policies !== undefined && (
+ {Boolean(coordinator?.policies) && (
{
diff --git a/frontend/src/components/Dialogs/Profile.tsx b/frontend/src/components/Dialogs/Profile.tsx
index 3b109b39..0c185245 100644
--- a/frontend/src/components/Dialogs/Profile.tsx
+++ b/frontend/src/components/Dialogs/Profile.tsx
@@ -83,7 +83,7 @@ const ProfileDialog = ({ open = false, baseUrl, onClose }: Props): JSX.Element =
diff --git a/frontend/src/components/MakerForm/MakerForm.tsx b/frontend/src/components/MakerForm/MakerForm.tsx
index 0a8a719e..8844508d 100644
--- a/frontend/src/components/MakerForm/MakerForm.tsx
+++ b/frontend/src/components/MakerForm/MakerForm.tsx
@@ -93,7 +93,7 @@ const MakerForm = ({
useEffect(() => {
const slot = garage.getSlot();
- if (slot?.token != null) void federation.fetchRobot(garage, slot?.token);
+ if (Boolean(slot?.token)) void federation.fetchRobot(garage, slot?.token);
}, [garage.currentSlot]);
useEffect(() => {
@@ -287,7 +287,7 @@ const MakerForm = ({
const handleCreateOrder = function (): void {
const slot = garage.getSlot();
- if (slot?.activeShortAlias != null) {
+ if (Boolean(slot?.activeShortAlias)) {
setBadRequest(t('You are already maker of an active order'));
return;
}
diff --git a/frontend/src/components/OrderDetails/index.tsx b/frontend/src/components/OrderDetails/index.tsx
index d913801d..ae994b0c 100644
--- a/frontend/src/components/OrderDetails/index.tsx
+++ b/frontend/src/components/OrderDetails/index.tsx
@@ -40,7 +40,6 @@ import type Coordinator from '../../models';
import { statusBadgeColor, pn, amountToString, computeSats } from '../../utils';
import TakeButton from './TakeButton';
import { F2fMapDialog } from '../Dialogs';
-import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
import { type UseFederationStoreType, FederationContext } from '../../contexts/FederationContext';
import { type Order } from '../../models';
@@ -62,7 +61,6 @@ const OrderDetails = ({
}: OrderDetailsProps): JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
- const { hostUrl } = useContext(AppContext);
const { federation } = useContext(FederationContext);
const { orderUpdatedAt } = useContext(GarageContext);
const [coordinator] = useState(federation.getCoordinator(shortAlias));
diff --git a/frontend/src/components/RobotInfo/index.tsx b/frontend/src/components/RobotInfo/index.tsx
index bb93dc8d..e01ad85c 100644
--- a/frontend/src/components/RobotInfo/index.tsx
+++ b/frontend/src/components/RobotInfo/index.tsx
@@ -203,7 +203,7 @@ const RobotInfo: React.FC = ({ coordinator, onClose }: Props) => {
- {robot?.tgEnabled === true ? (
+ {Boolean(robot?.tgEnabled) ? (
{t('Telegram enabled')}
@@ -241,7 +241,7 @@ const RobotInfo: React.FC = ({ coordinator, onClose }: Props) => {
{
- setStealthInvoice(!(robot?.stealthInvoices === true));
+ setStealthInvoice(!Boolean(robot?.stealthInvoices));
}}
/>
}
diff --git a/frontend/src/components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx b/frontend/src/components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx
index 47a3b737..0acdb224 100644
--- a/frontend/src/components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx
+++ b/frontend/src/components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx
@@ -88,7 +88,7 @@ const EncryptedTurtleChat: React.FC = ({
const loadMessages: () => void = () => {
const shortAlias = garage.getSlot()?.activeShortAlias;
- if (!(shortAlias == null)) return;
+ if (!shortAlias) return;
const { url, basePath } = federation
.getCoordinator(shortAlias)
@@ -123,7 +123,7 @@ const EncryptedTurtleChat: React.FC = ({
const onMessage = (dataFromServer: ServerMessage): void => {
const robot = garage.getSlot();
- if (robot != null && dataFromServer != null) {
+ if (robot && dataFromServer != null) {
// If we receive an encrypted message
if (dataFromServer.message.substring(0, 27) === `-----BEGIN PGP MESSAGE-----`) {
void decryptMessage(
@@ -178,8 +178,11 @@ const EncryptedTurtleChat: React.FC = ({
};
const onButtonClicked = (e: React.FormEvent): void => {
- const robot = garage.getSlot();
- if (robot?.token !== undefined && value.includes(robot.token)) {
+ const robot = garage.getSlot()?.getRobot();
+
+ if (!robot) return;
+
+ if (robot?.token && value.includes(robot.token)) {
alert(
`Aye! You just sent your own robot robot.token to your peer in chat, that's a catastrophic idea! So bad your message was blocked.`,
);
@@ -199,7 +202,7 @@ const EncryptedTurtleChat: React.FC = ({
order_id: orderId,
offset: lastIndex,
},
- { tokenSHA256: robot?.tokenSHA256 },
+ { tokenSHA256: robot?.tokenSHA256 ?? '' },
)
.then((response) => {
if (response != null) {
@@ -215,7 +218,7 @@ const EncryptedTurtleChat: React.FC = ({
});
}
// Else if message is not empty send message
- else if (value !== '' && robot?.pubKey != null) {
+ else if (value !== '' && Boolean(robot?.pubKey)) {
setWaitingEcho(true);
setLastSent(value);
encryptMessage(value, robot?.pubKey, peerPubKey ?? '', robot?.encPrivKey, robot?.token)
diff --git a/frontend/src/components/TradeBox/index.tsx b/frontend/src/components/TradeBox/index.tsx
index 0d60fb33..f16b6d9d 100644
--- a/frontend/src/components/TradeBox/index.tsx
+++ b/frontend/src/components/TradeBox/index.tsx
@@ -156,7 +156,7 @@ const TradeBox = ({ baseUrl, onStartAgain }: TradeBoxProps): JSX.Element => {
const renewOrder = function (): void {
const currentOrder = garage.getSlot()?.order;
- if (currentOrder != null) {
+ if (Boolean(currentOrder)) {
const body = {
type: currentOrder.type,
currency: currentOrder.currency,
@@ -362,7 +362,7 @@ const TradeBox = ({ baseUrl, onStartAgain }: TradeBoxProps): JSX.Element => {
// Effect on Order Status change (used for WebLN)
useEffect(() => {
const currentOrder = garage.getSlot()?.order;
- if (currentOrder != null && currentOrder?.status !== lastOrderStatus) {
+ if (currentOrder && currentOrder?.status !== lastOrderStatus) {
setLastOrderStatus(currentOrder.status);
void handleWebln(currentOrder);
}
@@ -380,7 +380,7 @@ const TradeBox = ({ baseUrl, onStartAgain }: TradeBoxProps): JSX.Element => {
titleIcon: () => <>>,
};
- if (order == null) return baseContract;
+ if (!order) return baseContract;
const status = order.status;
const isBuyer = order.is_buyer;
diff --git a/frontend/src/contexts/FederationContext.ts b/frontend/src/contexts/FederationContext.ts
index 19ace65d..4a5ff4f0 100644
--- a/frontend/src/contexts/FederationContext.ts
+++ b/frontend/src/contexts/FederationContext.ts
@@ -89,26 +89,24 @@ export const useFederationStore = (): UseFederationStoreType => {
useEffect(() => {
// On bitcoin network change we reset book, limits and federation info and fetch everything again
- setFederation(() => {
- const newFed = initialFederationContext.federation;
- newFed.registerHook('onFederationReady', () => {
- setCoordinatorUpdatedAt(new Date().toISOString());
- });
- newFed.registerHook('onCoordinatorUpdate', () => {
- setFederationUpdatedAt(new Date().toISOString());
- });
- void newFed.start(origin, settings, hostUrl);
- return newFed;
+ const newFed = initialFederationContext.federation;
+ newFed.registerHook('onFederationReady', () => {
+ setCoordinatorUpdatedAt(new Date().toISOString());
});
+ newFed.registerHook('onCoordinatorUpdate', () => {
+ setFederationUpdatedAt(new Date().toISOString());
+ });
+ void newFed.start(origin, settings, hostUrl);
+ setFederation(newFed);
}, [settings.network, torStatus]);
- const onOrderReceived = (order: any): void => {
- if (order?.bad_request !== undefined) {
+ const onOrderReceived = (order: Order): void => {
+ if (order?.bad_request) {
setBadOrder(order.bad_request);
setDelay(99999999);
- garage.updateOrder(undefined);
+ garage.updateOrder(null);
}
- if (order?.id != null) {
+ if (order?.id) {
setDelay(
order.status >= 0 && order.status <= 18
? page === 'order'
@@ -116,7 +114,7 @@ export const useFederationStore = (): UseFederationStoreType => {
: statusToDelay[order.status] * 5 // If user is not looking at "order" tab, refresh less often.
: 99999999,
);
- garage.updateOrder(order as Order);
+ garage.updateOrder(order);
setBadOrder(undefined);
}
};
@@ -124,12 +122,12 @@ export const useFederationStore = (): UseFederationStoreType => {
const fetchCurrentOrder = (): void => {
const activeSlot = garage.getSlot();
const robot = activeSlot?.getRobot(activeSlot?.activeShortAlias ?? '');
- if (robot != null && activeSlot?.activeShortAlias != null) {
- const coordinator = federation.getCoordinator(activeSlot?.activeShortAlias);
+ if (robot?.activeOrderId && activeSlot?.activeShortAlias) {
+ const coordinator = federation.getCoordinator(activeSlot?.activeShortAlias ?? '');
coordinator
- .fetchOrder(robot.activeOrderId, robot)
+ ?.fetchOrder(robot.activeOrderId, robot)
.then((order) => {
- onOrderReceived(order);
+ onOrderReceived(order as Order);
})
.finally(() => {
setTimer(setTimeout(fetchCurrentOrder, delay));
@@ -147,18 +145,18 @@ export const useFederationStore = (): UseFederationStoreType => {
};
}, []);
+ useEffect(() => {
+ if (page === 'offers') void federation.updateBook();
+ }, [page]);
+
useEffect(() => {
const slot = garage.getSlot();
const robot = slot?.getRobot();
- if (robot != null && garage.currentSlot != null) {
+ if (robot && garage.currentSlot) {
if (open.profile && Boolean(slot?.hashId) && slot?.token) {
void federation.fetchRobot(garage, slot?.token); // refresh/update existing robot
- } else if (
- robot.token !== undefined &&
- robot.encPrivKey !== undefined &&
- robot.pubKey !== undefined
- ) {
+ } else if (robot.token && robot.encPrivKey && robot.pubKey) {
void federation.fetchRobot(garage, robot.token); // create new robot with existing token and keys (on network and coordinator change)
}
}
diff --git a/frontend/src/models/Coordinator.model.ts b/frontend/src/models/Coordinator.model.ts
index 8b3548fd..ae745756 100644
--- a/frontend/src/models/Coordinator.model.ts
+++ b/frontend/src/models/Coordinator.model.ts
@@ -141,7 +141,6 @@ export class Coordinator {
this.url = String(this[settings.network][origin]);
this.basePath = '';
}
-
void this.update(() => {
onStarted(this.shortAlias);
});
@@ -157,14 +156,20 @@ export class Coordinator {
this.loadInfo(onDataLoad);
};
- generateAllMakerAvatars = (data: [PublicOrder]) => {
+ updateBook = async (onUpdate: (shortAlias: string) => void = () => {}): Promise => {
+ this.loadBook(() => {
+ onUpdate(this.shortAlias);
+ });
+ };
+
+ generateAllMakerAvatars = async (data: [PublicOrder]): Promise => {
for (const order of data) {
- robohash.generate(order.maker_hash_id, 'small');
+ void robohash.generate(order.maker_hash_id, 'small');
}
};
loadBook = (onDataLoad: () => void = () => {}): void => {
- if (this.enabled === false) return;
+ if (!this.enabled) return;
if (this.loadingBook) return;
this.loadingBook = true;
@@ -172,12 +177,12 @@ export class Coordinator {
apiClient
.get(this.url, `${this.basePath}/api/book/`)
.then((data) => {
- if (data.not_found === undefined) {
+ if (!data?.not_found) {
this.book = (data as PublicOrder[]).map((order) => {
order.coordinatorShortAlias = this.shortAlias;
return order;
});
- this.generateAllMakerAvatars(data);
+ void this.generateAllMakerAvatars(data);
onDataLoad();
}
})
@@ -190,7 +195,7 @@ export class Coordinator {
};
loadLimits = (onDataLoad: () => void = () => {}): void => {
- if (this.enabled === false) return;
+ if (!this.enabled) return;
if (this.loadingLimits) return;
this.loadingLimits = true;
@@ -218,7 +223,7 @@ export class Coordinator {
};
loadInfo = (onDataLoad: () => void = () => {}): void => {
- if (this.enabled === false) return;
+ if (!this.enabled) return;
if (this.loadingInfo) return;
this.loadingInfo = true;
@@ -275,7 +280,7 @@ export class Coordinator {
};
fecthRobot = async (garage: Garage, token: string): Promise => {
- if (this.enabled === false) return null;
+ if (!this.enabled) return null;
const robot = garage?.getSlot(token)?.getRobot() ?? null;
@@ -324,7 +329,7 @@ export class Coordinator {
};
fetchOrder = async (orderId: number, robot: Robot): Promise => {
- if (this.enabled === false) return null;
+ if (!this.enabled) return null;
if (!(robot.token != null)) return null;
const authHeaders = robot.getAuthHeaders();
@@ -355,7 +360,7 @@ export class Coordinator {
bad_invoice?: string;
successful_withdrawal?: boolean;
}> => {
- if (this.enabled === false) return null;
+ if (!this.enabled) return null;
const robot = garage.getSlot(index)?.getRobot();
@@ -377,7 +382,7 @@ export class Coordinator {
};
fetchStealth = async (wantsStealth: boolean, garage: Garage, index: string): Promise => {
- if (this.enabled === false) return null;
+ if (!this.enabled) return null;
const robot = garage?.getSlot(index)?.getRobot();
diff --git a/frontend/src/models/Federation.model.ts b/frontend/src/models/Federation.model.ts
index c5e1e2a6..99fcbd09 100644
--- a/frontend/src/models/Federation.model.ts
+++ b/frontend/src/models/Federation.model.ts
@@ -68,7 +68,6 @@ export class Federation {
this.onCoordinatorSaved(shortAlias);
};
this.loading = true;
- // Object.values(this.coordinators).forEach(async (coor) => {
for (const coor of Object.values(this.coordinators)) {
await coor.start(origin, settings, hostUrl, onCoordinatorStarted);
}
@@ -76,7 +75,6 @@ export class Federation {
update = async (): Promise => {
this.loading = false;
- // Object.values(this.coordinators).forEach(async (coor) => {
for (const coor of Object.values(this.coordinators)) {
await coor.update(() => {
this.onCoordinatorSaved(coor.shortAlias);
@@ -84,6 +82,15 @@ export class Federation {
}
};
+ updateBook = async (): Promise => {
+ this.loading = false;
+ for (const coor of Object.values(this.coordinators)) {
+ await coor.updateBook(() => {
+ this.onCoordinatorSaved(coor.shortAlias);
+ });
+ }
+ };
+
updateExchange = (): void => {
this.exchange.info = updateExchangeInfo(this);
};
diff --git a/frontend/src/models/Garage.model.ts b/frontend/src/models/Garage.model.ts
index f48c0bb2..af5c9299 100644
--- a/frontend/src/models/Garage.model.ts
+++ b/frontend/src/models/Garage.model.ts
@@ -58,7 +58,7 @@ class Garage {
if (slotsDump !== '') {
const rawSlots = JSON.parse(slotsDump);
Object.values(rawSlots).forEach((rawSlot: Record) => {
- if (rawSlot?.token != null) {
+ if (rawSlot?.token) {
this.createSlot(rawSlot?.token);
Object.keys(rawSlot.robots).forEach((shortAlias) => {
const rawRobot = rawSlot.robots[shortAlias];
@@ -76,7 +76,7 @@ class Garage {
// Slots
getSlot: (token?: string) => Slot | null = (token) => {
const currentToken = token ?? this.currentSlot;
- return currentToken != null ? this.slots[currentToken] ?? null : null;
+ return currentToken ? this.slots[currentToken] ?? null : null;
};
createSlot: (token: string) => Slot | null = (token) => {
@@ -89,7 +89,7 @@ class Garage {
deleteSlot: (token?: string) => void = (token) => {
const targetIndex = token ?? this.currentSlot;
- if (targetIndex != null) {
+ if (targetIndex) {
Reflect.deleteProperty(this.slots, targetIndex);
this.currentSlot = null;
this.triggerHook('onRobotUpdate');
@@ -103,7 +103,7 @@ class Garage {
token,
) => {
const slot = this.getSlot(token);
- if (attributes != null) {
+ if (attributes) {
if (attributes.copiedToken !== undefined) slot?.setCopiedToken(attributes.copiedToken);
this.triggerHook('onRobotUpdate');
}
@@ -116,7 +116,7 @@ class Garage {
shortAlias,
attributes,
) => {
- if (token === null || shortAlias === null) return;
+ if (!token || !shortAlias) return;
let slot = this.getSlot(token);
@@ -132,18 +132,22 @@ class Garage {
};
// Orders
- updateOrder: (order: Order) => void = (order) => {
+ updateOrder: (order: Order | null) => void = (order) => {
const slot = this.getSlot();
if (slot != null) {
- const updatedOrder = slot.order ?? null;
- if (updatedOrder !== null && updatedOrder.id === order.id) {
- Object.assign(updatedOrder, order);
- slot.order = updatedOrder;
+ if (order !== null) {
+ const updatedOrder = slot.order ?? null;
+ if (updatedOrder !== null && updatedOrder.id === order.id) {
+ Object.assign(updatedOrder, order);
+ slot.order = updatedOrder;
+ } else {
+ slot.order = order;
+ }
+ if (slot.order?.is_participant) {
+ slot.activeShortAlias = order.shortAlias;
+ }
} else {
- slot.order = order;
- }
- if (slot.order?.is_participant) {
- slot.activeShortAlias = order.shortAlias;
+ slot.order = null;
}
this.triggerHook('onOrderUpdate');
this.save();
diff --git a/frontend/src/models/Slot.model.ts b/frontend/src/models/Slot.model.ts
index 6b1754ad..ea38dcce 100644
--- a/frontend/src/models/Slot.model.ts
+++ b/frontend/src/models/Slot.model.ts
@@ -10,8 +10,8 @@ class Slot {
this.hashId = sha256(sha256(this.token));
this.nickname = generate_roboname(this.hashId);
// trigger RoboHash avatar generation in webworker and store in RoboHash class cache.
- robohash.generate(this.hashId, 'small');
- robohash.generate(this.hashId, 'large');
+ void robohash.generate(this.hashId, 'small');
+ void robohash.generate(this.hashId, 'large');
this.robots = {};
this.order = null;
@@ -35,11 +35,11 @@ class Slot {
};
getRobot = (shortAlias?: string): Robot | null => {
- if (shortAlias != null) {
+ if (shortAlias) {
return this.robots[shortAlias];
- } else if (this.activeShortAlias !== null && this.robots[this.activeShortAlias] != null) {
+ } else if (this.activeShortAlias !== null && this.robots[this.activeShortAlias]) {
return this.robots[this.activeShortAlias];
- } else if (this.lastShortAlias !== null && this.robots[this.lastShortAlias] != null) {
+ } else if (this.lastShortAlias !== null && this.robots[this.lastShortAlias]) {
return this.robots[this.lastShortAlias];
} else if (Object.values(this.robots).length > 0) {
return Object.values(this.robots)[0];