diff --git a/app/components/DeviceVerify/DeviceVerify.tsx b/app/components/DeviceVerify/DeviceVerify.tsx
index 5ba702f..71c541d 100644
--- a/app/components/DeviceVerify/DeviceVerify.tsx
+++ b/app/components/DeviceVerify/DeviceVerify.tsx
@@ -1,6 +1,8 @@
import { useRosettaColors } from "@/app/hooks/useRosettaColors";
+import { useDeviceResolve } from "@/app/providers/DeviceProvider/useDeviceResolve";
import { DeviceEntry } from "@/app/providers/ProtocolProvider/protocol/packets/packet.device.list";
import { Box, Button, Divider, Flex, Text } from "@mantine/core";
+import { modals } from "@mantine/modals";
export interface DeviceVerifyProps {
device: DeviceEntry;
@@ -8,6 +10,24 @@ export interface DeviceVerifyProps {
export function DeviceVerify(props: DeviceVerifyProps) {
const colors = useRosettaColors();
+ const { accept, decline } = useDeviceResolve();
+
+ const acceptConfirmModal = () => {
+ modals.openConfirmModal({
+ title: 'Accept new device',
+ children: (
+
+ Are you sure you want to accept this device? This will allow it to access your account.
+
+ ),
+ centered: true,
+ labels: { confirm: 'Accept', cancel: 'Cancel' },
+ cancelProps: { color: 'gray', style: {
+ outline: 'none'
+ } },
+ onConfirm: () => accept(props.device.deviceId),
+ });
+ }
return (
@@ -17,8 +37,8 @@ export function DeviceVerify(props: DeviceVerifyProps) {
New login from {props.device.deviceName} ({props.device.deviceOs})
-
-
+
+
diff --git a/app/hooks/useDeviceMessage.ts b/app/hooks/useDeviceMessage.ts
index 4289d11..3db8360 100644
--- a/app/hooks/useDeviceMessage.ts
+++ b/app/hooks/useDeviceMessage.ts
@@ -6,22 +6,22 @@ import { dotCenterIfNeeded } from "../utils/utils";
const messageTemplate = `
**Attempt to login from a new device**
-We detected a login to your account from **{os}** a new device **by seed phrase**. If this was you, you can safely ignore this message.
+We detected a login to your account from **{ip}** a new device **by seed phrase**. If this was you, you can safely ignore this message.
-**OS:** {os}
+**Arch:** {os}
**IP:** {ip}
**Device:** {device}
-**ID:** {deviceId}`
+**ID:** {deviceId}`;
export function useDeviceMessage() {
const send = useSendSystemMessage("safe");
usePacket(0x09, (packet: PacketDeviceNew) => {
send(messageTemplate
- .replace("{ip}", packet.getIpAddress())
- .replace("{device}", packet.getDevice().deviceName)
- .replace("{os}", packet.getDevice().deviceOs)
- .replace("{deviceId}", dotCenterIfNeeded(packet.getDevice().deviceId, 12, 4))
+ .replaceAll("{ip}", packet.getIpAddress())
+ .replaceAll("{device}", packet.getDevice().deviceName)
+ .replaceAll("{os}", packet.getDevice().deviceOs)
+ .replaceAll("{deviceId}", dotCenterIfNeeded(packet.getDevice().deviceId, 12, 4))
);
}, []);
}
\ No newline at end of file
diff --git a/app/providers/DeviceProvider/useDeviceResolve.ts b/app/providers/DeviceProvider/useDeviceResolve.ts
new file mode 100644
index 0000000..70e430f
--- /dev/null
+++ b/app/providers/DeviceProvider/useDeviceResolve.ts
@@ -0,0 +1,28 @@
+import { PacketDeviceResolve, Solution } from "../ProtocolProvider/protocol/packets/packet.device.resolve";
+import { useSender } from "../ProtocolProvider/useSender"
+
+/**
+ * Хук для отклонения или принятия устройств
+ */
+export function useDeviceResolve() {
+ const send = useSender();
+
+ const accept = (deviceId: string) => {
+ const packet = new PacketDeviceResolve();
+ packet.setDeviceId(deviceId);
+ packet.setSolution(Solution.ACCEPT);
+ send(packet);
+ }
+
+ const decline = (deviceId: string) => {
+ const packet = new PacketDeviceResolve();
+ packet.setDeviceId(deviceId);
+ packet.setSolution(Solution.DECLINE);
+ send(packet);
+ }
+
+ return {
+ accept,
+ decline
+ }
+}
\ No newline at end of file
diff --git a/app/providers/ProtocolProvider/protocol/packets/packet.device.resolve.ts b/app/providers/ProtocolProvider/protocol/packets/packet.device.resolve.ts
new file mode 100644
index 0000000..265bce7
--- /dev/null
+++ b/app/providers/ProtocolProvider/protocol/packets/packet.device.resolve.ts
@@ -0,0 +1,54 @@
+import Packet from "../packet";
+import Stream from "../stream";
+
+/**
+ * Решение по устройству при верификации
+ * Отклонить или принять
+ */
+export enum Solution {
+ DECLINE,
+ ACCEPT
+}
+
+/**
+ * Отправляется клиентом при решении по устройству
+ */
+export class PacketDeviceResolve extends Packet {
+
+ private deviceId: string = "";
+ private solution: Solution = Solution.DECLINE;
+
+ public getPacketId(): number {
+ return 0x18;
+ }
+
+ public _receive(stream: Stream): void {
+ this.deviceId = stream.readString();
+ this.solution = stream.readInt8();
+ }
+
+ public _send(): Promise | Stream {
+ const stream = new Stream();
+ stream.writeInt16(this.getPacketId());
+ stream.writeString(this.deviceId);
+ stream.writeInt8(this.solution);
+ return stream;
+ }
+
+ public getDeviceId(): string {
+ return this.deviceId;
+ }
+
+ public getSolution(): Solution {
+ return this.solution;
+ }
+
+ public setDeviceId(deviceId: string): void {
+ this.deviceId = deviceId;
+ }
+
+ public setSolution(solution: Solution): void {
+ this.solution = solution;
+ }
+
+}
\ No newline at end of file
diff --git a/app/providers/ProtocolProvider/protocol/protocol.ts b/app/providers/ProtocolProvider/protocol/protocol.ts
index 5ae939a..a6ea06a 100644
--- a/app/providers/ProtocolProvider/protocol/protocol.ts
+++ b/app/providers/ProtocolProvider/protocol/protocol.ts
@@ -26,6 +26,7 @@ import { PacketGroupLeave } from "./packets/packet.group.leave";
import { PacketGroupBan } from "./packets/packet.group.ban";
import { PacketDeviceNew } from "./packets/packet.device.new";
import { PacketDeviceList } from "./packets/packet.device.list";
+import { PacketDeviceResolve } from "./packets/packet.device.resolve";
export default class Protocol extends EventEmitter {
private serverAddress: string;
@@ -122,6 +123,7 @@ export default class Protocol extends EventEmitter {
this._supportedPackets.set(0x15, new PacketGroupLeave());
this._supportedPackets.set(0x16, new PacketGroupBan());
this._supportedPackets.set(0x17, new PacketDeviceList());
+ this._supportedPackets.set(0x18, new PacketDeviceResolve());
}
private _findWaiters(packetId: number): ((packet: Packet) => void)[] {
@@ -133,6 +135,11 @@ export default class Protocol extends EventEmitter {
public connect() {
this.socket = new WebSocket(this.serverAddress);
+ /**
+ * Сбрасываем флаг ручного закрытия соединения
+ * при подключении
+ */
+ this.isManuallyClosed = false;
this.socket.addEventListener('open', () => {
//this.reconnectTryings = 0;
diff --git a/app/views/DeviceConfirm/DeviceConfirm.tsx b/app/views/DeviceConfirm/DeviceConfirm.tsx
index d184089..e17a113 100644
--- a/app/views/DeviceConfirm/DeviceConfirm.tsx
+++ b/app/views/DeviceConfirm/DeviceConfirm.tsx
@@ -8,6 +8,8 @@ import { useNavigate } from "react-router-dom";
import animationData from './inbox.json'
import { AnimatedButton } from "@/app/components/AnimatedButton/AnimatedButton";
import { useLogout } from "@/app/providers/AccountProvider/useLogout";
+import { usePacket } from "@/app/providers/ProtocolProvider/usePacket";
+import { PacketDeviceResolve, Solution } from "@/app/providers/ProtocolProvider/protocol/packets/packet.device.resolve";
export function DeviceConfirm() {
const protocolState = useProtocolState();
@@ -19,6 +21,15 @@ export function DeviceConfirm() {
navigate('/main');
}
}, [protocolState]);
+
+ usePacket(0x18, (packet : PacketDeviceResolve) => {
+ /**
+ * Если решение отклонено, то выходим из аккаунта
+ */
+ if(packet.getSolution() == Solution.DECLINE){
+ logout();
+ }
+ }, []);
return (