diff --git a/apps/shinkai-visor/src/components/inboxes/inboxes.css b/apps/shinkai-visor/src/components/inboxes/inboxes.css
deleted file mode 100644
index 75b885059..000000000
--- a/apps/shinkai-visor/src/components/inboxes/inboxes.css
+++ /dev/null
@@ -1,7 +0,0 @@
-#shinkai-popup-root {
- .inbox-id-container {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-}
diff --git a/apps/shinkai-visor/src/components/inboxes/inboxes.tsx b/apps/shinkai-visor/src/components/inboxes/inboxes.tsx
index 5674e87b5..85d7e46bc 100644
--- a/apps/shinkai-visor/src/components/inboxes/inboxes.tsx
+++ b/apps/shinkai-visor/src/components/inboxes/inboxes.tsx
@@ -1,5 +1,3 @@
-import './inboxes.css';
-
import { isJobInbox } from '@shinkai_network/shinkai-message-ts/utils';
import { useAgents } from '@shinkai_network/shinkai-node-state/lib/queries/getAgents/useGetAgents';
import { useGetInboxes } from '@shinkai_network/shinkai-node-state/lib/queries/getInboxes/useGetInboxes';
@@ -11,6 +9,7 @@ import { useHistory } from 'react-router-dom';
import { useAuth } from '../../store/auth/auth';
import { EmptyAgents } from '../empty-agents/empty-agents';
import { EmptyInboxes } from '../empty-inboxes/empty-inboxes';
+import { Header } from '../header/header';
import { Button } from '../ui/button';
import { ScrollArea } from '../ui/scroll-area';
@@ -46,13 +45,12 @@ export const Inboxes = () => {
return (
-
-
-
+ }
+ title={
-
-
-
+ }
+ />
{!agents?.length ? (
) : !inboxIds?.length ? (
diff --git a/apps/shinkai-visor/src/components/nav/nav.tsx b/apps/shinkai-visor/src/components/nav/nav.tsx
index dfea03a36..a7f65b856 100644
--- a/apps/shinkai-visor/src/components/nav/nav.tsx
+++ b/apps/shinkai-visor/src/components/nav/nav.tsx
@@ -1,4 +1,14 @@
-import { ArrowLeft, Bot, Inbox, LogOut, Menu, MessageCircle, Workflow, X } from 'lucide-react';
+import {
+ ArrowLeft,
+ Bot,
+ Inbox,
+ LogOut,
+ Menu,
+ MessageCircle,
+ Settings,
+ Workflow,
+ X,
+} from 'lucide-react';
import { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { useHistory, useLocation } from 'react-router-dom';
@@ -24,6 +34,7 @@ enum MenuOption {
Agents = 'agents',
AddAgent = 'add-agent',
CreateJob = 'create-job',
+ Settings = 'settings',
Logout = 'logout',
}
@@ -31,20 +42,25 @@ export default function NavBar() {
const history = useHistory();
const location = useLocation();
const setLogout = useAuth((state) => state.setLogout);
+ const auth = useAuth((state) => state.auth);
const uiContainer = useUIContainer((state) => state.uiContainer);
const [isMenuOpened, setMenuOpened] = useState(false);
- const isRootPage = ['/inboxes', '/agents'].includes(
- location.pathname
- );
+ const isRootPage = [
+ '/inboxes',
+ '/agents',
+ '/settings',
+ '/nodes/connect/method/quick-start',
+ ].includes(location.pathname);
const goBack = () => {
history.goBack();
- }
+ };
const logout = (): void => {
setLogout();
};
const onClickMenuOption = (key: MenuOption) => {
+ console.log('menu option', key, MenuOption.Settings);
switch (key) {
case MenuOption.Inbox:
history.push('/inboxes');
@@ -61,6 +77,9 @@ export default function NavBar() {
case MenuOption.AddAgent:
history.push('/agents/add');
break;
+ case MenuOption.Settings:
+ history.push('/settings');
+ break;
case MenuOption.Logout:
logout();
break;
@@ -71,95 +90,109 @@ export default function NavBar() {
return (
);
diff --git a/apps/shinkai-visor/src/components/popup/popup.tsx b/apps/shinkai-visor/src/components/popup/popup.tsx
index 5b730bbdc..203f6fab5 100644
--- a/apps/shinkai-visor/src/components/popup/popup.tsx
+++ b/apps/shinkai-visor/src/components/popup/popup.tsx
@@ -15,13 +15,17 @@ import { useGlobalPopupChromeMessage } from '../../hooks/use-global-popup-chrome
import { langMessages, locale } from '../../lang/intl';
import { useAuth } from '../../store/auth/auth';
import { AddAgent } from '../add-agent/add-agent';
-import { AddNode } from '../add-node/add-node';
import { Agents } from '../agents/agents';
import { AnimatedRoute } from '../animated-route/animated-routed';
+import { ConnectMethodQrCode } from '../connect-method-qr-code/connec-method-qr-code';
+import { ConnectMethodQuickStart } from '../connect-method-quick-start/connect-method-quick-start';
+import { ConnectMethodRestoreConnection } from '../connect-method-restore-connection/connect-method-restore-connection';
import { CreateInbox } from '../create-inbox/create-inbox';
import { CreateJob } from '../create-job/create-job';
+import { ExportConnection } from '../export-connection/export-connection';
import { Inbox } from '../inbox/inbox';
import { Inboxes } from '../inboxes/inboxes';
+import { Settings } from '../settings/settings';
import { SplashScreen } from '../splash-screen/splash-screen';
import Welcome from '../welcome/welcome';
import { WithNav } from '../with-nav/with-nav';
@@ -31,9 +35,10 @@ export const Popup = () => {
const auth = useAuth((state) => state.auth);
const location = useLocation();
const [popupVisibility] = useGlobalPopupChromeMessage();
-
+
useEffect(() => {
const isAuthenticated = !!auth;
+ console.log('isAuth', isAuthenticated, auth);
if (isAuthenticated) {
ApiConfig.getInstance().setEndpoint(auth.node_address);
history.replace('/inboxes');
@@ -42,6 +47,9 @@ export const Popup = () => {
history.replace('/welcome');
}
}, [history, auth]);
+ useEffect(() => {
+ console.log('location', location.pathname);
+ }, [location]);
return (
{popupVisibility && (
@@ -63,18 +71,25 @@ export const Popup = () => {
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -101,6 +116,16 @@ export const Popup = () => {
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/shinkai-visor/src/components/settings/settings.tsx b/apps/shinkai-visor/src/components/settings/settings.tsx
new file mode 100644
index 000000000..c6f45f925
--- /dev/null
+++ b/apps/shinkai-visor/src/components/settings/settings.tsx
@@ -0,0 +1,27 @@
+import { FileKey, SettingsIcon } from 'lucide-react';
+import { FormattedMessage } from 'react-intl';
+import { useHistory } from 'react-router';
+
+import { Header } from '../header/header';
+import { Button } from '../ui/button';
+
+export const Settings = () => {
+ const history = useHistory();
+ const exportConnection = () => {
+ history.push('settings/export-connection');
+ };
+ return (
+
+
}
+ title={
}
+ />
+
+
+
+
+ );
+};
diff --git a/apps/shinkai-visor/src/components/ui/error-message.tsx b/apps/shinkai-visor/src/components/ui/error-message.tsx
index f075ad541..8f4ccaeca 100644
--- a/apps/shinkai-visor/src/components/ui/error-message.tsx
+++ b/apps/shinkai-visor/src/components/ui/error-message.tsx
@@ -1,8 +1,8 @@
const ErrorMessage = ({ message }: { message: string }) => {
return (
-
+
Error:
- {message}
+ {message}
);
};
diff --git a/apps/shinkai-visor/src/components/ui/form.tsx b/apps/shinkai-visor/src/components/ui/form.tsx
index add95a55e..180e21ba9 100644
--- a/apps/shinkai-visor/src/components/ui/form.tsx
+++ b/apps/shinkai-visor/src/components/ui/form.tsx
@@ -78,7 +78,7 @@ const FormItem = React.forwardRef<
return (
-
+
)
})
diff --git a/apps/shinkai-visor/src/components/ui/input.tsx b/apps/shinkai-visor/src/components/ui/input.tsx
index b8277252f..3a87dc969 100644
--- a/apps/shinkai-visor/src/components/ui/input.tsx
+++ b/apps/shinkai-visor/src/components/ui/input.tsx
@@ -9,7 +9,7 @@ const Input = React.forwardRef
(
return (
-
diff --git a/apps/shinkai-visor/src/components/with-nav/with-nav.tsx b/apps/shinkai-visor/src/components/with-nav/with-nav.tsx
index f9adb2430..f2b1dd1be 100644
--- a/apps/shinkai-visor/src/components/with-nav/with-nav.tsx
+++ b/apps/shinkai-visor/src/components/with-nav/with-nav.tsx
@@ -4,7 +4,7 @@ import NavBar from '../nav/nav';
export const WithNav = (props: PropsWithChildren) => {
return (
-
+
diff --git a/apps/shinkai-visor/src/helpers/encryption-keys.ts b/apps/shinkai-visor/src/helpers/encryption-keys.ts
new file mode 100644
index 000000000..228e732ef
--- /dev/null
+++ b/apps/shinkai-visor/src/helpers/encryption-keys.ts
@@ -0,0 +1,34 @@
+import { generateEncryptionKeys, generateSignatureKeys } from "@shinkai_network/shinkai-message-ts/utils";
+
+export type Encryptionkeys = {
+ my_device_encryption_pk: string;
+ my_device_encryption_sk: string;
+
+ my_device_identity_pk: string;
+ my_device_identity_sk: string;
+
+ profile_encryption_pk: string;
+ profile_encryption_sk: string;
+
+ profile_identity_pk: string;
+ profile_identity_sk: string;
+};
+
+export const generateMyEncryptionKeys = async (): Promise
=> {
+ const seed = crypto.getRandomValues(new Uint8Array(32));
+ const deviceEncryptionKeys = await generateEncryptionKeys(seed);
+ const deviceSignataureKeys = await generateSignatureKeys();
+ const profileEncryptionKeys = await generateEncryptionKeys(seed);
+ const profileSignatureKeys = await generateSignatureKeys();
+
+ return {
+ my_device_encryption_pk: deviceEncryptionKeys.my_encryption_pk_string,
+ my_device_encryption_sk: deviceEncryptionKeys.my_encryption_sk_string,
+ my_device_identity_pk: deviceSignataureKeys.my_identity_pk_string,
+ my_device_identity_sk: deviceSignataureKeys.my_identity_sk_string,
+ profile_encryption_pk: profileEncryptionKeys.my_encryption_pk_string,
+ profile_encryption_sk: profileEncryptionKeys.my_encryption_sk_string,
+ profile_identity_pk: profileSignatureKeys.my_identity_pk_string,
+ profile_identity_sk: profileSignatureKeys.my_identity_sk_string,
+ }
+};
\ No newline at end of file
diff --git a/apps/shinkai-visor/src/lang/en.json b/apps/shinkai-visor/src/lang/en.json
index 9ae90733b..dcae54b72 100644
--- a/apps/shinkai-visor/src/lang/en.json
+++ b/apps/shinkai-visor/src/lang/en.json
@@ -5,7 +5,7 @@
"inbox.one": "Inbox",
"inbox.other": "Inboxes",
"setting.one": "Setting",
- "settings.other": "Settings",
+ "setting.other": "Settings",
"about": "About Shinkai",
"add-node": "Add Node",
"registration-code": "Registration Code",
@@ -54,5 +54,25 @@
"yesterday": "Yesterday",
"installed-sucessfully": "Shinkai Visor was installed sucessfully, navigate to a website and use the action button to start asking Shinkai AI",
"file-processing-alert-title": "Your file is being processed",
- "file-processing-alert-description": "It can take a few minutes"
+ "file-processing-alert-description": "It can take a few minutes",
+ "export-connection": "Export connection",
+ "generate-connection-file": "Generate connection file",
+ "passphrase": "Passphrase",
+ "confirm-passphrase": "Confirm passphrase",
+ "download": "Download",
+ "download-keep-safe-place": "Download and keep this connection file in a safe place",
+ "use-it-to-restore": "Use it with your passphrase to restore the connection to your Shinkai Node",
+ "passphrases-dont-match": "Passphrases don't match",
+ "connect-your-shinkai-node": "Connect your Shinkai Node",
+ "select-connection-method": "Select a method to connect your Shinkai Node",
+ "quick-connection-connection-method-title": "Quick connection",
+ "quick-connection-connection-method-description": "Use address to connect for first time",
+ "qr-code-connection-connection-method-title": "QR Code",
+ "qr-code-connection-connection-method-description": "Use a QR code to connect",
+ "restore-connection-connection-method-title": "Restore from connection file",
+ "restore-connection-connection-method-description": "Use a connection file and passphrase",
+ "encrypted-connection": "Encrypted connection",
+ "click-to-upload": "Click to upload or drag and drop",
+ "restore-connection": "Restore connection",
+ "did-you-connected-before": "Do you have experience using shinkai?"
}
diff --git a/apps/shinkai-visor/src/lang/es.json b/apps/shinkai-visor/src/lang/es.json
index 87dcb5b12..005ecfec9 100644
--- a/apps/shinkai-visor/src/lang/es.json
+++ b/apps/shinkai-visor/src/lang/es.json
@@ -5,7 +5,7 @@
"inbox.one": "Bandeja de entrada",
"inbox.other": "Bandejas de entrada",
"setting.one": "Configuración",
- "settings.other": "Configuraciones",
+ "setting.other": "Configuraciones",
"about": "Acerca de Shinkai",
"add-node": "Conectar nodo",
"registration-code": "Código de registración",
@@ -52,5 +52,27 @@
"empty-agents-message": "Conecta tu primer agente para comenzar a preguntar a Shinkai AI",
"today": "Hoy",
"yesterday": "Ayer",
- "installed-sucessfully": "Shinkai Visor se instaló correctamente, navega a un sitio web y usa el botón de acción para comenzar a preguntar a Shinkai AI"
+ "installed-sucessfully": "Shinkai Visor se instaló correctamente, navega a un sitio web y usa el botón de acción para comenzar a preguntar a Shinkai AI",
+ "file-processing-alert-title": "Tu archivo está siendo procesado",
+ "file-processing-alert-description": "Puede tardar unos minutos",
+ "export-connection": "Exportar conexión",
+ "generate-connection-file": "Generar archivo de conexión",
+ "passphrase": "Frase de contraseña",
+ "confirm-passphrase": "Confirmar frase de contraseña",
+ "download": "Descargar",
+ "download-keep-safe-place": "Descarga y guarda este archivo de conexión en un lugar seguro",
+ "use-it-to-restore": "Úsalo con tu frase de contraseña para restaurar la conexión a tu Nodo Shinkai",
+ "passphrases-dont-match": "Las frases de contraseña no coinciden",
+ "connect-your-shinkai-node": "Conecta tu Nodo Shinkai",
+ "select-connection-method": "Selecciona un método para conectar tu Nodo Shinkai",
+ "quick-connection-connection-method-title": "Conexión rápida",
+ "quick-connection-connection-method-description": "Usa la dirección para conectar por primera vez",
+ "qr-code-connection-connection-method-title": "Código QR",
+ "qr-code-connection-connection-method-description": "Usa un código QR para conectar",
+ "restore-connection-connection-method-title": "Restaurar desde archivo de conexión",
+ "restore-connection-connection-method-description": "Usa un archivo de conexión y frase de contraseña",
+ "encrypted-connection": "Conexión cifrada",
+ "click-to-upload": "Haz clic para subir o arrastra y suelta",
+ "restore-connection": "Restaurar conexión",
+ "did-you-connected-before": "¿Tienes experiencia usando shinkai?"
}
diff --git a/libs/shinkai-message-ts/package.json b/libs/shinkai-message-ts/package.json
index 6b0772350..3da8c28c1 100644
--- a/libs/shinkai-message-ts/package.json
+++ b/libs/shinkai-message-ts/package.json
@@ -16,7 +16,8 @@
},
"dependencies": {
"@noble/ed25519": "^2.0.0",
- "curve25519-js": "^0.0.4"
+ "curve25519-js": "^0.0.4",
+ "libsodium-wrappers-sumo": "^0.7.13"
},
"exports": {
".": {
@@ -38,6 +39,10 @@
"./wasm": {
"import": "./wasm.js",
"types": "./wasm.d.ts"
+ },
+ "./cryptography": {
+ "import": "./cryptography.js",
+ "types": "./cryptography.d.ts"
}
},
"typesVersions": {
@@ -56,6 +61,9 @@
],
"wasm": [
"wasm.d.ts"
+ ],
+ "cryptography": [
+ "cryptography.d.ts"
]
}
}
diff --git a/libs/shinkai-message-ts/src/cryptography.ts b/libs/shinkai-message-ts/src/cryptography.ts
new file mode 100644
index 000000000..84a88e71d
--- /dev/null
+++ b/libs/shinkai-message-ts/src/cryptography.ts
@@ -0,0 +1 @@
+export * from './cryptography/shinkai-encryption';
diff --git a/libs/shinkai-message-ts/src/cryptography/shinkai-encryption.test.ts b/libs/shinkai-message-ts/src/cryptography/shinkai-encryption.test.ts
new file mode 100644
index 000000000..20c14147f
--- /dev/null
+++ b/libs/shinkai-message-ts/src/cryptography/shinkai-encryption.test.ts
@@ -0,0 +1,25 @@
+import * as sodium from "libsodium-wrappers-sumo";
+
+import { decryptMessageWithPassphrase,encryptMessageWithPassphrase } from './shinkai-encryption';
+
+test("encrypt and decrypt message with passphrase", async () => {
+ await sodium.ready; // Ensure sodium is fully loaded
+
+ const originalMessage = "Hello, world!";
+ const passphrase = "my secret passphrase";
+
+ // Encrypt the message
+ const encryptedMessage = await encryptMessageWithPassphrase(
+ originalMessage,
+ passphrase
+ );
+
+ // Decrypt the message
+ const decryptedMessage = await decryptMessageWithPassphrase(
+ encryptedMessage,
+ passphrase
+ );
+
+ // The decrypted message should be the same as the original message
+ expect(decryptedMessage).toBe(originalMessage);
+});
\ No newline at end of file
diff --git a/libs/shinkai-message-ts/src/cryptography/shinkai-encryption.ts b/libs/shinkai-message-ts/src/cryptography/shinkai-encryption.ts
new file mode 100644
index 000000000..3eedbac88
--- /dev/null
+++ b/libs/shinkai-message-ts/src/cryptography/shinkai-encryption.ts
@@ -0,0 +1,78 @@
+import * as sodium from "libsodium-wrappers-sumo";
+
+export async function encryptMessageWithPassphrase(
+ message: string,
+ passphrase: string
+): Promise {
+ await sodium.ready;
+
+ const salt = sodium.randombytes_buf(16); // Use a fixed length for the salt
+ const key = sodium.crypto_pwhash(
+ 32,
+ passphrase,
+ salt,
+ sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
+ sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
+ sodium.crypto_pwhash_ALG_DEFAULT
+ );
+
+ const nonce = sodium.randombytes_buf(
+ sodium.crypto_aead_chacha20poly1305_IETF_NPUBBYTES
+ );
+ const ciphertext = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(
+ message,
+ null,
+ null,
+ nonce,
+ key
+ );
+
+ const encrypted_body =
+ sodium.to_hex(salt) + sodium.to_hex(nonce) + sodium.to_hex(ciphertext);
+ return `encrypted:${encrypted_body}`;
+}
+
+export async function decryptMessageWithPassphrase(
+ encryptedBody: string,
+ passphrase: string
+): Promise {
+ await sodium.ready;
+
+ const parts: string[] = encryptedBody.split(":");
+ if (parts[0] !== "encrypted") {
+ throw new Error("Unexpected variant");
+ }
+
+ const content = parts[1];
+ const salt = sodium.from_hex(content.slice(0, 32)); // Get the salt from the encrypted message
+ const key = sodium.crypto_pwhash(
+ 32,
+ passphrase,
+ salt,
+ sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
+ sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
+ sodium.crypto_pwhash_ALG_DEFAULT
+ );
+
+ const nonce = sodium.from_hex(content.slice(32, 56));
+ const ciphertext = sodium.from_hex(content.slice(56));
+
+ try {
+ const plaintext_bytes = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(
+ null,
+ ciphertext,
+ null,
+ nonce,
+ key
+ );
+ const decrypted_body = sodium.to_string(plaintext_bytes);
+ return decrypted_body;
+ } catch (e) {
+ if (e instanceof Error) {
+ console.error(e.message);
+ throw new Error("Decryption failure!: " + e.message);
+ } else {
+ throw new Error("Decryption failure!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/shinkai-message-ts/src/index.ts b/libs/shinkai-message-ts/src/index.ts
index e933299e4..6907042f5 100644
--- a/libs/shinkai-message-ts/src/index.ts
+++ b/libs/shinkai-message-ts/src/index.ts
@@ -1,6 +1,7 @@
import * as api from "./api";
+import * as cryptography from "./cryptography/shinkai-encryption";
import * as models from "./models";
import * as utils from "./utils";
import * as wasm from "./utils";
-export { api, models, utils, wasm };
+export { api, models, utils, wasm, cryptography };
diff --git a/package-lock.json b/package-lock.json
index e0c114b4c..f94c6cb24 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -60,6 +60,7 @@
"ionicons": "^7.0.0",
"jsbi": "^4.3.0",
"jspdf": "^2.5.1",
+ "libsodium-wrappers-sumo": "^0.7.13",
"lucide-react": "^0.263.1",
"node-forge": ">=1.0.0",
"react": "18.2.0",
@@ -111,6 +112,7 @@
"@types/chrome": "^0.0.246",
"@types/crypto-js": "^4.1.2",
"@types/jest": "^29.5.4",
+ "@types/libsodium-wrappers-sumo": "^0.7.7",
"@types/node": "18.14.2",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.6",
@@ -8633,6 +8635,21 @@
"@types/node": "*"
}
},
+ "node_modules/@types/libsodium-wrappers": {
+ "version": "0.7.12",
+ "resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.12.tgz",
+ "integrity": "sha512-NNUV6W5KFMYSazUh7bofvIqjHunu1ia24Q4gygXrhluXvvdPtkV6fXuciidYU7eBc9XTltAc6k727wYlrpo9Jg==",
+ "dev": true
+ },
+ "node_modules/@types/libsodium-wrappers-sumo": {
+ "version": "0.7.7",
+ "resolved": "https://registry.npmjs.org/@types/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.7.tgz",
+ "integrity": "sha512-L5KaYOEJqPlMZjP2kUaKjr0vQyv8LRR/QkwAKUazl3JrcEt/VXDdCAi2+Z5mSHOUjan7PEPRSxEPvwsIyXDLDA==",
+ "dev": true,
+ "dependencies": {
+ "@types/libsodium-wrappers": "*"
+ }
+ },
"node_modules/@types/linkify-it": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.3.tgz",
@@ -17873,6 +17890,19 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/libsodium-sumo": {
+ "version": "0.7.13",
+ "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.13.tgz",
+ "integrity": "sha512-zTGdLu4b9zSNLfovImpBCbdAA4xkpkZbMnSQjP8HShyOutnGjRHmSOKlsylh1okao6QhLiz7nG98EGn+04cZjQ=="
+ },
+ "node_modules/libsodium-wrappers-sumo": {
+ "version": "0.7.13",
+ "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.13.tgz",
+ "integrity": "sha512-lz4YdplzDRh6AhnLGF2Dj2IUj94xRN6Bh8T0HLNwzYGwPehQJX6c7iYVrFUPZ3QqxE0bqC+K0IIqqZJYWumwSQ==",
+ "dependencies": {
+ "libsodium-sumo": "^0.7.13"
+ }
+ },
"node_modules/license-webpack-plugin": {
"version": "4.0.2",
"dev": true,
diff --git a/package.json b/package.json
index 2ee5bba5a..fc6eef2bf 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"@types/chrome": "^0.0.246",
"@types/crypto-js": "^4.1.2",
"@types/jest": "^29.5.4",
+ "@types/libsodium-wrappers-sumo": "^0.7.7",
"@types/node": "18.14.2",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.6",
@@ -135,6 +136,7 @@
"ionicons": "^7.0.0",
"jsbi": "^4.3.0",
"jspdf": "^2.5.1",
+ "libsodium-wrappers-sumo": "^0.7.13",
"lucide-react": "^0.263.1",
"node-forge": ">=1.0.0",
"react": "18.2.0",