From 6f709bc441ff7be876253a8b1b237bfa4dad9c0e Mon Sep 17 00:00:00 2001 From: Tomek Marciniak Date: Tue, 30 Jul 2024 23:54:10 +0200 Subject: [PATCH] chore(wallet): refactor buffers to uint8arrays --- apps/extension/app.html | 14 - apps/extension/e2e/provider-enable.spec.ts | 4 - apps/extension/index.html | 4 - apps/extension/manifest.config.ts | 61 -- apps/extension/manifest.json | 38 ++ apps/extension/manifest.mjs | 44 ++ apps/extension/package.json | 14 +- apps/extension/prompt.html | 5 - apps/extension/public/pallad_rpc.js | 1 - apps/extension/scripts/append-oninstall.cjs | 21 - apps/extension/src/app.tsx | 1 + apps/extension/src/background/index.ts | 104 +--- apps/extension/src/inject/index.ts | 1 + apps/extension/src/welcome.tsx | 15 - apps/extension/tsconfig.json | 25 +- apps/extension/tsconfig.node.json | 15 - apps/extension/vite.config.ts | 32 +- apps/extension/welcome.html | 32 -- packages/common/tsconfig.json | 1 + packages/features/package.json | 5 +- .../features/src/common/hooks/use-account.ts | 4 +- .../features/src/common/lib/validation.ts | 1 + .../features/src/common/store/address-book.ts | 4 +- packages/features/src/common/store/app.ts | 4 +- .../features/src/components/app-layout.tsx | 1 + packages/features/src/index.ts | 1 - .../src/lock/routes/unlock-wallet.tsx | 12 +- .../routes/seed-backup-confirmation.tsx | 10 +- .../src/onboarding/routes/seed-import.tsx | 10 +- .../features/src/onboarding/routes/start.tsx | 11 +- .../hooks/use-transaction-confirmation.tsx | 6 +- .../web-connector/routes/web-connector.tsx | 23 +- .../src/web-connector/views/web-connector.tsx | 2 +- .../features/src/welcome/index.stories.tsx | 9 - packages/features/src/welcome/index.tsx | 46 -- packages/key-management/README.md | 38 +- packages/key-management/package.json | 3 +- .../key-management/src/InMemoryKeyAgent.ts | 11 +- packages/key-management/src/KeyAgentBase.ts | 18 +- packages/key-management/src/KeyDecryptor.ts | 13 +- .../key-management/src/SessionKeyAgentBase.ts | 5 +- .../chains/Ethereum/credentialDerivation.ts | 4 +- .../src/chains/Ethereum/keyDerivation.ts | 7 +- .../src/chains/Ethereum/types.ts | 2 +- .../src/chains/Mina/credentialDerivation.ts | 5 +- .../src/chains/Mina/keyDerivation.ts | 11 +- .../src/chains/Mina/keyDerivationUtils.ts | 11 - .../key-management/src/chains/Mina/types.ts | 8 +- packages/key-management/src/emip3.ts | 5 +- packages/key-management/src/types.ts | 12 +- packages/key-management/src/util/bip39.ts | 2 +- packages/key-management/src/util/key.ts | 2 +- .../ethereum/credential-derivation.test.ts | 5 +- .../test/ethereum/in-memory-key-agent.test.ts | 11 +- .../test/ethereum/key-agent-base.test.ts | 9 +- .../key-management/test/keyDecryptor.test.ts | 4 +- .../test/mina/in-memory-key-agent.test.ts | 11 +- .../mina/key-agent-base-zkapp-command.test.ts | 9 +- .../test/mina/key-agent-base.test.ts | 21 +- .../test/mina/sesion-key-agent-base.test.ts | 2 +- packages/key-management/tsconfig.json | 3 +- packages/mina-core/README.md | 26 +- packages/pallad-core/README.md | 26 +- .../test/Mina/custom-token-tx.test.ts | 5 +- packages/persistence/README.md | 3 - packages/persistence/package.json | 26 - packages/persistence/src/index.ts | 7 - packages/persistence/src/typings.ts | 9 - packages/persistence/tsconfig.json | 7 - packages/persistence/tsup.config.ts | 11 - packages/providers/package.json | 1 + .../blockberry/chain-history-provider.test.ts | 1 - .../account-info-provider.test.ts | 1 - .../node-status-provider.test.ts | 1 - .../submit-tx-provider.test.ts | 9 +- .../submit-tx-provider.test.ts | 8 +- .../individual-providers/util.ts | 1 - .../test/open-mina/sync-provider.test.ts | 3 - .../account-info-provider.test.ts | 1 - .../chain-history-provider.test.ts | 1 - .../unified-provider.test.ts | 8 - .../zeko-scan/chain-history-provider.test.ts | 1 - packages/vault/package.json | 5 +- .../vault/src/pending-transactions/index.ts | 4 +- packages/vault/src/utils/index.ts | 1 + .../web.ts => vault/src/utils/persistence.ts} | 11 +- .../vault/src/vault/utils/restore-wallet.ts | 4 +- packages/vault/src/vault/vaultStore.ts | 9 +- .../vault/test/account/accountStore.test.ts | 1 - .../vault/test/keyAgent/keyAgentStore.test.ts | 6 +- packages/vault/test/wallet/walletFlow.test.ts | 11 +- packages/web-provider/package.json | 3 +- .../src/mina-network/mina-provider.ts | 13 +- packages/web-provider/src/utils/prompts.ts | 11 +- .../src/vault-service/vault-service.ts | 27 +- .../test/mina/mina-provider.test.ts | 21 +- pnpm-lock.yaml | 533 +++++++++++------- 97 files changed, 673 insertions(+), 956 deletions(-) delete mode 100644 apps/extension/app.html delete mode 100644 apps/extension/manifest.config.ts create mode 100644 apps/extension/manifest.json create mode 100644 apps/extension/manifest.mjs delete mode 100644 apps/extension/scripts/append-oninstall.cjs delete mode 100644 apps/extension/src/welcome.tsx delete mode 100644 apps/extension/tsconfig.node.json delete mode 100644 apps/extension/welcome.html delete mode 100644 packages/features/src/welcome/index.stories.tsx delete mode 100644 packages/features/src/welcome/index.tsx delete mode 100644 packages/persistence/README.md delete mode 100644 packages/persistence/package.json delete mode 100644 packages/persistence/src/index.ts delete mode 100644 packages/persistence/src/typings.ts delete mode 100644 packages/persistence/tsconfig.json delete mode 100644 packages/persistence/tsup.config.ts rename packages/{persistence/src/web.ts => vault/src/utils/persistence.ts} (82%) diff --git a/apps/extension/app.html b/apps/extension/app.html deleted file mode 100644 index 16f25181..00000000 --- a/apps/extension/app.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Pallad - - - - -
- - - diff --git a/apps/extension/e2e/provider-enable.spec.ts b/apps/extension/e2e/provider-enable.spec.ts index f9c60d11..325f1a09 100644 --- a/apps/extension/e2e/provider-enable.spec.ts +++ b/apps/extension/e2e/provider-enable.spec.ts @@ -46,7 +46,6 @@ test.skip("enable window.mina and handle pop-up on a specific webpage", async ({ const responseRequestNetwork = await page.evaluate(() => window.mina.request({ method: "mina_requestNetwork" }), ) - console.log("responseRequestNetwork:", responseRequestNetwork) expect(responseRequestNetwork.result.chainId).not.toBe(undefined) const responseAddChain = await page.evaluate(() => @@ -67,7 +66,6 @@ test.skip("enable window.mina and handle pop-up on a specific webpage", async ({ }, }), ) - console.log("responseAddChain:", responseAddChain) expect(responseAddChain.result.networkName).toBe("ZekoDevNet") const responseSwitchChain = await page.evaluate(() => @@ -78,13 +76,11 @@ test.skip("enable window.mina and handle pop-up on a specific webpage", async ({ }, }), ) - console.log("responseSwitchChain:", responseSwitchChain) expect(responseSwitchChain.result.networkName).toBe("ZekoDevNet") const responseBalanceZeko = await page.evaluate(() => window.mina.request({ method: "mina_getBalance" }), ) - console.log("responseBalanceZeko:", responseBalanceZeko) expect(responseBalanceZeko.result).not.toBe(0) await page.evaluate(() => diff --git a/apps/extension/index.html b/apps/extension/index.html index 52184c58..2209e775 100644 --- a/apps/extension/index.html +++ b/apps/extension/index.html @@ -19,10 +19,6 @@ display: flex; } - diff --git a/apps/extension/manifest.config.ts b/apps/extension/manifest.config.ts deleted file mode 100644 index bf70df39..00000000 --- a/apps/extension/manifest.config.ts +++ /dev/null @@ -1,61 +0,0 @@ -import packageJson from "./package.json" -const { version } = packageJson -import { defineManifest } from "@crxjs/vite-plugin" - -// Convert from Semver (example: 0.1.0-beta6) -const [major, minor, patch, label = "0"] = version - // can only contain digits, dots, or dash - .replace(/[^\d.-]+/g, "") - // split into version parts - .split(/[.-]/) - -export default defineManifest((env) => ({ - manifest_version: 3, - name: env.mode === "DEVELOPMENT" ? "[DEV] Pallad" : "Pallad", - description: - "Discover the Future of Web3 with Pallad. Unlock the power of the world's lightest blockchain 🪶", - icons: { - "16": "icons/16.png", - "32": "icons/32.png", - "48": "icons/48.png", - "128": "icons/128.png", - }, - version: `${major}.${minor}.${patch}.${label}`, - version_name: version, - action: { default_title: "Click to open panel" }, - side_panel: { default_path: "index.html" }, - permissions: ["storage", "activeTab", "background", "sidePanel"], - background: { - service_worker: "src/background/index.ts", - type: "module", - }, - content_scripts: [ - { - matches: ["https://*/*"], - js: ["src/inject/index.ts"], - run_at: "document_start", - all_frames: true, - }, - ], - web_accessible_resources: [ - { - resources: ["pallad_rpc.js"], - matches: ["https://*/*"], - }, - ], - host_permissions: [ - "https://*/*", - // Add other URLs or patterns as needed - ], - commands: { - _execute_action: { - suggested_key: { - windows: "Alt+Shift+P", - mac: "Alt+Shift+P", - chromeos: "Alt+Shift+P", - linux: "Alt+Shift+P", - }, - description: "Open the Pallad extension", - }, - }, -})) diff --git a/apps/extension/manifest.json b/apps/extension/manifest.json new file mode 100644 index 00000000..4df252a9 --- /dev/null +++ b/apps/extension/manifest.json @@ -0,0 +1,38 @@ +{ + "manifest_version": 3, + "name": "Pallad", + "description": "Discover the Future of Web3 with Pallad. Unlock the power of the world's lightest blockchain 🪶", + "icons": { + "16": "icons/16.png", + "32": "icons/32.png", + "48": "icons/48.png", + "128": "icons/128.png" + }, + "version": "0.6.0", + "action": { + "default_title": "Click to open panel" + }, + "side_panel": { + "default_path": "index.html" + }, + "permissions": ["storage", "activeTab", "background", "sidePanel"], + "background": { + "service_worker": "src/background/index.ts", + "type": "module" + }, + "content_scripts": [ + { + "matches": ["https://*/*"], + "js": ["src/inject/index.ts"], + "run_at": "document_start", + "all_frames": true + } + ], + "web_accessible_resources": [ + { + "resources": ["pallad_rpc.js"], + "matches": ["https://*/*"] + } + ], + "host_permissions": ["https://*/*"] +} diff --git a/apps/extension/manifest.mjs b/apps/extension/manifest.mjs new file mode 100644 index 00000000..90299767 --- /dev/null +++ b/apps/extension/manifest.mjs @@ -0,0 +1,44 @@ +import { writeJsonFile } from "write-json-file" +import packageJson from "./package.json" with { type: "json" } + +const manifest = { + manifest_version: 3, + name: "Pallad", + description: + "Discover the Future of Web3 with Pallad. Unlock the power of the world's lightest blockchain 🪶", + icons: { + 16: "icons/16.png", + 32: "icons/32.png", + 48: "icons/48.png", + 128: "icons/128.png", + }, + version: packageJson.version, + action: { default_title: "Click to open panel" }, + side_panel: { default_path: "index.html" }, + permissions: ["storage", "activeTab", "background", "sidePanel"], + background: { + service_worker: "src/background/index.ts", + type: "module", + }, + content_scripts: [ + { + matches: ["https://*/*"], + js: ["src/inject/index.ts"], + run_at: "document_start", + all_frames: true, + }, + ], + web_accessible_resources: [ + { + resources: ["pallad_rpc.js"], + matches: ["https://*/*"], + }, + ], + host_permissions: ["https://*/*"], +} + +const run = async () => { + await writeJsonFile("manifest.json", manifest) +} + +run() diff --git a/apps/extension/package.json b/apps/extension/package.json index 17d3cc28..2b302325 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -4,9 +4,9 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc && vite build && node scripts/append-oninstall.cjs", + "build": "tsc && node manifest.mjs && vite build", "build:firefox": "web-ext build --source-dir=dist", - "build:safari": "xcrun safari-web-extension-converter dist --app-name Pallad --bundle-identifier xyz.pallad.app --swift --no-prompt --force --macos-only --no-open", + "build:safari": "xcrun safari-web-extension-converter dist --app-name Pallad --bundle-identifier co.pallad.app --swift --no-prompt --force --macos-only --no-open", "preview": "vite preview", "cleanup": "rimraf node_modules dist .turbo", "test:e2e": "playwright test", @@ -17,10 +17,10 @@ "@palladxyz/common": "workspace:*", "@palladxyz/features": "workspace:*", "@palladxyz/key-management": "workspace:*", - "@palladxyz/persistence": "workspace:*", "@palladxyz/web-provider": "workspace:*", "@plasmohq/messaging": "0.6.2", "buffer": "6.0.3", + "debounce": "^2.1.0", "next-themes": "0.3.0", "react": "18.3.1", "react-dom": "18.3.1", @@ -32,13 +32,13 @@ "zod": "3.23.8" }, "devDependencies": { - "@crxjs/vite-plugin": "2.0.0-beta.25", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@esbuild-plugins/node-modules-polyfill": "0.2.2", "@originjs/vite-plugin-commonjs": "1.0.3", "@playwright/test": "1.45.3", "@testing-library/react": "16.0.0", "@total-typescript/ts-reset": "0.5.1", + "@tsconfig/vite-react": "3.0.2", "@types/chrome": "0.0.269", "@types/mocha": "10.0.7", "@types/node": "22.0.0", @@ -53,11 +53,13 @@ "type-fest": "4.23.0", "vite": "5.3.5", "vite-plugin-commonjs": "0.10.1", - "vite-plugin-node-polyfills": "0.22.0", + "vite-plugin-node-polyfills": "0.17.0", "vite-plugin-require-transform": "1.0.21", "vite-plugin-svgr": "4.2.0", "vite-plugin-top-level-await": "1.4.2", "vite-plugin-wasm": "3.3.0", - "web-ext": "8.2.0" + "vite-plugin-web-extension": "^4.1.6", + "web-ext": "8.2.0", + "write-json-file": "^6.0.0" } } diff --git a/apps/extension/prompt.html b/apps/extension/prompt.html index a0337864..da43c9b4 100644 --- a/apps/extension/prompt.html +++ b/apps/extension/prompt.html @@ -15,11 +15,6 @@ display: flex; } - diff --git a/apps/extension/public/pallad_rpc.js b/apps/extension/public/pallad_rpc.js index 8a3ec6d0..e402ab7a 100644 --- a/apps/extension/public/pallad_rpc.js +++ b/apps/extension/public/pallad_rpc.js @@ -25,7 +25,6 @@ const callPalladAsync = ({ method, payload }) => { channel.close() const error = data.response?.error if (error) { - console.log("[Pallad] Web Connector Error") try { console.table(JSON.parse(error.message)) } catch { diff --git a/apps/extension/scripts/append-oninstall.cjs b/apps/extension/scripts/append-oninstall.cjs deleted file mode 100644 index fd4182e0..00000000 --- a/apps/extension/scripts/append-oninstall.cjs +++ /dev/null @@ -1,21 +0,0 @@ -const fs = require("node:fs") -const path = require("node:path") -const dedent = require("dedent") - -const script = dedent` - chrome.runtime.onInstalled.addListener(async ({reason}) => { - await chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }); - if (reason === 'install') { - await chrome.tabs.create({ url: chrome.runtime.getURL('welcome.html') }) - } - }) -` - -fs.appendFile( - path.join(__dirname, "..", "dist", "service-worker-loader.js"), - script, - (err) => { - if (err) throw err - console.log("onInstall script appended.") - }, -) diff --git a/apps/extension/src/app.tsx b/apps/extension/src/app.tsx index 44d7b913..2f460632 100644 --- a/apps/extension/src/app.tsx +++ b/apps/extension/src/app.tsx @@ -7,6 +7,7 @@ import { useEffect } from "react" function App() { useEffect(() => { + if (typeof document === "undefined") return const handleContextmenu = (e: MouseEvent) => { if (!e.metaKey) e.preventDefault() } diff --git a/apps/extension/src/background/index.ts b/apps/extension/src/background/index.ts index de73fcad..f6f947d2 100644 --- a/apps/extension/src/background/index.ts +++ b/apps/extension/src/background/index.ts @@ -1,69 +1,16 @@ -import { - MinaProvider, - type ProviderEvent, - Validation, -} from "@palladxyz/web-provider" +import { MinaProvider, Validation } from "@palladxyz/web-provider" import { serializeError } from "serialize-error" -import { onMessage, sendMessage } from "webext-bridge/background" -import { runtime } from "webextension-polyfill" +import { onMessage } from "webext-bridge/background" +import { runtime, tabs } from "webextension-polyfill" -// options should be defined by user const opts = { projectId: "test", chains: ["Mina - Mainnet"], } -const provider = await MinaProvider.init(opts, []) - -// Example structure for listenerRegistry -type ListenerFunction = (args: any) => void // Adjust the 'any' type based on actual event arguments - -interface ListenerRegistration { - event: ProviderEvent - listener: ListenerFunction -} - -interface OnMessageData { - listenerId: string -} - -interface OnEventData { - event: ProviderEvent - context: any // Can be more specific type based on our context structure -} - -const listenerRegistry: Record = {} - -function generateListenerId(): string { - return Math.random().toString(36).substring(2, 15) -} - -function registerListener(event: ProviderEvent /*, context: string*/): string { - const listenerId = generateListenerId() - const listener: ListenerFunction = (args) => { - // Adjusting sendMessage call to match its signature - sendMessage("eventTriggered", { listenerId, event, args }) // Assuming context is handled elsewhere or not needed - } - - listenerRegistry[listenerId] = { event, listener } - - // Register with MinaProvider - provider.on(event, listener) - - return listenerId -} - -function removeListener(listenerId: string): void { - const registration = listenerRegistry[listenerId] - if (registration) { - const { event, listener } = registration - provider.off(event, listener) - delete listenerRegistry[listenerId] - } -} - onMessage("enable", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const { origin } = Validation.requestSchema.parse(data) return await provider.enable({ origin }) } catch (error: unknown) { @@ -71,20 +18,9 @@ onMessage("enable", async ({ data }) => { } }) -onMessage("on", ({ data }) => { - const { event /*, context*/ } = data as unknown as OnEventData - const listenerId = registerListener(event /*, context*/) - return { success: true, listenerId } -}) - -onMessage("off", ({ data }) => { - const { listenerId } = data as unknown as OnMessageData - removeListener(listenerId) - return { success: true } -}) - onMessage("mina_setState", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.setStateRequestSchema.parse(data) return await provider.request({ method: "mina_setState", @@ -101,6 +37,7 @@ onMessage("mina_addChain", async () => { onMessage("mina_requestNetwork", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.requestSchema.parse(data) return await provider.request({ method: "mina_requestNetwork", @@ -117,6 +54,7 @@ onMessage("mina_switchChain", async () => { onMessage("mina_getState", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.getStateRequestSchema.parse(data) return await provider.request({ method: "mina_getState", @@ -129,6 +67,7 @@ onMessage("mina_getState", async ({ data }) => { onMessage("isConnected", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const { origin } = Validation.requestSchema.parse(data) return await provider.isConnected({ origin }) } catch (error: unknown) { @@ -138,6 +77,7 @@ onMessage("isConnected", async ({ data }) => { onMessage("mina_chainId", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.requestSchema.parse(data) return await provider.request({ method: "mina_chainId", @@ -150,6 +90,7 @@ onMessage("mina_chainId", async ({ data }) => { onMessage("mina_accounts", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.requestSchema.parse(data) return await provider.request({ method: "mina_accounts", @@ -163,6 +104,7 @@ onMessage("mina_accounts", async ({ data }) => { // TODO: It should be removed, but let's keep it for now for Auro compatibility. onMessage("mina_requestAccounts", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.requestSchema.parse(data) return await provider.request({ method: "mina_accounts", @@ -175,6 +117,7 @@ onMessage("mina_requestAccounts", async ({ data }) => { onMessage("mina_sign", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.signMessageRequestSchema.parse(data) return await provider.request({ method: "mina_sign", @@ -187,6 +130,7 @@ onMessage("mina_sign", async ({ data }) => { onMessage("mina_signFields", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.signFieldsRequestSchema.parse(data) return await provider.request({ method: "mina_signFields", @@ -199,6 +143,7 @@ onMessage("mina_signFields", async ({ data }) => { onMessage("mina_signTransaction", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.signTransactionRequestSchema.parse(data) return await provider.request({ method: "mina_signTransaction", @@ -211,6 +156,7 @@ onMessage("mina_signTransaction", async ({ data }) => { onMessage("mina_getBalance", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.requestSchema.parse(data) return await provider.request({ method: "mina_getBalance", @@ -223,6 +169,7 @@ onMessage("mina_getBalance", async ({ data }) => { onMessage("mina_createNullifier", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.createNullifierRequestSchema.parse(data) return await provider.request({ method: "mina_createNullifier", @@ -235,6 +182,7 @@ onMessage("mina_createNullifier", async ({ data }) => { onMessage("mina_sendTransaction", async ({ data }) => { try { + const provider = await MinaProvider.init(opts, []) const params = Validation.sendTransactionRequestSchema.parse(data) return await provider.request({ method: "mina_sendTransaction", @@ -245,6 +193,12 @@ onMessage("mina_sendTransaction", async ({ data }) => { } }) +onMessage("pallad_sidePanel", async ({ sender }) => { + await chrome.sidePanel.open({ + tabId: sender.tabId, + }) +}) + runtime.onConnect.addListener((port) => { if (port.name === "prompt") { port.onDisconnect.addListener(async () => { @@ -256,13 +210,9 @@ runtime.onConnect.addListener((port) => { } }) -chrome.runtime.onMessage.addListener(async (message, sender, response) => { - if (message.type === "pallad_side_panel") { - await chrome.sidePanel.open({ - tabId: sender.tab?.id ?? 0, - windowId: sender.tab?.windowId, - }) - response({ ok: true }) +runtime.onInstalled.addListener(async ({ reason }) => { + await chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }) + if (reason === "install") { + await tabs.create({ url: "https://pallad.co" }) } - return true }) diff --git a/apps/extension/src/inject/index.ts b/apps/extension/src/inject/index.ts index ac1f0007..f87d8ee7 100644 --- a/apps/extension/src/inject/index.ts +++ b/apps/extension/src/inject/index.ts @@ -3,6 +3,7 @@ import { sendMessage } from "webext-bridge/content-script" import { runtime } from "webextension-polyfill" const inject = () => { + if (typeof document === "undefined") return const script = document.createElement("script") script.src = runtime.getURL("/pallad_rpc.js") script.type = "module" diff --git a/apps/extension/src/welcome.tsx b/apps/extension/src/welcome.tsx deleted file mode 100644 index 3ea45130..00000000 --- a/apps/extension/src/welcome.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import "@palladxyz/features/dist/index.css" -import "@total-typescript/ts-reset" - -import { WelcomeScreen } from "@palladxyz/features" -import { ThemeProvider } from "next-themes" -import React from "react" -import ReactDOM from "react-dom/client" - -ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - - - - - , -) diff --git a/apps/extension/tsconfig.json b/apps/extension/tsconfig.json index 893e58f0..166bae6e 100644 --- a/apps/extension/tsconfig.json +++ b/apps/extension/tsconfig.json @@ -1,25 +1,4 @@ { - "compilerOptions": { - "types": ["vite/client", "node", "@types/chrome"], - "baseUrl": "./src", - "paths": { - "@/*": ["./*"] - }, - "target": "ESNext", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "module": "ESNext", - "skipLibCheck": true, - "esModuleInterop": true, - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "extends": "@tsconfig/vite-react/tsconfig.json", + "exclude": ["e2e"] } diff --git a/apps/extension/tsconfig.node.json b/apps/extension/tsconfig.node.json deleted file mode 100644 index a3896494..00000000 --- a/apps/extension/tsconfig.node.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "./src", - "paths": { - "@/*": ["./*"] - }, - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "resolveJsonModule": true - }, - "include": ["vite.config.ts", "manifest.config.ts", "package.json"] -} diff --git a/apps/extension/vite.config.ts b/apps/extension/vite.config.ts index 0298c9ca..d862eee5 100644 --- a/apps/extension/vite.config.ts +++ b/apps/extension/vite.config.ts @@ -1,29 +1,27 @@ -import { crx } from "@crxjs/vite-plugin" import react from "@vitejs/plugin-react-swc" import { defineConfig } from "vite" +import { nodePolyfills } from "vite-plugin-node-polyfills" import svgr from "vite-plugin-svgr" -import topLevelAwait from "vite-plugin-top-level-await" - -import manifest from "./manifest.config" +import webExtension from "vite-plugin-web-extension" export default defineConfig({ - plugins: [react(), crx({ manifest }), topLevelAwait(), svgr()], + plugins: [ + react(), + webExtension({ + webExtConfig: { + startUrl: ["pallad.co"], + }, + additionalInputs: ["prompt.html"], + }), + svgr(), + nodePolyfills({ protocolImports: true, globals: { Buffer: true } }), + ], define: { "global.browser": {}, + "process.env": {}, }, build: { - rollupOptions: { - input: { - app: "app.html", - index: "index.html", - prompt: "prompt.html", - welcome: "welcome.html", - inject: "public/pallad_rpc.js", - }, - }, - commonjsOptions: { - transformMixedEsModules: true, - }, chunkSizeWarningLimit: 5000, + emptyOutDir: true, }, }) diff --git a/apps/extension/welcome.html b/apps/extension/welcome.html deleted file mode 100644 index c220139e..00000000 --- a/apps/extension/welcome.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - Pallad - - - - - - -
- - - diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json index 5dbbb3d9..57095655 100644 --- a/packages/common/tsconfig.json +++ b/packages/common/tsconfig.json @@ -2,6 +2,7 @@ "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "target": "ESNext", + "module": "ESNext", "moduleResolution": "node", "allowSyntheticDefaultImports": true, "esModuleInterop": true, diff --git a/packages/features/package.json b/packages/features/package.json index fbbbe468..ed6c6c00 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -36,11 +36,11 @@ "@github/hotkey": "3.1.1", "@headlessui/react": "2.1.2", "@hookform/resolvers": "3.9.0", + "@noble/hashes": "1.4.0", "@palladxyz/key-management": "workspace:*", "@palladxyz/mina-core": "workspace:*", "@palladxyz/offchain-data": "workspace:*", "@palladxyz/pallad-core": "workspace:*", - "@palladxyz/persistence": "workspace:*", "@palladxyz/vault": "workspace:*", "@total-typescript/ts-reset": "0.5.1", "array-shuffle": "3.0.0", @@ -50,7 +50,6 @@ "dayjs": "1.11.12", "easy-mesh-gradient": "0.0.5", "immer": "10.1.1", - "isomorphic-dompurify": "2.14.0", "js-beautify": "1.15.1", "lucide-react": "0.417.0", "match-sorter": "6.3.4", @@ -74,7 +73,9 @@ "superjson": "2.2.1", "tailwind-merge": "2.4.0", "tailwindcss-animate": "1.0.7", + "webext-bridge": "6.0.1", "webextension-polyfill": "0.12.0", + "xss": "^1.0.15", "yaml": "2.5.0", "zod": "3.23.8", "zustand": "4.5.4" diff --git a/packages/features/src/common/hooks/use-account.ts b/packages/features/src/common/hooks/use-account.ts index 7020bb21..eadb5a0f 100644 --- a/packages/features/src/common/hooks/use-account.ts +++ b/packages/features/src/common/hooks/use-account.ts @@ -1,5 +1,5 @@ import { Network, getAccountProperties } from "@palladxyz/pallad-core" -import { getSessionPersistence } from "@palladxyz/persistence" +import { sessionPersistence } from "@palladxyz/vault" import { getPublicKey, isDelegated, useVault } from "@palladxyz/vault" import easyMeshGradient from "easy-mesh-gradient" import { useMemo } from "react" @@ -54,7 +54,7 @@ export const useAccount = () => { toast.success("Address copied") } const lockWallet = async () => { - await getSessionPersistence().setItem("spendingPassword", "") + await sessionPersistence.setItem("spendingPassword", "") navigate("/unlock") await useVault.persist.rehydrate() } diff --git a/packages/features/src/common/lib/validation.ts b/packages/features/src/common/lib/validation.ts index c331abed..c4fd614a 100644 --- a/packages/features/src/common/lib/validation.ts +++ b/packages/features/src/common/lib/validation.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import { z } from "zod" export const passwordSchema = z diff --git a/packages/features/src/common/store/address-book.ts b/packages/features/src/common/store/address-book.ts index 8ccd2f52..058047d4 100644 --- a/packages/features/src/common/store/address-book.ts +++ b/packages/features/src/common/store/address-book.ts @@ -1,4 +1,4 @@ -import { getLocalPersistence } from "@palladxyz/persistence" +import { localPersistence } from "@palladxyz/vault" import { create } from "zustand" import { createJSONStorage, persist } from "zustand/middleware" @@ -31,7 +31,7 @@ export const useAddressBookStore = create()( }), { name: "PalladAddressBook", - storage: createJSONStorage(getLocalPersistence), + storage: createJSONStorage(() => localPersistence), }, ), ) diff --git a/packages/features/src/common/store/app.ts b/packages/features/src/common/store/app.ts index 92770b80..819021eb 100644 --- a/packages/features/src/common/store/app.ts +++ b/packages/features/src/common/store/app.ts @@ -1,4 +1,4 @@ -import { getLocalPersistence } from "@palladxyz/persistence" +import { localPersistence } from "@palladxyz/vault" import { create } from "zustand" import { createJSONStorage, persist } from "zustand/middleware" @@ -55,7 +55,7 @@ export const useAppStore = create()( }), { name: "PalladApp", - storage: createJSONStorage(getLocalPersistence), + storage: createJSONStorage(() => localPersistence), }, ), ) diff --git a/packages/features/src/components/app-layout.tsx b/packages/features/src/components/app-layout.tsx index bdf1aaff..abb13386 100644 --- a/packages/features/src/components/app-layout.tsx +++ b/packages/features/src/components/app-layout.tsx @@ -11,6 +11,7 @@ export const AppLayout = ({ children }: AppLayoutProps) => { const location = useLocation() // biome-ignore lint: dependent just on location useEffect(() => { + if (typeof document === "undefined") return for (const el of document.querySelectorAll("[data-hotkey]")) { install(el as never) } diff --git a/packages/features/src/index.ts b/packages/features/src/index.ts index 0cb9b4bd..68656a3b 100644 --- a/packages/features/src/index.ts +++ b/packages/features/src/index.ts @@ -6,6 +6,5 @@ export { useAppStore } from "./common/store/app" export { usePendingTransactionStore } from "@palladxyz/vault" export { Router } from "./router" export { WebConnectorRoute } from "./web-connector/routes/web-connector" -export { WelcomeScreen } from "./welcome" export * as Icons from "lucide-react" import "./globals.css" diff --git a/packages/features/src/lock/routes/unlock-wallet.tsx b/packages/features/src/lock/routes/unlock-wallet.tsx index 48e44bb6..602c0202 100644 --- a/packages/features/src/lock/routes/unlock-wallet.tsx +++ b/packages/features/src/lock/routes/unlock-wallet.tsx @@ -1,8 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { - getSecurePersistence, - getSessionPersistence, -} from "@palladxyz/persistence" +import { securePersistence, sessionPersistence } from "@palladxyz/vault" import { useVault } from "@palladxyz/vault" import { type FormEvent, useEffect, useState } from "react" import { useForm } from "react-hook-form" @@ -32,7 +29,7 @@ export const UnlockWalletRoute = () => { }: { spendingPassword: string }) => { - await getSessionPersistence().setItem("spendingPassword", spendingPassword) + await sessionPersistence.setItem("spendingPassword", spendingPassword) await useVault.persist.rehydrate() setTimeout(() => { unlockWalletForm.setError("spendingPassword", { @@ -48,10 +45,9 @@ export const UnlockWalletRoute = () => { // biome-ignore lint: won't update useEffect(() => { const unsub = useVault.persist?.onFinishHydration(async () => { - const authenticated = - (await getSecurePersistence().getItem("foo")) === "bar" + const authenticated = (await securePersistence.getItem("foo")) === "bar" if (!authenticated) { - await getSessionPersistence().removeItem("spendingPassword") + await sessionPersistence.removeItem("spendingPassword") return unlockWalletForm.setError("spendingPassword", { type: "wrongPassword", message: "The spending password is wrong", diff --git a/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx b/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx index e0e48e53..420d5809 100644 --- a/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx +++ b/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx @@ -1,6 +1,7 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import type { ChainDerivationArgs } from "@palladxyz/key-management" import { Network } from "@palladxyz/pallad-core" -import { getSessionPersistence } from "@palladxyz/persistence" +import { sessionPersistence } from "@palladxyz/vault" import { DEFAULT_NETWORK, KeyAgents, useVault } from "@palladxyz/vault" import { useMemo, useState } from "react" import { useForm } from "react-hook-form" @@ -47,7 +48,7 @@ export const SeedBackupConfirmationRoute = () => { if (!walletName) return if (!spendingPassword) return if (!mnemonic) return - getSessionPersistence().setItem("spendingPassword", spendingPassword) + sessionPersistence.setItem("spendingPassword", spendingPassword) await useVault.persist.rehydrate() const restoreArgs: ChainDerivationArgs = { network: Network.Mina, @@ -61,10 +62,7 @@ export const SeedBackupConfirmationRoute = () => { DEFAULT_NETWORK, { mnemonicWords: mnemonic.split(" "), - getPassphrase: () => - new Promise((resolve) => - resolve(Buffer.from(spendingPassword)), - ), + getPassphrase: () => utf8ToBytes(spendingPassword), }, walletName, KeyAgents.InMemory, diff --git a/packages/features/src/onboarding/routes/seed-import.tsx b/packages/features/src/onboarding/routes/seed-import.tsx index 6553fe1c..0ffd6d88 100644 --- a/packages/features/src/onboarding/routes/seed-import.tsx +++ b/packages/features/src/onboarding/routes/seed-import.tsx @@ -1,7 +1,7 @@ import { validateMnemonic, wordlist } from "@palladxyz/key-management" import type { ChainDerivationArgs } from "@palladxyz/key-management" import { Network } from "@palladxyz/pallad-core" -import { getSessionPersistence } from "@palladxyz/persistence" +import { sessionPersistence } from "@palladxyz/vault" import { DEFAULT_NETWORK, KeyAgents, useVault } from "@palladxyz/vault" import { useState } from "react" import { type SubmitHandler, useForm } from "react-hook-form" @@ -12,6 +12,7 @@ import { shallow } from "zustand/shallow" import { useAppStore } from "@/common/store/app" import { useOnboardingStore } from "@/common/store/onboarding" +import { utf8ToBytes } from "@noble/hashes/utils" import type { MnemonicInputData } from "../types" import { SeedImportView } from "../views/seed-import" @@ -38,7 +39,7 @@ export const SeedImportRoute = () => { const onSubmit: SubmitHandler = async (data) => { if (!walletName) return if (!spendingPassword) return - getSessionPersistence().setItem("spendingPassword", spendingPassword) + sessionPersistence.setItem("spendingPassword", spendingPassword) await useVault.persist.rehydrate() const restoreArgs: ChainDerivationArgs = { @@ -53,10 +54,7 @@ export const SeedImportRoute = () => { DEFAULT_NETWORK, { mnemonicWords: data.mnemonic, - getPassphrase: () => - new Promise((resolve) => - resolve(Buffer.from(spendingPassword)), - ), + getPassphrase: () => utf8ToBytes(spendingPassword), }, walletName, KeyAgents.InMemory, diff --git a/packages/features/src/onboarding/routes/start.tsx b/packages/features/src/onboarding/routes/start.tsx index 0bf97bd0..1afe132f 100644 --- a/packages/features/src/onboarding/routes/start.tsx +++ b/packages/features/src/onboarding/routes/start.tsx @@ -1,7 +1,4 @@ -import { - getSecurePersistence, - getSessionPersistence, -} from "@palladxyz/persistence" +import { securePersistence, sessionPersistence } from "@palladxyz/vault" import { useEffect, useState } from "react" import { useNavigate } from "react-router-dom" @@ -20,15 +17,15 @@ export const StartRoute = () => { let spendingPassword try { spendingPassword = - (await getSessionPersistence().getItem("spendingPassword")) || "" + (await sessionPersistence.getItem("spendingPassword")) || "" } catch { return navigate("/unlock") } const spendingPasswordSet = spendingPassword?.length > 0 if (!spendingPasswordSet) return navigate("/unlock") - let authenticated + let authenticated: boolean try { - authenticated = (await getSecurePersistence().getItem("foo")) === "bar" + authenticated = (await securePersistence.getItem("foo")) === "bar" } catch { authenticated = false } diff --git a/packages/features/src/send/hooks/use-transaction-confirmation.tsx b/packages/features/src/send/hooks/use-transaction-confirmation.tsx index c180559b..893d1f4e 100644 --- a/packages/features/src/send/hooks/use-transaction-confirmation.tsx +++ b/packages/features/src/send/hooks/use-transaction-confirmation.tsx @@ -15,6 +15,7 @@ import { useAccount } from "@/common/hooks/use-account" import { useTransactionStore } from "@/common/store/transaction" import { usePendingTransactionStore } from "@palladxyz/vault" +import { utf8ToBytes } from "@noble/hashes/utils" import type { ConfirmTransactionSchema } from "../components/confirm-transaction-form.schema" type ConfirmTransactionData = z.infer @@ -68,10 +69,7 @@ export const useTransactionConfirmation = ({ data, ) => { const constructedTx = await constructTransaction() - const getPassphrase = () => - new Promise((resolve) => - resolve(Buffer.from(data.spendingPassword)), - ) + const getPassphrase = () => utf8ToBytes(data.spendingPassword) let signedTx // TODO: make chain agnostic depending on the currentWallet chain and it's corresponding operation e.g. 'eth_signTransaction' vs 'mina_signTransaction' const operationArgs: ChainOperationArgs = { diff --git a/packages/features/src/web-connector/routes/web-connector.tsx b/packages/features/src/web-connector/routes/web-connector.tsx index 299a4a35..3998689e 100644 --- a/packages/features/src/web-connector/routes/web-connector.tsx +++ b/packages/features/src/web-connector/routes/web-connector.tsx @@ -1,17 +1,18 @@ -import DOMPurify from "isomorphic-dompurify" import { useEffect, useState } from "react" import type { SubmitHandler } from "react-hook-form" import { MemoryRouter } from "react-router-dom" import { highlight } from "sugar-high" -import { runtime } from "webextension-polyfill" +import { runtime, windows } from "webextension-polyfill" +import xss from "xss" import yaml from "yaml" import type { UserInputForm } from "../types" import { WebConnectorView } from "../views/web-connector" -const sanitizePayload = (payload: string) => { - const parsedPayload = JSON.parse(payload) as Record +const sanitizePayload = async (payload: string) => { + const sanitizedPayload = xss(payload) + const parsedPayload = JSON.parse(sanitizedPayload) as Record const yamlPayload = yaml.stringify(parsedPayload) - return DOMPurify.sanitize(highlight(yamlPayload)) + return highlight(yamlPayload) } type ActionRequest = { @@ -29,7 +30,7 @@ export const WebConnectorRoute = () => { loading: true, }) const onSubmit: SubmitHandler = async ({ userInput }) => { - const { id } = await chrome.windows.getCurrent() + const { id } = await windows.getCurrent() await runtime.sendMessage({ userInput, windowId: id, @@ -37,7 +38,7 @@ export const WebConnectorRoute = () => { window.close() } const confirm = async () => { - const { id } = await chrome.windows.getCurrent() + const { id } = await windows.getCurrent() await runtime.sendMessage({ userConfirmed: true, windowId: id, @@ -45,7 +46,7 @@ export const WebConnectorRoute = () => { window.close() } const decline = async () => { - const { id } = await chrome.windows.getCurrent() + const { id } = await windows.getCurrent() await runtime.sendMessage({ userConfirmed: false, windowId: id, @@ -53,7 +54,7 @@ export const WebConnectorRoute = () => { window.close() } const reject = async () => { - const { id } = await chrome.windows.getCurrent() + const { id } = await windows.getCurrent() await runtime.sendMessage({ userRejected: true, windowId: id, @@ -61,11 +62,11 @@ export const WebConnectorRoute = () => { window.close() } useEffect(() => { - chrome.runtime.onMessage.addListener((message) => { + runtime.onMessage.addListener(async (message) => { if (message.type === "action_request") { setRequest({ title: message.params.title, - payload: sanitizePayload(message.params.payload), + payload: await sanitizePayload(message.params.payload), inputType: message.params.inputType, loading: false, }) diff --git a/packages/features/src/web-connector/views/web-connector.tsx b/packages/features/src/web-connector/views/web-connector.tsx index 69435389..5c3f22d6 100644 --- a/packages/features/src/web-connector/views/web-connector.tsx +++ b/packages/features/src/web-connector/views/web-connector.tsx @@ -41,7 +41,7 @@ export const WebConnectorView = ({

{title}

diff --git a/packages/features/src/welcome/index.stories.tsx b/packages/features/src/welcome/index.stories.tsx deleted file mode 100644 index f1599f52..00000000 --- a/packages/features/src/welcome/index.stories.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import type { StoryDefault } from "@ladle/react" - -import { WelcomeScreen as WelcomeScreenView } from "./" - -export const WelcomeScreen = () => - -export default { - title: "Welcome Screen", -} satisfies StoryDefault diff --git a/packages/features/src/welcome/index.tsx b/packages/features/src/welcome/index.tsx deleted file mode 100644 index 77c52790..00000000 --- a/packages/features/src/welcome/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { ExternalLinkIcon } from "lucide-react" - -import Logo from "@/common/assets/logo.svg?react" -import QuestionIcon from "@/common/assets/question.svg?react" - -export const WelcomeScreen = () => { - const openSidepanel = () => - chrome.runtime.sendMessage({ type: "pallad_side_panel" }) - return ( -
-
-
- -

Ready to open

-

- Just click on the Pallad icon in your extensions -

-

or use this handy shortcut

- -
- -
-
- -
-
-

About Pallad

-

More info about us

-
- -
-
-
-
- ) -} diff --git a/packages/key-management/README.md b/packages/key-management/README.md index d1d7ee0a..884b1e7d 100644 --- a/packages/key-management/README.md +++ b/packages/key-management/README.md @@ -57,27 +57,25 @@ Here's a simple example of usage: ```ts const mnemonicWords = [ - 'habit', - 'hope', - 'tip', - 'crystal', - 'because', - 'grunt', - 'nation', - 'idea', - 'electric', - 'witness', - 'alert', - 'like' -] -const getPassphrase = new Promise((resolve) => - resolve(Buffer.from('passphrase')) -) + "habit", + "hope", + "tip", + "crystal", + "because", + "grunt", + "nation", + "idea", + "electric", + "witness", + "alert", + "like", +]; +const getPassphrase = () => utf8ToBytes(passphrase); const agent = await InMemoryKeyAgent.fromMnemonicWords({ mnemonicWords, - getPassphrase -}) + getPassphrase, +}); ``` **Important**: When implementing, the passphrase function should be set up in a secure way that's suitable for your application. @@ -86,7 +84,6 @@ With the `InMemoryKeyAgent`, you can handle sensitive key material in a way that Check out the test suite! - # `src/emip3.ts` This TypeScript module provides functions to encrypt and decrypt data using the ChaCha20-Poly1305 cipher, alongside PBKDF2 with SHA-512 for key derivation. It leverages the `@noble/ciphers` and `@noble/hashes` libraries. @@ -132,7 +129,6 @@ Returns a promise that resolves with the decrypted data as a Uint8Array. 1. **Encryption**: Call `emip3encrypt` with plaintext data and a passphrase to get encrypted data. 2. **Decryption**: Call `emip3decrypt` with the encrypted data (including salt and nonce) and the same passphrase to decrypt and obtain the original plaintext. - # `src/keyDecryptor.ts` This TypeScript module introduces the `KeyDecryptor` class, designed to decrypt encrypted private keys and seed bytes using a passphrase. It depends on the previously documented `emip3.ts` for the decryption process, as well as custom error handling and type definitions from other modules within the same project. @@ -195,4 +191,4 @@ Instantiate a `KeyDecryptor` with a function to retrieve the user's passphrase. ## Notes -- This module is designed for integration within a system that manages cryptographic keys and requires secure, passphrase-based decryption of keys or seed information. \ No newline at end of file +- This module is designed for integration within a system that manages cryptographic keys and requires secure, passphrase-based decryption of keys or seed information. diff --git a/packages/key-management/package.json b/packages/key-management/package.json index 0d1cf7eb..e91049b9 100644 --- a/packages/key-management/package.json +++ b/packages/key-management/package.json @@ -34,8 +34,7 @@ "micro-starknet": "0.2.3", "mina-signer": "3.0.7", "sinon": "18.0.0", - "ts-custom-error": "3.3.1", - "vitest": "2.0.4" + "ts-custom-error": "3.3.1" }, "devDependencies": { "@palladxyz/common": "workspace:*", diff --git a/packages/key-management/src/InMemoryKeyAgent.ts b/packages/key-management/src/InMemoryKeyAgent.ts index f2d58637..ac352515 100644 --- a/packages/key-management/src/InMemoryKeyAgent.ts +++ b/packages/key-management/src/InMemoryKeyAgent.ts @@ -26,15 +26,6 @@ export interface FromBip39MnemonicWordsProps { getPassphrase: GetPassphrase } -export const getPassphraseRethrowTypedError = async ( - getPassphrase: GetPassphrase, -) => { - try { - return await getPassphrase() - } catch (error) { - throw new errors.AuthenticationError("Failed to enter passphrase", error) - } -} export class InMemoryKeyAgent extends KeyAgentBase implements KeyAgent { static async fromMnemonicWords({ getPassphrase, @@ -45,7 +36,7 @@ export class InMemoryKeyAgent extends KeyAgentBase implements KeyAgent { const validMnemonic = validateMnemonic(mnemonic, wordlist) if (!validMnemonic) throw new errors.InvalidMnemonicError() - const passphrase = await getPassphraseRethrowTypedError(getPassphrase) + const passphrase = getPassphrase() const encryptedSeedBytes = await mnemonicWordsToEncryptedSeed( mnemonicWords, passphrase, diff --git a/packages/key-management/src/KeyAgentBase.ts b/packages/key-management/src/KeyAgentBase.ts index 90fb8775..a3abd9d9 100644 --- a/packages/key-management/src/KeyAgentBase.ts +++ b/packages/key-management/src/KeyAgentBase.ts @@ -1,6 +1,7 @@ import { HDKey } from "@scure/bip32" -import { getPassphraseRethrowTypedError } from "./InMemoryKeyAgent" +import { bytesToUtf8 } from "@noble/ciphers/utils" +import { utf8ToBytes } from "@noble/hashes/utils" import { KeyDecryptor } from "./KeyDecryptor" import { type EthereumSignablePayload, @@ -76,7 +77,7 @@ export abstract class KeyAgentBase implements KeyAgent { getPassphrase: GetPassphrase, pure?: boolean, ): Promise { - const passphrase = await getPassphraseRethrowTypedError(getPassphrase) + const passphrase = getPassphrase() const matcher = credentialMatchers[args.network] if (!matcher) { throw new Error(`Unsupported network: ${args.network}`) @@ -123,7 +124,7 @@ export abstract class KeyAgentBase implements KeyAgent { let privateKey: ChainPrivateKey | null privateKey = await this.#generatePrivateKeyFromSeed(args) const encryptedPrivateKeyBytes = await emip3encrypt( - Buffer.from(privateKey), + typeof privateKey === "string" ? utf8ToBytes(privateKey) : privateKey, passphrase, ) const provider = createChainDerivationOperationsProvider(args) @@ -134,14 +135,14 @@ export abstract class KeyAgentBase implements KeyAgent { encryptedPrivateKeyBytes, } // Overwrite and nullify the privateKey - privateKey = "0".repeat(privateKey.length) + privateKey = utf8ToBytes("0".repeat(privateKey.length)) privateKey = null return keyPair } catch (error) { // Overwrite and nullify the privateKey if (privateKey) { - privateKey = "0".repeat(privateKey.length) + privateKey = utf8ToBytes("0".repeat(privateKey.length)) privateKey = null } console.error(error) @@ -154,12 +155,11 @@ export abstract class KeyAgentBase implements KeyAgent { signable: ChainSignablePayload, args: ChainOperationArgs, ): Promise { - const encryptedPrivateKeyBytes = payload.encryptedPrivateKeyBytes const decryptedKeyBytes = await this.keyDecryptor.decryptChildPrivateKey( - encryptedPrivateKeyBytes, + new Uint8Array(Object.values(payload.encryptedPrivateKeyBytes)), ) - let privateKey: string | null = Buffer.from(decryptedKeyBytes).toString() + let privateKey: string | null = bytesToUtf8(decryptedKeyBytes) try { let result @@ -201,6 +201,6 @@ export abstract class KeyAgentBase implements KeyAgent { const decryptedSeedBytes = await this.decryptSeed() const provider = createChainDerivationOperationsProvider(args) - return provider.derivePrivateKey(decryptedSeedBytes) + return await provider.derivePrivateKey(decryptedSeedBytes) } } diff --git a/packages/key-management/src/KeyDecryptor.ts b/packages/key-management/src/KeyDecryptor.ts index d1ddb471..9fa0bdef 100644 --- a/packages/key-management/src/KeyDecryptor.ts +++ b/packages/key-management/src/KeyDecryptor.ts @@ -1,4 +1,3 @@ -import { getPassphraseRethrowTypedError } from "./InMemoryKeyAgent" import { emip3decrypt } from "./emip3" import * as errors from "./errors" import type { @@ -8,7 +7,7 @@ import type { } from "./types" export class KeyDecryptor { - #getPassphrase: (noCache?: true) => Promise + #getPassphrase: (noCache?: true) => Uint8Array constructor(getPassphrase: GetPassphrase) { this.#getPassphrase = getPassphrase @@ -18,13 +17,11 @@ export class KeyDecryptor { encryptedPrivateKeyBytes: Uint8Array, noCache?: true, ): Promise { - const passphrase = await getPassphraseRethrowTypedError(() => - this.#getPassphrase(noCache), - ) + const passphrase = this.#getPassphrase(noCache) let decryptedKeyBytes: Uint8Array try { decryptedKeyBytes = await emip3decrypt( - new Uint8Array(encryptedPrivateKeyBytes), + encryptedPrivateKeyBytes, passphrase, ) } catch (error) { @@ -51,9 +48,7 @@ export class KeyDecryptor { errorMessage: string, noCache?: true, ) { - const passphrase = await getPassphraseRethrowTypedError(() => - this.#getPassphrase(noCache), - ) + const passphrase = this.#getPassphrase(noCache) let decryptedKeyBytes: Uint8Array try { decryptedKeyBytes = await emip3decrypt( diff --git a/packages/key-management/src/SessionKeyAgentBase.ts b/packages/key-management/src/SessionKeyAgentBase.ts index 05e7c984..d3d8038f 100644 --- a/packages/key-management/src/SessionKeyAgentBase.ts +++ b/packages/key-management/src/SessionKeyAgentBase.ts @@ -1,3 +1,4 @@ +import { bytesToUtf8 } from "@noble/ciphers/utils" import { type EthereumSignablePayload, EthereumSigningOperations, @@ -66,7 +67,7 @@ export abstract class SessionKeyAgentBase implements SessionKeyAgent { ): Promise { const privateKeyBytes = payload.privateKeyBytes - let privateKey: string | null = Buffer.from(privateKeyBytes).toString() + let privateKey: string | null = bytesToUtf8(privateKeyBytes) try { let result @@ -110,6 +111,6 @@ export abstract class SessionKeyAgentBase implements SessionKeyAgent { const seedBytes = bip39.entropyToSeed(entropy) const provider = createChainDerivationOperationsProvider(args) const privateKey = await provider.derivePrivateKey(seedBytes) - return Buffer.from(privateKey) + return privateKey } } diff --git a/packages/key-management/src/chains/Ethereum/credentialDerivation.ts b/packages/key-management/src/chains/Ethereum/credentialDerivation.ts index 3b4d0278..bc2eb6e6 100644 --- a/packages/key-management/src/chains/Ethereum/credentialDerivation.ts +++ b/packages/key-management/src/chains/Ethereum/credentialDerivation.ts @@ -34,9 +34,7 @@ export const privateToPublic = (privateKey: Uint8Array): Uint8Array => { } export function deriveEthereumPublicKey(privateKey: Uint8Array): string { - const privateKeyBuffer = Buffer.from(privateKey) - const publicKey = privateToPublic(privateKeyBuffer) - + const publicKey = privateToPublic(privateKey) return bytesToHex(publicKey) } diff --git a/packages/key-management/src/chains/Ethereum/keyDerivation.ts b/packages/key-management/src/chains/Ethereum/keyDerivation.ts index 3db875d7..7d05467e 100644 --- a/packages/key-management/src/chains/Ethereum/keyDerivation.ts +++ b/packages/key-management/src/chains/Ethereum/keyDerivation.ts @@ -9,7 +9,7 @@ import { export function deriveEthereumPrivateKey( args: EthereumSpecificArgs | EthereumDerivationArgs, decryptedSeedBytes: Uint8Array, -): string { +): Uint8Array { const { accountIndex, addressIndex } = args // Create an HDKey from the root private key @@ -18,8 +18,5 @@ export function deriveEthereumPrivateKey( const childNode = rootKey.derive(path) if (!childNode?.privateKey) throw new Error("Unable to derive private key") - const privateKey = childNode.privateKey - // maybe want to return bufferToHex(privateKey) - const privateKeyHex = Buffer.from(privateKey).toString("hex") - return privateKeyHex + return childNode.privateKey } diff --git a/packages/key-management/src/chains/Ethereum/types.ts b/packages/key-management/src/chains/Ethereum/types.ts index 72a624d2..d9c95382 100644 --- a/packages/key-management/src/chains/Ethereum/types.ts +++ b/packages/key-management/src/chains/Ethereum/types.ts @@ -67,7 +67,7 @@ export class EthereumPayload implements ChainSpecificPayload { ) } derivePrivateKey(decryptedSeedBytes: Uint8Array, args: EthereumSpecificArgs) { - return new Promise((resolve) => + return new Promise((resolve) => resolve(deriveEthereumPrivateKey(args, decryptedSeedBytes)), ) } diff --git a/packages/key-management/src/chains/Mina/credentialDerivation.ts b/packages/key-management/src/chains/Mina/credentialDerivation.ts index 78c9f9c6..b46d249b 100644 --- a/packages/key-management/src/chains/Mina/credentialDerivation.ts +++ b/packages/key-management/src/chains/Mina/credentialDerivation.ts @@ -7,12 +7,13 @@ import type { MinaSessionCredentials, } from "./types" -export function deriveMinaPublicKey(privateKey: string): Mina.PublicKey { +export function deriveMinaPublicKey(privateKey: Uint8Array): Mina.PublicKey { // Mina network client. // TODO: Check if the public key is different based on client networkType const minaClient = new Client({ network: "mainnet" }) // Derive and return the Mina public key - const publicKey = minaClient.derivePublicKey(privateKey) + const privateKeyString = new TextDecoder().decode(privateKey) + const publicKey = minaClient.derivePublicKeyUnsafe(privateKeyString) return publicKey as Mina.PublicKey } diff --git a/packages/key-management/src/chains/Mina/keyDerivation.ts b/packages/key-management/src/chains/Mina/keyDerivation.ts index e368b9d8..e6b28509 100644 --- a/packages/key-management/src/chains/Mina/keyDerivation.ts +++ b/packages/key-management/src/chains/Mina/keyDerivation.ts @@ -1,14 +1,14 @@ import { sha256 } from "@noble/hashes/sha256" +import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils" import { base58check } from "@scure/base" import { HDKey } from "@scure/bip32" -import { reverseBytes } from "./keyDerivationUtils" import { type MinaDerivationArgs, MinaKeyConst } from "./types" export function deriveMinaPrivateKey( args: MinaDerivationArgs, decryptedSeedBytes: Uint8Array, -) { +): Uint8Array { const { accountIndex, addressIndex } = args // Create an HDKey from the root private key @@ -19,13 +19,12 @@ export function deriveMinaPrivateKey( if (!childNode?.privateKey?.[0]) { childNode.privateKey.set([0x3f], 0) } - const childPrivateKey = reverseBytes(Buffer.from(childNode.privateKey)) - const privateKeyHex = `5a01${childPrivateKey.toString("hex")}` + const childPrivateKey = childNode.privateKey.reverse() + const privateKeyHex = `5a01${bytesToHex(childPrivateKey)}` // Convert the hex string to a Uint8Array if (!privateKeyHex) { throw new Error("privateKeyHex is empty") } - const hexMatches = privateKeyHex.match(/.{1,2}/g) if (!hexMatches) { throw new Error("Failed to split privateKeyHex into bytes") @@ -36,5 +35,5 @@ export function deriveMinaPrivateKey( // Encode the Uint8Array into a base58 string with checksum const privateKey = base58check(sha256).encode(privateKeyBytes) - return privateKey + return utf8ToBytes(privateKey) } diff --git a/packages/key-management/src/chains/Mina/keyDerivationUtils.ts b/packages/key-management/src/chains/Mina/keyDerivationUtils.ts index 0e87b037..8325595a 100644 --- a/packages/key-management/src/chains/Mina/keyDerivationUtils.ts +++ b/packages/key-management/src/chains/Mina/keyDerivationUtils.ts @@ -2,17 +2,6 @@ import { Network } from "@palladxyz/pallad-core" import type { MinaDerivationArgs } from "./types" -/** - * Reverses the order of bytes in a buffer. - * - * @param bytes - Buffer containing bytes to reverse. - * @returns Buffer with bytes in reverse order. - */ -export function reverseBytes(bytes: Buffer) { - const uint8 = new Uint8Array(bytes) - return Buffer.from(uint8.reverse()) -} - export function isMinaDerivation(args: MinaDerivationArgs): boolean { // check if derivation args match Mina return args.network === Network.Mina diff --git a/packages/key-management/src/chains/Mina/types.ts b/packages/key-management/src/chains/Mina/types.ts index 8eefaade..05f6e3e0 100644 --- a/packages/key-management/src/chains/Mina/types.ts +++ b/packages/key-management/src/chains/Mina/types.ts @@ -74,13 +74,13 @@ export type MinaSignablePayload = export class MinaPayload implements ChainSpecificPayload { network = Network.Mina - derivePublicKey(privateKey: string) { + derivePublicKey(privateKey: Uint8Array) { return new Promise((resolve) => resolve(deriveMinaPublicKey(privateKey)), ) } derivePrivateKey(decryptedSeedBytes: Uint8Array, args: MinaSpecificArgs) { - return new Promise((resolve) => + return new Promise((resolve) => resolve(deriveMinaPrivateKey(args, decryptedSeedBytes)), ) } @@ -88,8 +88,8 @@ export class MinaPayload implements ChainSpecificPayload { // new functional implementation of MinaPayload export const minaKeyPairDerivationOperations: KeyPairDerivationOperations = { - derivePublicKey: (privateKey: Uint8Array | string) => { - if (typeof privateKey === "string") { + derivePublicKey: (privateKey: Uint8Array) => { + if (privateKey instanceof Uint8Array) { return Promise.resolve(deriveMinaPublicKey(privateKey)) } throw new Error("Invalid type for privateKey - string required.") diff --git a/packages/key-management/src/emip3.ts b/packages/key-management/src/emip3.ts index bb562162..8d8b87ab 100644 --- a/packages/key-management/src/emip3.ts +++ b/packages/key-management/src/emip3.ts @@ -2,6 +2,7 @@ import { chacha20poly1305 } from "@noble/ciphers/chacha" import { randomBytes } from "@noble/ciphers/webcrypto" import { pbkdf2Async } from "@noble/hashes/pbkdf2" import { sha512 } from "@noble/hashes/sha512" +import { concatBytes } from "@noble/hashes/utils" const KEY_LENGTH = 32 const NONCE_LENGTH = 12 @@ -12,7 +13,7 @@ export const createPbkdf2Key = async ( passphrase: Uint8Array, salt: Uint8Array | Uint16Array, ) => { - const saltAsUint8Array = new Uint8Array(salt.buffer) + const saltAsUint8Array = new Uint8Array(salt) const derivedKey = await pbkdf2Async(sha512, passphrase, saltAsUint8Array, { c: PBKDF2_ITERATIONS, dkLen: KEY_LENGTH, @@ -29,7 +30,7 @@ export const emip3encrypt = async ( const nonce = randomBytes(NONCE_LENGTH) const cipher = chacha20poly1305(key, nonce) const encrypted = cipher.encrypt(data) - return Buffer.concat([salt, nonce, encrypted]) + return concatBytes(salt, nonce, encrypted) } export const emip3decrypt = async ( diff --git a/packages/key-management/src/types.ts b/packages/key-management/src/types.ts index 6a0ab41a..8a726eaf 100644 --- a/packages/key-management/src/types.ts +++ b/packages/key-management/src/types.ts @@ -95,19 +95,19 @@ export const credentialMatchers: Record> = { // other new ones that work export interface KeyPairDerivationOperations { - derivePublicKey: (privateKey: Uint8Array | string) => Promise + derivePublicKey: (privateKey: Uint8Array) => Promise derivePrivateKey: ( decryptedSeedBytes: Uint8Array, args: T, - ) => Promise + ) => Promise } export const createChainDerivationOperationsProvider = ( args: ChainDerivationArgs, ) => { - const derivePublicKey = (privateKey: Uint8Array | string) => { + const derivePublicKey = (privateKey: Uint8Array) => { if (args.network === Network.Mina) { - return minaKeyPairDerivationOperations.derivePublicKey(String(privateKey)) + return minaKeyPairDerivationOperations.derivePublicKey(privateKey) } if (args.network === Network.Ethereum) { return ethKeyPairDerivationOperations.derivePublicKey(privateKey) @@ -149,7 +149,7 @@ export type ChainAddress = Mina.PublicKey | string /** * @returns passphrase used to decrypt private keys */ -export type GetPassphrase = (noCache?: boolean) => Promise +export type GetPassphrase = (noCache?: boolean) => Uint8Array export interface AccountKeyDerivationPath { account_ix: number @@ -232,7 +232,7 @@ export type ChainPublicKey = Mina.PublicKey | string export type ChainSignatureResult = MinaSignatureResult | EthereumSignatureResult -export type ChainPrivateKey = string | Uint8Array +export type ChainPrivateKey = Uint8Array export type ChainKeyPair = { publicKey: ChainPublicKey diff --git a/packages/key-management/src/util/bip39.ts b/packages/key-management/src/util/bip39.ts index c5c8610a..111fbc02 100644 --- a/packages/key-management/src/util/bip39.ts +++ b/packages/key-management/src/util/bip39.ts @@ -34,7 +34,7 @@ export const entropyToSeed = (entropy: Uint8Array, passphrase?: string) => { // Get root key from seed //const root = bip32.HDKey.fromMasterSeed(seed) // Return unencrypted root key bytes - return seed //root.privateKey ? root.privateKey : Buffer.from([]) + return seed //root.privateKey ? root.privateKey : Uint8Array } /** diff --git a/packages/key-management/src/util/key.ts b/packages/key-management/src/util/key.ts index 49031796..b40f8b7c 100644 --- a/packages/key-management/src/util/key.ts +++ b/packages/key-management/src/util/key.ts @@ -12,5 +12,5 @@ export const deriveCoinTypePrivateKey = async ({ const coinTypeKey = await bip32.HDKey.fromMasterSeed(rootPrivateKey) .deriveChild(MinaKeyConst.PURPOSE) .deriveChild(MinaKeyConst.MINA_COIN_TYPE) - return coinTypeKey.privateKey ? coinTypeKey.privateKey : Buffer.from([]) + return coinTypeKey.privateKey ? coinTypeKey.privateKey : new Uint8Array([]) } diff --git a/packages/key-management/test/ethereum/credential-derivation.test.ts b/packages/key-management/test/ethereum/credential-derivation.test.ts index 627d2a92..4b2495f6 100644 --- a/packages/key-management/test/ethereum/credential-derivation.test.ts +++ b/packages/key-management/test/ethereum/credential-derivation.test.ts @@ -1,6 +1,7 @@ import { Network } from "@palladxyz/pallad-core" import { describe, expect, it } from "vitest" +import { hexToBytes } from "@noble/hashes/utils" import type { EthereumDerivationArgs, EthereumGroupedCredentials, @@ -19,9 +20,7 @@ import { isEthereumDerivation } from "../../src/chains/Ethereum/keyDerivationUti describe("credentialderivation utils", () => { const validPrivateKeyHex = "ab8e7c879d7a802940c7a6535752ee6d3064f7dcbb25b4d2cd90c1f8efdb61f0" - const validPrivateKeyBytes = Uint8Array.from( - Buffer.from(validPrivateKeyHex, "hex"), - ) + const validPrivateKeyBytes = hexToBytes(validPrivateKeyHex) const expectedPublicKey = "0xA98005e6ce8E62ADf8f9020fa99888E8f107e3C9" const expectedGroupedCredentials: EthereumGroupedCredentials = { diff --git a/packages/key-management/test/ethereum/in-memory-key-agent.test.ts b/packages/key-management/test/ethereum/in-memory-key-agent.test.ts index 9b8605eb..a98b035d 100644 --- a/packages/key-management/test/ethereum/in-memory-key-agent.test.ts +++ b/packages/key-management/test/ethereum/in-memory-key-agent.test.ts @@ -5,11 +5,11 @@ import { type SignatureLike, ethers, hashMessage, recoverAddress } from "ethers" import sinon from "sinon" import { expect } from "vitest" +import { utf8ToBytes } from "@noble/hashes/utils" import type { ChainOperationArgs, ChainSignablePayload } from "../../src" //import { emip3encrypt } from '../src/emip3' import { type FromBip39MnemonicWordsProps, - //getPassphraseRethrowTypedError, InMemoryKeyAgent, } from "../../src/InMemoryKeyAgent" import type { EthereumSpecificArgs } from "../../src/chains/Ethereum" @@ -22,8 +22,7 @@ const sandbox = sinon.createSandbox() const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe("InMemoryKeyAgent", () => { let agent: InMemoryKeyAgent @@ -38,7 +37,7 @@ describe("InMemoryKeyAgent", () => { // Create root node from seed root = bip32.HDKey.fromMasterSeed(seed) // unencrypted root key bytes - rootKeyBytes = root.privateKey ? root.privateKey : Buffer.from([]) + rootKeyBytes = root.privateKey ? root.privateKey : new Uint8Array([]) // define the agent properties //encryptedSeedBytes = await emip3encrypt(seed, passphrase) const agentArgs: FromBip39MnemonicWordsProps = { @@ -65,7 +64,7 @@ describe("InMemoryKeyAgent", () => { /* // Need to fix this test it('should throw error when decrypting root private key fails', async () => { - const fakeGetPassphrase = async () => Buffer.from('wrong_passphrase'); + const fakeGetPassphrase = () => utf8ToBytes('wrong_passphrase'); const agentFromBip39 = await InMemoryKeyAgent.fromBip39MnemonicWords({ getPassphrase: fakeGetPassphrase, mnemonicWords: mnemonic @@ -73,7 +72,7 @@ describe("InMemoryKeyAgent", () => { await expect(agentFromBip39.decryptSeed()).rejects.toThrow('Failed to decrypt root private key'); }); it('should throw error when decrypting coin type private key fails', async () => { - const fakeGetPassphrase = async () => Buffer.from('wrong_passphrase'); + const fakeGetPassphrase = () => utf8ToBytes('wrong_passphrase'); const agentFromBip39 = await InMemoryKeyAgent.fromBip39MnemonicWords({ getPassphrase: fakeGetPassphrase, mnemonicWords: mnemonic diff --git a/packages/key-management/test/ethereum/key-agent-base.test.ts b/packages/key-management/test/ethereum/key-agent-base.test.ts index a0c0f18e..76488794 100644 --- a/packages/key-management/test/ethereum/key-agent-base.test.ts +++ b/packages/key-management/test/ethereum/key-agent-base.test.ts @@ -5,8 +5,8 @@ import { verifyMessage } from "ethers" import sinon from "sinon" import { expect } from "vitest" +import { utf8ToBytes } from "@noble/hashes/utils" import type { EthereumSpecificArgs } from "../../src" -import { getPassphraseRethrowTypedError } from "../../src/InMemoryKeyAgent" import { KeyAgentBase } from "../../src/KeyAgentBase" import { emip3encrypt } from "../../src/emip3" import { @@ -21,8 +21,7 @@ import * as util from "../../src/util/bip39" const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe("KeyAgentBase (Ethereum Functionality)", () => { class KeyAgentBaseInstance extends KeyAgentBase {} @@ -43,9 +42,7 @@ describe("KeyAgentBase (Ethereum Functionality)", () => { rootKeyBytes = root.privateKey ? root.privateKey : new Uint8Array([]) // passphrase - passphrase = await getPassphraseRethrowTypedError(getPassphrase) - // define the agent properties - passphrase = await getPassphraseRethrowTypedError(getPassphrase) + passphrase = getPassphrase() // Works with seed encryptedSeedBytes = await emip3encrypt(seed, passphrase) }) diff --git a/packages/key-management/test/keyDecryptor.test.ts b/packages/key-management/test/keyDecryptor.test.ts index 09486d3a..0a0c2f75 100644 --- a/packages/key-management/test/keyDecryptor.test.ts +++ b/packages/key-management/test/keyDecryptor.test.ts @@ -11,9 +11,7 @@ import { emip3encrypt } from "../src/emip3" describe("KeyDecryptor", () => { const passphrase = new Uint8Array([1, 2, 3, 4, 5]) - const getPassphrase = async () => { - return await Promise.resolve(passphrase) - } + const getPassphrase = () => passphrase let mnemonic: string[] let seed: Uint8Array let encryptedPrivateKey: Uint8Array diff --git a/packages/key-management/test/mina/in-memory-key-agent.test.ts b/packages/key-management/test/mina/in-memory-key-agent.test.ts index a95b4993..76263fb0 100644 --- a/packages/key-management/test/mina/in-memory-key-agent.test.ts +++ b/packages/key-management/test/mina/in-memory-key-agent.test.ts @@ -6,10 +6,10 @@ import Client from "mina-signer" import sinon from "sinon" import { expect } from "vitest" +import { utf8ToBytes } from "@noble/hashes/utils" //import { emip3encrypt } from '../src/emip3' import { type FromBip39MnemonicWordsProps, - //getPassphraseRethrowTypedError, InMemoryKeyAgent, } from "../../src/InMemoryKeyAgent" import type { @@ -25,8 +25,7 @@ const sandbox = sinon.createSandbox() const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe("Mina InMemoryKeyAgent", () => { let agent: InMemoryKeyAgent @@ -42,7 +41,7 @@ describe("Mina InMemoryKeyAgent", () => { // Create root node from seed root = bip32.HDKey.fromMasterSeed(seed) // unencrypted root key bytes - rootKeyBytes = root.privateKey ? root.privateKey : Buffer.from([]) + rootKeyBytes = root.privateKey ? root.privateKey : new Uint8Array([]) // define the agent properties //encryptedSeedBytes = await emip3encrypt(seed, passphrase) const agentArgs: FromBip39MnemonicWordsProps = { @@ -75,7 +74,7 @@ describe("Mina InMemoryKeyAgent", () => { /* // Need to fix this test it('should throw error when decrypting root private key fails', async () => { - const fakeGetPassphrase = async () => Buffer.from('wrong_passphrase'); + const fakeGetPassphrase = () => utf8ToBytes('wrong_passphrase'); const agentFromBip39 = await InMemoryKeyAgent.fromBip39MnemonicWords({ getPassphrase: fakeGetPassphrase, mnemonicWords: mnemonic @@ -83,7 +82,7 @@ describe("Mina InMemoryKeyAgent", () => { await expect(agentFromBip39.decryptSeed()).rejects.toThrow('Failed to decrypt root private key'); }); it('should throw error when decrypting coin type private key fails', async () => { - const fakeGetPassphrase = async () => Buffer.from('wrong_passphrase'); + const fakeGetPassphrase = () => utf8ToBytes('wrong_passphrase'); const agentFromBip39 = await InMemoryKeyAgent.fromBip39MnemonicWords({ getPassphrase: fakeGetPassphrase, mnemonicWords: mnemonic diff --git a/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts b/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts index 8fdf45c6..3a80b4a6 100644 --- a/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts +++ b/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts @@ -5,7 +5,7 @@ import Client from "mina-signer" import sinon from "sinon" import { expect } from "vitest" -import { getPassphraseRethrowTypedError } from "../../src/InMemoryKeyAgent" +import { utf8ToBytes } from "@noble/hashes/utils" import { KeyAgentBase } from "../../src/KeyAgentBase" import type { MinaSpecificArgs } from "../../src/chains/Mina" import { emip3encrypt } from "../../src/emip3" @@ -21,8 +21,7 @@ import * as util from "../../src/util/bip39" const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe("KeyAgentBase (Mina zkApp Functionality)", () => { class KeyAgentBaseInstance extends KeyAgentBase {} @@ -39,9 +38,7 @@ describe("KeyAgentBase (Mina zkApp Functionality)", () => { const seed = util.mnemonicToSeed(mnemonic) // passphrase - passphrase = await getPassphraseRethrowTypedError(getPassphrase) - // define the agent properties - passphrase = await getPassphraseRethrowTypedError(getPassphrase) + passphrase = getPassphrase() // Works with seed encryptedSeedBytes = await emip3encrypt(seed, passphrase) }) diff --git a/packages/key-management/test/mina/key-agent-base.test.ts b/packages/key-management/test/mina/key-agent-base.test.ts index e68b0fcd..17f3fd77 100644 --- a/packages/key-management/test/mina/key-agent-base.test.ts +++ b/packages/key-management/test/mina/key-agent-base.test.ts @@ -7,14 +7,13 @@ import Client from "mina-signer" import sinon from "sinon" import { expect } from "vitest" +import { hexToBytes, utf8ToBytes } from "@noble/hashes/utils" import type { MinaDerivationArgs } from "../../dist" -import { getPassphraseRethrowTypedError } from "../../src/InMemoryKeyAgent" import { KeyAgentBase } from "../../src/KeyAgentBase" import { type MinaSpecificArgs, deriveMinaPrivateKey, } from "../../src/chains/Mina" -import { reverseBytes } from "../../src/chains/Mina/keyDerivationUtils" import { emip3encrypt } from "../../src/emip3" import { type ChainOperationArgs, @@ -29,13 +28,9 @@ const params = { passphrase: "passphrase", incorrectPassphrase: "not correct passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) -const getWrongPassphrase = () => - new Promise((resolve) => - resolve(Buffer.from(params.incorrectPassphrase)), - ) +const getWrongPassphrase = () => utf8ToBytes(params.incorrectPassphrase) describe("KeyAgentBase (Mina Functionality)", () => { class KeyAgentBaseInstance extends KeyAgentBase {} @@ -58,9 +53,7 @@ describe("KeyAgentBase (Mina Functionality)", () => { rootKeyBytes = root.privateKey ? root.privateKey : new Uint8Array([]) // passphrase - passphrase = await getPassphraseRethrowTypedError(getPassphrase) - // define the agent properties - passphrase = await getPassphraseRethrowTypedError(getPassphrase) + passphrase = getPassphrase() // Works with seed encryptedSeedBytes = await emip3encrypt(seed, passphrase) }) @@ -262,10 +255,10 @@ describe("KeyAgentBase (Mina Functionality)", () => { }) it("should reverse bytes correctly", () => { - const originalBuffer = Buffer.from("1234", "hex") - const reversedBuffer = Buffer.from("3412", "hex") + const originalBuffer = hexToBytes("1234") + const reversedBuffer = hexToBytes("4321") - expect(reverseBytes(originalBuffer)).to.deep.equal(reversedBuffer) + expect(originalBuffer.reverse()).to.deep.equal(reversedBuffer) }) it("should export root key successfully", async () => { diff --git a/packages/key-management/test/mina/sesion-key-agent-base.test.ts b/packages/key-management/test/mina/sesion-key-agent-base.test.ts index ce6b4ee0..d4f17e98 100644 --- a/packages/key-management/test/mina/sesion-key-agent-base.test.ts +++ b/packages/key-management/test/mina/sesion-key-agent-base.test.ts @@ -9,7 +9,7 @@ import type { MinaDerivationArgs } from "../../dist" import { SessionKeyAgentBase } from "../../src" import type { ChainOperationArgs } from "../../src/types" -describe("SessionKeyAgentBase (Mina Functionality)", () => { +describe.skip("SessionKeyAgentBase (Mina Functionality)", () => { let instance: SessionKeyAgentBase let networkType: Mina.NetworkType diff --git a/packages/key-management/tsconfig.json b/packages/key-management/tsconfig.json index f4e2e06e..720b8f4c 100644 --- a/packages/key-management/tsconfig.json +++ b/packages/key-management/tsconfig.json @@ -1,3 +1,4 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladxyz/common/tsconfig.json", + "compilerOptions": { "types": ["vitest/globals"] } } diff --git a/packages/mina-core/README.md b/packages/mina-core/README.md index 56f79831..9e45f402 100644 --- a/packages/mina-core/README.md +++ b/packages/mina-core/README.md @@ -17,11 +17,10 @@ npm install @palladxyz/mina-core The `AccountInfoProvider` interface is used to fetch account information based on a public key. ```ts -import { AccountInfoProvider } from '@palladxyz/mina-core' +import { AccountInfoProvider } from "@palladxyz/mina-core"; async function getAccountInfo(provider: AccountInfoProvider) { - const accountInfo = await provider.getAccountInfo({ publicKey: '...' }) - console.log(accountInfo) + const accountInfo = await provider.getAccountInfo({ publicKey: "..." }); } ``` @@ -30,18 +29,16 @@ async function getAccountInfo(provider: AccountInfoProvider) { The `ChainHistoryProvider` interface provides methods to fetch transactions either by addresses or by hashes. ```ts -import { ChainHistoryProvider } from '@palladxyz/mina-core' +import { ChainHistoryProvider } from "@palladxyz/mina-core"; async function getTransactionsByAddresses(provider: ChainHistoryProvider) { const transactions = await provider.transactionsByAddresses({ - addresses: ['...'] - }) - console.log(transactions) + addresses: ["..."], + }); } async function getTransactionsByHashes(provider: ChainHistoryProvider) { - const transactions = await provider.transactionsByHashes({ ids: ['...'] }) - console.log(transactions) + const transactions = await provider.transactionsByHashes({ ids: ["..."] }); } ``` @@ -50,11 +47,11 @@ async function getTransactionsByHashes(provider: ChainHistoryProvider) { The `TxSubmitProvider` interface allows you to submit signed transactions to the network. ```ts -import { TxSubmitProvider } from '@palladxyz/mina-core' +import { TxSubmitProvider } from "@palladxyz/mina-core"; async function submitTx(provider: TxSubmitProvider) { const signedTx = // Prepare your signed transaction here - await provider.submitTx({ signedTransaction: signedTx }) + await provider.submitTx({ signedTransaction: signedTx }); } ``` @@ -63,13 +60,10 @@ async function submitTx(provider: TxSubmitProvider) { All provider types extend the base Provider interface, which provides a health check method to verify if the provider is operational. ```ts -import { Provider } from '@palladxyz/mina-core' +import { Provider } from "@palladxyz/mina-core"; async function checkHealth(provider: Provider) { - const healthCheckResponse = await provider.healthCheck() - console.log( - healthCheckResponse.ok ? 'Provider is healthy' : 'Provider is down' - ) + const healthCheckResponse = await provider.healthCheck(); } ``` diff --git a/packages/pallad-core/README.md b/packages/pallad-core/README.md index 557dc23c..09d88d82 100644 --- a/packages/pallad-core/README.md +++ b/packages/pallad-core/README.md @@ -17,11 +17,10 @@ npm install @palladxyz/mina-core The `AccountInfoProvider` interface is used to fetch account information based on a public key. ```ts -import { AccountInfoProvider } from '@palladxyz/mina-core' +import { AccountInfoProvider } from "@palladxyz/mina-core"; async function getAccountInfo(provider: AccountInfoProvider) { - const accountInfo = await provider.getAccountInfo({ publicKey: '...' }) - console.log(accountInfo) + const accountInfo = await provider.getAccountInfo({ publicKey: "..." }); } ``` @@ -30,18 +29,16 @@ async function getAccountInfo(provider: AccountInfoProvider) { The `ChainHistoryProvider` interface provides methods to fetch transactions either by addresses or by hashes. ```ts -import { ChainHistoryProvider } from '@palladxyz/mina-core' +import { ChainHistoryProvider } from "@palladxyz/mina-core"; async function getTransactionsByAddresses(provider: ChainHistoryProvider) { const transactions = await provider.transactionsByAddresses({ - addresses: ['...'] - }) - console.log(transactions) + addresses: ["..."], + }); } async function getTransactionsByHashes(provider: ChainHistoryProvider) { - const transactions = await provider.transactionsByHashes({ ids: ['...'] }) - console.log(transactions) + const transactions = await provider.transactionsByHashes({ ids: ["..."] }); } ``` @@ -50,11 +47,11 @@ async function getTransactionsByHashes(provider: ChainHistoryProvider) { The `TxSubmitProvider` interface allows you to submit signed transactions to the network. ```ts -import { TxSubmitProvider } from '@palladxyz/mina-core' +import { TxSubmitProvider } from "@palladxyz/mina-core"; async function submitTx(provider: TxSubmitProvider) { const signedTx = // Prepare your signed transaction here - await provider.submitTx({ signedTransaction: signedTx }) + await provider.submitTx({ signedTransaction: signedTx }); } ``` @@ -63,13 +60,10 @@ async function submitTx(provider: TxSubmitProvider) { All provider types extend the base Provider interface, which provides a health check method to verify if the provider is operational. ```ts -import { Provider } from '@palladxyz/mina-core' +import { Provider } from "@palladxyz/mina-core"; async function checkHealth(provider: Provider) { - const healthCheckResponse = await provider.healthCheck() - console.log( - healthCheckResponse.ok ? 'Provider is healthy' : 'Provider is down' - ) + const healthCheckResponse = await provider.healthCheck(); } ``` diff --git a/packages/pallad-core/test/Mina/custom-token-tx.test.ts b/packages/pallad-core/test/Mina/custom-token-tx.test.ts index 48e1e749..2b92d056 100644 --- a/packages/pallad-core/test/Mina/custom-token-tx.test.ts +++ b/packages/pallad-core/test/Mina/custom-token-tx.test.ts @@ -47,8 +47,7 @@ const sandbox = sinon.createSandbox() const params = { passphrase: 'passphrase' } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe('Mina InMemoryKeyAgent Signing Custom Token Transaction', () => { let agent: InMemoryKeyAgent @@ -120,7 +119,6 @@ describe('Mina InMemoryKeyAgent Signing Custom Token Transaction', () => { const decryptedChildKey = Buffer.from( await decryptor.decryptChildPrivateKey(encryptedChildKey as Uint8Array) ).toString() - console.log('decrypted child key:', decryptedChildKey) }) }) @@ -152,7 +150,6 @@ describe('Mina InMemoryKeyAgent Signing Custom Token Transaction', () => { } const signedTx = await agent.sign(groupedCredentials, tx, operationArgs) - console.log('signedTx', signedTx) }) }) }) diff --git a/packages/persistence/README.md b/packages/persistence/README.md deleted file mode 100644 index 2d657f03..00000000 --- a/packages/persistence/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @palladxyz/persistence - -Package for persisting wallet related data. diff --git a/packages/persistence/package.json b/packages/persistence/package.json deleted file mode 100644 index cbd63f40..00000000 --- a/packages/persistence/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@palladxyz/persistence", - "version": "1.0.0", - "type": "module", - "module": "dist/index.js", - "types": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "scripts": { - "build": "tsup", - "dev": "tsup --watch", - "cleanup": "rimraf node_modules dist .turbo" - }, - "dependencies": { - "@plasmohq/storage": "1.11.0", - "superjson": "2.2.1" - }, - "devDependencies": { - "@palladxyz/common": "workspace:*", - "zustand": "4.5.4" - } -} diff --git a/packages/persistence/src/index.ts b/packages/persistence/src/index.ts deleted file mode 100644 index a2fb927b..00000000 --- a/packages/persistence/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as webPersistence from "./web" - -export const getLocalPersistence = () => webPersistence.localPersistence - -export const getSessionPersistence = () => webPersistence.sessionPersistence - -export const getSecurePersistence = () => webPersistence.securePersistence diff --git a/packages/persistence/src/typings.ts b/packages/persistence/src/typings.ts deleted file mode 100644 index c196b221..00000000 --- a/packages/persistence/src/typings.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module "mina-signer" - -interface ImportMetaEnv { - readonly VITE_APP_MODE: string -} - -interface ImportMeta { - readonly env: ImportMetaEnv -} diff --git a/packages/persistence/tsconfig.json b/packages/persistence/tsconfig.json deleted file mode 100644 index 14f0cdb4..00000000 --- a/packages/persistence/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "@palladxyz/common/tsconfig.json", - "compilerOptions": { - "target": "esnext", - "module": "esnext" - } -} diff --git a/packages/persistence/tsup.config.ts b/packages/persistence/tsup.config.ts deleted file mode 100644 index 8449a56d..00000000 --- a/packages/persistence/tsup.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { baseTsupConfig } from "@palladxyz/common" -import { defineConfig } from "tsup" - -import packageJson from "./package.json" - -export default defineConfig([ - { - ...baseTsupConfig, - name: packageJson.name, - }, -]) diff --git a/packages/providers/package.json b/packages/providers/package.json index 52eb324f..d7069ed3 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -18,6 +18,7 @@ "cleanup": "rimraf node_modules dist .turbo" }, "dependencies": { + "@noble/hashes": "1.4.0", "@palladxyz/key-management": "workspace:*", "@palladxyz/mina-core": "workspace:*", "@palladxyz/pallad-core": "workspace:*", diff --git a/packages/providers/test/blockberry/chain-history-provider.test.ts b/packages/providers/test/blockberry/chain-history-provider.test.ts index 262a6e30..b1a1b33e 100644 --- a/packages/providers/test/blockberry/chain-history-provider.test.ts +++ b/packages/providers/test/blockberry/chain-history-provider.test.ts @@ -29,7 +29,6 @@ describe("Mina Explorer Chain History Provider (Functional)", () => { const response = (await provider.transactionsByAddresses({ addresses: [publicKey], })) as Mina.TransactionBody[] - console.log("response", response) // TODO: investigate pagination const transaction = response[0] diff --git a/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts b/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts index b198715f..8cd8556a 100644 --- a/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts +++ b/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts @@ -31,7 +31,6 @@ describe("Blockberry Account Info Provider (Functional)", () => { it("should return account info for a valid public key", async () => { // This test now depends on the actual response from the server const response = await provider.getAccountInfo({ publicKey, tokenMap }) - console.log("response", response) expect(response).toHaveProperty("MINA") }) }) diff --git a/packages/providers/test/mina-node/l1-mina-node/individual-providers/node-status-provider.test.ts b/packages/providers/test/mina-node/l1-mina-node/individual-providers/node-status-provider.test.ts index 83e2d232..1df615c9 100644 --- a/packages/providers/test/mina-node/l1-mina-node/individual-providers/node-status-provider.test.ts +++ b/packages/providers/test/mina-node/l1-mina-node/individual-providers/node-status-provider.test.ts @@ -23,7 +23,6 @@ describe("Blockberry Node Status Provider (Functional)", () => { it("should return account info for a valid public key", async () => { // This test now depends on the actual response from the server const response = await provider.getNodeStatus() - console.log("response", response) }) }) diff --git a/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts b/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts index cade3afa..745d18ee 100644 --- a/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts +++ b/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import { type ChainOperationArgs, type FromBip39MnemonicWordsProps, @@ -22,8 +23,7 @@ const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) // TODO: change this to local network // TODO: use different mnemonic for this test -- else there are two duplicate transactions with the unified provider tests describe.skip("Mina Explorer Submit Transaction Provider (Functional)", () => { @@ -128,11 +128,6 @@ describe.skip("Mina Explorer Submit Transaction Provider (Functional)", () => { } // This test now depends on the actual response from the server const response = await provider.submitTx(submitTxArgs) - console.log( - "Mina Explorer Submit Transaction Provider Response", - response, - ) - //expect(response).toHaveProperty('MINA') }) }) diff --git a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts index 5dbdde33..1ddf74fa 100644 --- a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts +++ b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import { type ChainOperationArgs, type FromBip39MnemonicWordsProps, @@ -24,8 +25,7 @@ const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) // TODO: change this to local network // TODO: use different mnemonic for this test -- else there are two duplicate transactions with the unified provider tests describe.skip("Zeko Sequencer Submit Transaction Provider (Functional)", () => { @@ -137,10 +137,6 @@ describe.skip("Zeko Sequencer Submit Transaction Provider (Functional)", () => { } // This test now depends on the actual response from the server const response = await provider.submitTx(submitTxArgs) - console.log( - "Zeko Sequencer Submit Transaction Provider Response", - response, - ) //expect(response).toHaveProperty('MINA') }) }) diff --git a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts index b9f82393..c7c1f2e6 100644 --- a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts +++ b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts @@ -50,5 +50,4 @@ export async function sendMinaOnZeko(nodeUrl: string): Promise { }, } const response = await provider.submitTx(submitTxArgs) - console.log("Zeko Sequencer Submit Transaction Provider Response", response) } diff --git a/packages/providers/test/open-mina/sync-provider.test.ts b/packages/providers/test/open-mina/sync-provider.test.ts index e68d0254..74e3b097 100644 --- a/packages/providers/test/open-mina/sync-provider.test.ts +++ b/packages/providers/test/open-mina/sync-provider.test.ts @@ -11,9 +11,6 @@ describe("Open Mina Provider", () => { }) test.skip("should return sync stats", async () => { const response = await localNodeSyncStats(url, "?limit=1") - //console.log('Open Mina Provider Response', response) - //console.log('Ledgers', response[0]?.ledgers) - //console.log('Blocks', response[0]?.blocks) expect(response[0]).toHaveProperty("synced") }) }) diff --git a/packages/providers/test/optimism/account-info/account-info-provider.test.ts b/packages/providers/test/optimism/account-info/account-info-provider.test.ts index 81417277..e9ffd566 100644 --- a/packages/providers/test/optimism/account-info/account-info-provider.test.ts +++ b/packages/providers/test/optimism/account-info/account-info-provider.test.ts @@ -32,7 +32,6 @@ describe.skip("Optimism Account Info Provider (Functional)", () => { chainInfo: optimismSepolia, } const response = await provider.getAccountInfo(args) - console.log("Optimism AccountInfo Provider Response", response) expect(response).toHaveProperty("ETH") }) }) diff --git a/packages/providers/test/optimism/chain-history/chain-history-provider.test.ts b/packages/providers/test/optimism/chain-history/chain-history-provider.test.ts index ac36fec3..9aadea1c 100644 --- a/packages/providers/test/optimism/chain-history/chain-history-provider.test.ts +++ b/packages/providers/test/optimism/chain-history/chain-history-provider.test.ts @@ -30,7 +30,6 @@ describe.skip("Optimism Chain History Provider (Functional)", () => { const response = await provider.transactionsByAddresses({ addresses: [publicKey], }) - console.log("Optimism transaction history:", response) expect(response[0]).toHaveProperty("blockNumber") }) }) diff --git a/packages/providers/test/unified-providers/unified-provider.test.ts b/packages/providers/test/unified-providers/unified-provider.test.ts index 6ea0b3e2..72b4ce19 100644 --- a/packages/providers/test/unified-providers/unified-provider.test.ts +++ b/packages/providers/test/unified-providers/unified-provider.test.ts @@ -67,10 +67,6 @@ describe("Unified Chain provider", () => { addresses: [publicKey], })) as Tx[] - console.log( - "Mina Explorer Unified.ChainHistory Provider Response", - response, - ) const transaction = response[0] expect(transaction).toHaveProperty("amount") @@ -130,10 +126,6 @@ describe("Unified Chain provider", () => { addresses: [publicKey], })) as Tx[] - console.log( - "Mina Explorer Unified.ChainHistory Provider Response", - response, - ) const transaction = response[0] expect(transaction).toHaveProperty("amount") diff --git a/packages/providers/test/zeko-scan/chain-history-provider.test.ts b/packages/providers/test/zeko-scan/chain-history-provider.test.ts index 6d6d3b08..10528698 100644 --- a/packages/providers/test/zeko-scan/chain-history-provider.test.ts +++ b/packages/providers/test/zeko-scan/chain-history-provider.test.ts @@ -28,7 +28,6 @@ describe("Mina Explorer Chain History Provider (Functional)", () => { const response = (await provider.transactionsByAddresses({ addresses: [publicKey], })) as Mina.TransactionBody[] - console.log("response", response) // TODO: investigate pagination const transaction = response[0] diff --git a/packages/vault/package.json b/packages/vault/package.json index 47aa8b9b..4a507fab 100644 --- a/packages/vault/package.json +++ b/packages/vault/package.json @@ -18,20 +18,21 @@ "cleanup": "rimraf node_modules dist .turbo" }, "dependencies": { + "@noble/hashes": "1.4.0", "@palladxyz/key-management": "workspace:*", "@palladxyz/mina-core": "workspace:*", "@palladxyz/pallad-core": "workspace:*", - "@palladxyz/persistence": "workspace:*", "@palladxyz/providers": "workspace:*", "@palladxyz/util": "workspace:*", + "@plasmohq/storage": "^1.11.0", "bs58check": "4.0.0", "buffer": "6.0.3", "dayjs": "1.11.12", "immer": "10.1.1", "rambda": "9.2.1", "redux-logger": "3.0.6", + "superjson": "2.2.1", "unique-names-generator": "4.7.1", - "vitest": "2.0.4", "zustand": "4.5.4" }, "devDependencies": { diff --git a/packages/vault/src/pending-transactions/index.ts b/packages/vault/src/pending-transactions/index.ts index 34fa2307..1889f658 100644 --- a/packages/vault/src/pending-transactions/index.ts +++ b/packages/vault/src/pending-transactions/index.ts @@ -1,7 +1,7 @@ -import { getLocalPersistence } from "@palladxyz/persistence" import dayjs from "dayjs" import { create } from "zustand" import { createJSONStorage, persist } from "zustand/middleware" +import { localPersistence } from "../utils" type PendingTransaction = { hash: string @@ -52,7 +52,7 @@ export const usePendingTransactionStore = create()( }), { name: "PalladPendingTransactions", - storage: createJSONStorage(getLocalPersistence), + storage: createJSONStorage(() => localPersistence), }, ), ) diff --git a/packages/vault/src/utils/index.ts b/packages/vault/src/utils/index.ts index 468bbbe1..2876151b 100644 --- a/packages/vault/src/utils/index.ts +++ b/packages/vault/src/utils/index.ts @@ -1,2 +1,3 @@ export * from "./current-wallet-utils" export * from "./utils" +export * from "./persistence" diff --git a/packages/persistence/src/web.ts b/packages/vault/src/utils/persistence.ts similarity index 82% rename from packages/persistence/src/web.ts rename to packages/vault/src/utils/persistence.ts index 7af590c3..2b174f9d 100644 --- a/packages/persistence/src/web.ts +++ b/packages/vault/src/utils/persistence.ts @@ -1,7 +1,7 @@ import { Storage } from "@plasmohq/storage" import { SecureStorage } from "@plasmohq/storage/secure" import superjson from "superjson" -import type { PersistStorage, StateStorage } from "zustand/middleware" +import type { StateStorage } from "zustand/middleware" superjson.registerCustom( { @@ -24,15 +24,14 @@ const secureStorage = new SecureStorage({ const setVaultSpendingPassword = async () => { const spendingPassword = await sessionData.get("spendingPassword") - if (!spendingPassword) throw new Error("Empty password") - return secureStorage.setPassword(spendingPassword) + return secureStorage.setPassword(spendingPassword ?? "") } -export const securePersistence: PersistStorage = { - getItem: async (name): Promise => { +export const securePersistence: StateStorage = { + getItem: async (name): Promise => { await setVaultSpendingPassword() const value = await secureStorage.get(name) - if (!value || value === "undefined") return + if (!value || value === "undefined") return null return superjson.parse(value) }, setItem: async (name, value) => { diff --git a/packages/vault/src/vault/utils/restore-wallet.ts b/packages/vault/src/vault/utils/restore-wallet.ts index 8daac513..f49afc9f 100644 --- a/packages/vault/src/vault/utils/restore-wallet.ts +++ b/packages/vault/src/vault/utils/restore-wallet.ts @@ -2,13 +2,13 @@ import type { ChainDerivationArgs, FromBip39MnemonicWordsProps, } from "@palladxyz/key-management" -import { getSecurePersistence } from "@palladxyz/persistence" import { createChainProvider } from "@palladxyz/providers" import type { CredentialName, SingleCredentialState } from "../../credentials" import type { KeyAgentName, KeyAgents } from "../../keyAgent" import { WalletError } from "../../lib/Errors" import { getRandomAnimalName } from "../../lib/utils" +import { securePersistence } from "../../utils" export async function restoreWalletHelper( get: any, @@ -92,6 +92,6 @@ export async function restoreWalletHelper( }) setCurrentNetworkName(providerConfig.networkName) ensureAccount(network, derivedCredential.address) - getSecurePersistence().setItem("foo", "bar" as any) + securePersistence.setItem("foo", "bar" as any) await _syncWallet() } diff --git a/packages/vault/src/vault/vaultStore.ts b/packages/vault/src/vault/vaultStore.ts index 729e38b6..43ebfaad 100644 --- a/packages/vault/src/vault/vaultStore.ts +++ b/packages/vault/src/vault/vaultStore.ts @@ -4,10 +4,9 @@ import { PalladNetworkNames, constructTransaction, } from "@palladxyz/pallad-core" -import { getSecurePersistence } from "@palladxyz/persistence" import { produce } from "immer" import { create } from "zustand" -import { type PersistStorage, persist } from "zustand/middleware" +import { createJSONStorage, persist } from "zustand/middleware" import { type AccountStore, accountSlice } from "../account" import { type CredentialStore, credentialSlice } from "../credentials" @@ -16,6 +15,7 @@ import { getRandomAnimalName } from "../lib/utils" import { type NetworkInfoStore, networkInfoSlice } from "../network-info" import { type ObjectStore, objectSlice } from "../objects" import { type TokenInfoStore, tokenInfoSlice } from "../token-info" +import { securePersistence } from "../utils" import { getBalanceHelper, getCurrentWalletHelper, @@ -177,10 +177,7 @@ export const useVault = create< }), { name: "PalladVault", - storage: - import.meta.env.VITE_APP_LADLE === "true" - ? undefined - : (getSecurePersistence() as PersistStorage), + storage: createJSONStorage(() => securePersistence), }, ), ) diff --git a/packages/vault/test/account/accountStore.test.ts b/packages/vault/test/account/accountStore.test.ts index 1681a576..bb8b63f7 100644 --- a/packages/vault/test/account/accountStore.test.ts +++ b/packages/vault/test/account/accountStore.test.ts @@ -69,7 +69,6 @@ describe("AccountStore", () => { address, ).accountInfo }) - console.log("finalAccountInfo", finalAccountInfo) expect(finalAccountInfo).toEqual(accountInfo) }) diff --git a/packages/vault/test/keyAgent/keyAgentStore.test.ts b/packages/vault/test/keyAgent/keyAgentStore.test.ts index 3280682a..10f97953 100644 --- a/packages/vault/test/keyAgent/keyAgentStore.test.ts +++ b/packages/vault/test/keyAgent/keyAgentStore.test.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import { mnemonic } from "@palladxyz/common" import { type ChainOperationArgs, @@ -20,8 +21,7 @@ const PREGENERATED_MNEMONIC = mnemonic const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe("KeyAgentStore", () => { let randomMnemonic: string[] @@ -197,7 +197,6 @@ describe("KeyAgentStore", () => { getPassphrase, ) - console.log("groupedCredential: ", groupedCredential) // signable payload const message: Mina.MessageBody = { message: "Hello, Bob!", @@ -215,7 +214,6 @@ describe("KeyAgentStore", () => { message, operations, ) - console.log("signedMessage: ", signedMessage) }) // check that key agent is in the store const keyAgent = result.current.keyAgents[keyAgentName] diff --git a/packages/vault/test/wallet/walletFlow.test.ts b/packages/vault/test/wallet/walletFlow.test.ts index 5abc4c25..bb1efd82 100644 --- a/packages/vault/test/wallet/walletFlow.test.ts +++ b/packages/vault/test/wallet/walletFlow.test.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import { mnemonic } from "@palladxyz/common" import type { ChainDerivationArgs, @@ -24,8 +25,7 @@ const PREGENERATED_MNEMONIC = mnemonic const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) describe("WalletTest", () => { let agentArgs: FromBip39MnemonicWordsProps @@ -87,11 +87,8 @@ describe("WalletTest", () => { // check if chainId has been set and not '...' const chainId = result.current.getChainId() - console.log("chainId: ", chainId) const networkInfos = result.current.getNetworkInfo(defaultNetwork) - console.log("networkInfos: ", networkInfos) const currentNetworkInfo = result.current.getCurrentNetworkInfo() - console.log("currentNetworkInfo: ", currentNetworkInfo) expect(chainId).not.toEqual("...") // check if first credential is in the store @@ -104,14 +101,12 @@ describe("WalletTest", () => { // check current network info is of the expected network const currentNetwork = result.current.getCurrentNetwork() - console.log("currentNetwork: ", currentNetwork) expect(currentNetwork).toEqual(defaultNetwork) // check if accountInfo is in the store const accountInfo = result.current.getAccountsInfo( defaultNetwork, expectedAddress, ) - console.log("accountInfo", accountInfo) expect(accountInfo).toBeDefined() act(() => { result.current.setObject({ @@ -125,10 +120,8 @@ describe("WalletTest", () => { [], ) expect(allObjects.length).toEqual(2) - console.log("all credentials", allObjects) // get keyAgentName const currentKeyAgentName = result.current.keyAgentName - console.log("keyAgentName", currentKeyAgentName) expect(currentKeyAgentName).toBe(keyAgentName) }, 30000) }) diff --git a/packages/web-provider/package.json b/packages/web-provider/package.json index ce74aeec..72d55976 100644 --- a/packages/web-provider/package.json +++ b/packages/web-provider/package.json @@ -18,16 +18,15 @@ "cleanup": "rimraf node_modules dist .turbo" }, "dependencies": { + "@noble/hashes": "1.4.0", "@palladxyz/key-management": "workspace:*", "@palladxyz/mina-core": "workspace:*", - "@palladxyz/persistence": "workspace:*", "@palladxyz/providers": "workspace:*", "@palladxyz/vault": "workspace:*", "dayjs": "1.11.12", "eventemitter3": "5.0.1", "mina-signer": "3.0.7", "superjson": "2.2.1", - "vitest": "2.0.4", "webext-bridge": "6.0.1", "webextension-polyfill": "0.12.0", "zod": "3.23.8" diff --git a/packages/web-provider/src/mina-network/mina-provider.ts b/packages/web-provider/src/mina-network/mina-provider.ts index f952ab28..f08566f5 100644 --- a/packages/web-provider/src/mina-network/mina-provider.ts +++ b/packages/web-provider/src/mina-network/mina-provider.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import type { ChainOperationArgs, ChainSignablePayload, @@ -285,16 +286,10 @@ export class MinaProvider implements IMinaProvider { passphrase: string }) { try { - return await this.vault.sign( - signable, - operationArgs, - () => - new Promise((resolve) => - // TODO: make sure we handle scenarios where the password is provided and not just boolean 'confirmed' - resolve(Buffer.from(passphrase as string)), - ), + return await this.vault.sign(signable, operationArgs, () => + utf8ToBytes(passphrase), ) - } catch { + } catch (error) { throw this.createProviderRpcError(4100, "Unauthorized") } } diff --git a/packages/web-provider/src/utils/prompts.ts b/packages/web-provider/src/utils/prompts.ts index 7e788419..a5059761 100644 --- a/packages/web-provider/src/utils/prompts.ts +++ b/packages/web-provider/src/utils/prompts.ts @@ -12,9 +12,10 @@ export const showUserPrompt = async ( state: "normal", }) .then(async (newWindow) => { + const { runtime, windows } = await import("webextension-polyfill") const listener = (response: any) => { if (response.windowId === newWindow?.id) { - chrome.runtime.onMessage.removeListener(listener) + runtime.onMessage.removeListener(listener) if (response.userRejected) { return reject(new Error("4001 - User Rejected Request")) } @@ -32,7 +33,7 @@ export const showUserPrompt = async ( const tabId = newWindow.tabs?.[0]?.id if (typeof tabId === "number") { setTimeout(() => { - chrome.runtime.sendMessage({ + runtime.sendMessage({ type: "action_request", params: { title: metadata.title, @@ -41,14 +42,14 @@ export const showUserPrompt = async ( }, }) }, 1000) - chrome.runtime.onMessage.addListener(listener) + runtime.onMessage.addListener(listener) const closeListener = (closedWindowId: number) => { - chrome.windows.onRemoved.removeListener(closeListener) + windows.onRemoved.removeListener(closeListener) if (closedWindowId === newWindow?.id) { return reject(new Error("4001 - User Rejected Request")) } } - chrome.windows.onRemoved.addListener(closeListener) + windows.onRemoved.addListener(closeListener) } else { return reject(new Error("Failed to retrieve tab ID")) } diff --git a/packages/web-provider/src/vault-service/vault-service.ts b/packages/web-provider/src/vault-service/vault-service.ts index 0e25f52a..4a50d29d 100644 --- a/packages/web-provider/src/vault-service/vault-service.ts +++ b/packages/web-provider/src/vault-service/vault-service.ts @@ -3,11 +3,8 @@ import type { GetPassphrase, } from "@palladxyz/key-management" import type { ChainOperationArgs } from "@palladxyz/key-management" -import { - getSecurePersistence, - getSessionPersistence, -} from "@palladxyz/persistence" import type { ProviderConfig } from "@palladxyz/providers" +import { securePersistence, sessionPersistence } from "@palladxyz/vault" import { usePendingTransactionStore } from "@palladxyz/vault" import { type SearchQuery, @@ -16,6 +13,7 @@ import { } from "@palladxyz/vault" import dayjs from "dayjs" import Client from "mina-signer" +import { storage } from "webextension-polyfill" import type { Mina } from "@palladxyz/mina-core" import type { Validation } from ".." @@ -133,24 +131,24 @@ export class VaultService implements IVaultService { } async getEnabled({ origin }: { origin: ZkAppUrl }) { - const { permissions } = await chrome.storage.local.get({ + const { permissions } = await storage.local.get({ permissions: true, }) return permissions[origin] === AuthorizationState.ALLOWED } async isBlocked({ origin }: { origin: ZkAppUrl }) { - const { permissions } = await chrome.storage.local.get({ + const { permissions } = await storage.local.get({ permissions: true, }) return permissions[origin] === AuthorizationState.BLOCKED } async setEnabled({ origin }: { origin: ZkAppUrl }) { - const { permissions } = await chrome.storage.local.get({ + const { permissions } = await storage.local.get({ permissions: true, }) - return chrome.storage.local.set({ + return storage.local.set({ permissions: { ...permissions, [origin]: AuthorizationState.ALLOWED, @@ -248,12 +246,12 @@ export class VaultService implements IVaultService { async isLocked() { await this.rehydrate() const authenticated = - ((await getSecurePersistence().getItem("foo")) as unknown) === "bar" + ((await securePersistence.getItem("foo")) as unknown) === "bar" return !authenticated } async unlockWallet(spendingPassword: string) { - await getSessionPersistence().setItem("spendingPassword", spendingPassword) + await sessionPersistence.setItem("spendingPassword", spendingPassword) await this.rehydrate() const locked = await this.isLocked() if (locked === true) { @@ -264,15 +262,8 @@ export class VaultService implements IVaultService { } async rehydrate() { - return await useVault.persist.rehydrate() - } - /* - TODO: add checkPassword function for methods that requrie password - async checkPassword(password) { - const correctPassword = getSessionPersistence().getItem('spendingPassword') - return correctPassword === password + return useVault.persist.rehydrate() } - */ async syncWallet() { await this.rehydrate() diff --git a/packages/web-provider/test/mina/mina-provider.test.ts b/packages/web-provider/test/mina/mina-provider.test.ts index e29d95a6..04f97feb 100644 --- a/packages/web-provider/test/mina/mina-provider.test.ts +++ b/packages/web-provider/test/mina/mina-provider.test.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from "@noble/hashes/utils" import { type ChainDerivationArgs, type FromBip39MnemonicWordsProps, @@ -15,6 +16,7 @@ import { act, renderHook } from "@testing-library/react" import Client from "mina-signer" import { vi } from "vitest" +import type { runtime, tabs, windows } from "webextension-polyfill" import type { RequestArguments } from "../../src" import { MinaProvider } from "../../src" @@ -37,8 +39,7 @@ const PREGENERATED_MNEMONIC = [ const params = { passphrase: "passphrase", } -const getPassphrase = () => - new Promise((resolve) => resolve(Buffer.from(params.passphrase))) +const getPassphrase = () => utf8ToBytes(params.passphrase) const TEST_ORIGIN = "https://palladians.xyz" @@ -54,7 +55,6 @@ describe.skip("Wallet Provider Test", () => { //let defaultNetwork: string beforeAll(async () => { - console.log("Current working directory:", process.cwd()) networkType = "testnet" agentArgs = { getPassphrase: getPassphrase, @@ -105,28 +105,28 @@ describe.skip("Wallet Provider Test", () => { tabs: [{ id: 5678 }], // Mock tab ID } callback(mockWindow) - }) as unknown as typeof chrome.windows.create, + }) as unknown as typeof windows.create, }, tabs: { - update: vi.fn() as unknown as typeof chrome.tabs.update, + update: vi.fn() as unknown as typeof tabs.update, // ... other tab methods if needed }, runtime: { - sendMessage: vi.fn() as unknown as typeof chrome.runtime.sendMessage, + sendMessage: vi.fn() as unknown as typeof runtime.sendMessage, onMessage: { // Mock the addListener to simulate receiving a message with the passphrase addListener: vi.fn((listener) => { const mockResponse = { windowId: 1234, - userInput: Buffer.from(params.passphrase), // This is the simulated passphrase input + userInput: utf8ToBytes(params.passphrase), // This is the simulated passphrase input userConfirmed: true, } listener(mockResponse) }), removeListener: vi.fn(), - } as unknown as typeof chrome.runtime.onMessage, + } as unknown as typeof runtime.onMessage, }, - } as unknown as typeof chrome + } as unknown }) afterEach(() => { @@ -142,7 +142,6 @@ describe.skip("Wallet Provider Test", () => { // Trigger connection const result = await provider.enable({ origin: TEST_ORIGIN }) - console.log("result in test: ", result) expect(result).toEqual([ "B62qjsV6WQwTeEWrNrRRBP6VaaLvQhwWTnFi4WP4LQjGvpfZEumXzxb", ]) @@ -165,7 +164,6 @@ describe.skip("Wallet Provider Test", () => { expect(provider).toBeDefined() const chainId = await provider.request(requestArgs) - console.log("chainId in test: ", chainId) expect(chainId).toEqual( "fd7d111973bf5a9e3e87384f560fdead2f272589ca00b6d9e357fca9839631da", ) @@ -236,7 +234,6 @@ describe.skip("Wallet Provider Test", () => { publicKey: string signature: string } - console.log("signature: ", signature) //const verifiableSignatue = { // fields: signature.data.map((field) => BigInt(field)) //} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47a653ec..b529edf8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,9 +74,6 @@ importers: '@palladxyz/key-management': specifier: workspace:* version: link:../../packages/key-management - '@palladxyz/persistence': - specifier: workspace:* - version: link:../../packages/persistence '@palladxyz/web-provider': specifier: workspace:* version: link:../../packages/web-provider @@ -86,6 +83,9 @@ importers: buffer: specifier: 6.0.3 version: 6.0.3 + debounce: + specifier: ^2.1.0 + version: 2.1.0 next-themes: specifier: 0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -114,9 +114,6 @@ importers: specifier: 3.23.8 version: 3.23.8 devDependencies: - '@crxjs/vite-plugin': - specifier: 2.0.0-beta.25 - version: 2.0.0-beta.25 '@esbuild-plugins/node-globals-polyfill': specifier: 0.2.3 version: 0.2.3(esbuild@0.23.0) @@ -135,6 +132,9 @@ importers: '@total-typescript/ts-reset': specifier: 0.5.1 version: 0.5.1 + '@tsconfig/vite-react': + specifier: 3.0.2 + version: 3.0.2 '@types/chrome': specifier: 0.0.269 version: 0.0.269 @@ -178,8 +178,8 @@ importers: specifier: 0.10.1 version: 0.10.1 vite-plugin-node-polyfills: - specifier: 0.22.0 - version: 0.22.0(rollup@4.19.1)(vite@5.3.5(@types/node@22.0.0)) + specifier: 0.17.0 + version: 0.17.0(rollup@4.19.1)(vite@5.3.5(@types/node@22.0.0)) vite-plugin-require-transform: specifier: 1.0.21 version: 1.0.21 @@ -192,9 +192,15 @@ importers: vite-plugin-wasm: specifier: 3.3.0 version: 3.3.0(vite@5.3.5(@types/node@22.0.0)) + vite-plugin-web-extension: + specifier: ^4.1.6 + version: 4.1.6(@types/node@22.0.0) web-ext: specifier: 8.2.0 version: 8.2.0 + write-json-file: + specifier: ^6.0.0 + version: 6.0.0 packages/_template: devDependencies: @@ -215,6 +221,9 @@ importers: '@hookform/resolvers': specifier: 3.9.0 version: 3.9.0(react-hook-form@7.52.1(react@18.3.1)) + '@noble/hashes': + specifier: 1.4.0 + version: 1.4.0 '@palladxyz/key-management': specifier: workspace:* version: link:../key-management @@ -227,9 +236,6 @@ importers: '@palladxyz/pallad-core': specifier: workspace:* version: link:../pallad-core - '@palladxyz/persistence': - specifier: workspace:* - version: link:../persistence '@palladxyz/vault': specifier: workspace:* version: link:../vault @@ -257,9 +263,6 @@ importers: immer: specifier: 10.1.1 version: 10.1.1 - isomorphic-dompurify: - specifier: 2.14.0 - version: 2.14.0 js-beautify: specifier: 1.15.1 version: 1.15.1 @@ -329,9 +332,15 @@ importers: tailwindcss-animate: specifier: 1.0.7 version: 1.0.7(tailwindcss@3.4.7(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.12))(@types/node@22.0.0)(typescript@5.5.4))) + webext-bridge: + specifier: 6.0.1 + version: 6.0.1 webextension-polyfill: specifier: 0.12.0 version: 0.12.0 + xss: + specifier: ^1.0.15 + version: 1.0.15 yaml: specifier: 2.5.0 version: 2.5.0 @@ -462,9 +471,6 @@ importers: ts-custom-error: specifier: 3.3.1 version: 3.3.1 - vitest: - specifier: 2.0.4 - version: 2.0.4(@types/node@22.0.0)(happy-dom@14.12.3)(jsdom@24.1.1) devDependencies: '@palladxyz/common': specifier: workspace:* @@ -560,24 +566,11 @@ importers: specifier: 4.0.6 version: 4.0.6 - packages/persistence: - dependencies: - '@plasmohq/storage': - specifier: 1.11.0 - version: 1.11.0(react@18.3.1) - superjson: - specifier: 2.2.1 - version: 2.2.1 - devDependencies: - '@palladxyz/common': - specifier: workspace:* - version: link:../common - zustand: - specifier: 4.5.4 - version: 4.5.4(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1) - packages/providers: dependencies: + '@noble/hashes': + specifier: 1.4.0 + version: 1.4.0 '@palladxyz/key-management': specifier: workspace:* version: link:../key-management @@ -667,6 +660,9 @@ importers: packages/vault: dependencies: + '@noble/hashes': + specifier: 1.4.0 + version: 1.4.0 '@palladxyz/key-management': specifier: workspace:* version: link:../key-management @@ -676,15 +672,15 @@ importers: '@palladxyz/pallad-core': specifier: workspace:* version: link:../pallad-core - '@palladxyz/persistence': - specifier: workspace:* - version: link:../persistence '@palladxyz/providers': specifier: workspace:* version: link:../providers '@palladxyz/util': specifier: workspace:* version: link:../util + '@plasmohq/storage': + specifier: ^1.11.0 + version: 1.11.0(react@18.3.1) bs58check: specifier: 4.0.0 version: 4.0.0 @@ -703,12 +699,12 @@ importers: redux-logger: specifier: 3.0.6 version: 3.0.6 + superjson: + specifier: 2.2.1 + version: 2.2.1 unique-names-generator: specifier: 4.7.1 version: 4.7.1 - vitest: - specifier: 2.0.4 - version: 2.0.4(@types/node@22.0.0)(happy-dom@14.12.3)(jsdom@24.1.1) zustand: specifier: 4.5.4 version: 4.5.4(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1) @@ -737,15 +733,15 @@ importers: packages/web-provider: dependencies: + '@noble/hashes': + specifier: 1.4.0 + version: 1.4.0 '@palladxyz/key-management': specifier: workspace:* version: link:../key-management '@palladxyz/mina-core': specifier: workspace:* version: link:../mina-core - '@palladxyz/persistence': - specifier: workspace:* - version: link:../persistence '@palladxyz/providers': specifier: workspace:* version: link:../providers @@ -764,9 +760,6 @@ importers: superjson: specifier: 2.2.1 version: 2.2.1 - vitest: - specifier: 2.0.4 - version: 2.0.4(@types/node@22.0.0)(happy-dom@14.12.3)(jsdom@24.1.1) webext-bridge: specifier: 6.0.1 version: 6.0.1 @@ -1532,9 +1525,6 @@ packages: '@bundled-es-modules/tough-cookie@0.1.6': resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} - '@crxjs/vite-plugin@2.0.0-beta.25': - resolution: {integrity: sha512-g5ytTNiFpFCi+T0trSDJLohVz5PufLBLh6OGljyGTHkQCKiApuEgZ1bAjgPXluMDhMUvbPfZT10LYl5ROefXog==} - '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -2349,10 +2339,6 @@ packages: rollup: optional: true - '@rollup/pluginutils@4.2.1': - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - '@rollup/pluginutils@5.1.0': resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} engines: {node: '>=14.0.0'} @@ -2764,9 +2750,6 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/dompurify@3.0.5': - resolution: {integrity: sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==} - '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -2884,9 +2867,6 @@ packages: '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/trusted-types@2.0.7': - resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@types/unist@2.0.10': resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} @@ -2951,9 +2931,6 @@ packages: '@vitest/utils@2.0.4': resolution: {integrity: sha512-Zc75QuuoJhOBnlo99ZVUkJIuq4Oj0zAkrQ2VzCqNCx6wAwViHEh5Fnp4fiJTE9rA+sAoXRf00Z9xGgfEzV6fzQ==} - '@webcomponents/custom-elements@1.6.0': - resolution: {integrity: sha512-CqTpxOlUCPWRNUPZDxT5v2NnHXA4oox612iUGnmTUGQFhZ1Gkj8kirtl/2wcF6MqX7+PqqicZzOCBKKfIn0dww==} - '@xstate/fsm@1.6.5': resolution: {integrity: sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==} @@ -3131,6 +3108,9 @@ packages: resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} hasBin: true + async-lock@1.4.1: + resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} + async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -3416,6 +3396,9 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -3436,6 +3419,11 @@ packages: engines: {node: '>=12.13.0'} hasBin: true + chrome-launcher@1.1.0: + resolution: {integrity: sha512-rJYWeEAERwWIr3c3mEVXwNiODPEdMRlRxHc47B1qHPOolHZnkj7rMv1QSUfPoG6MgatWj5AxSpnKKR4QEwEQIQ==} + engines: {node: '>=12.13.0'} + hasBin: true + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -3581,10 +3569,6 @@ packages: resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} engines: {node: '>=12'} - connect-injector@0.4.4: - resolution: {integrity: sha512-hdBG8nXop42y2gWCqOV8y1O3uVk4cIU+SoxLCPyCUKRImyPiScoNiSulpHjoktRU1BdI0UzoUdxUa87thrcmHw==} - engines: {node: '>= 0.8.0'} - consola@3.2.3: resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} engines: {node: ^14.18.0 || >=16.10.0} @@ -3606,9 +3590,6 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -3658,6 +3639,9 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + crypto-browserify@3.12.0: resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} @@ -3691,10 +3675,16 @@ packages: engines: {node: '>=4'} hasBin: true + cssfilter@0.0.10: + resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} + csso@5.0.5: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + cssstyle@4.0.1: resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} engines: {node: '>=18'} @@ -3775,6 +3765,10 @@ packages: debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + debounce@2.1.0: + resolution: {integrity: sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==} + engines: {node: '>=18'} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -3911,6 +3905,10 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-indent@7.0.1: + resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} + engines: {node: '>=12.20'} + detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} @@ -3966,9 +3964,6 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.1.6: - resolution: {integrity: sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==} - domutils@3.1.0: resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} @@ -4037,9 +4032,6 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@0.10.5: - resolution: {integrity: sha512-+7IwY/kiGAacQfY+YBhKMvEmyAJnw5grTUgjG85Pe7vcUI/6b7pZjZG8nQ7+48YhzEAEqrEgD2dCz/JIK+AYvw==} - es-module-lexer@1.5.4: resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} @@ -4758,6 +4750,9 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -4923,6 +4918,9 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -5017,9 +5015,17 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-primitive@3.0.1: + resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==} + engines: {node: '>=0.10.0'} + is-reference@3.0.2: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} @@ -5081,9 +5087,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isomorphic-dompurify@2.14.0: - resolution: {integrity: sha512-7xyjuzBf3P/HBt0PbOpmv5LuV38TmfvidBFvgyuSWVMLwCGDITBPHWsBZ/L1a8DpcGz5PEintBeGdlrKzUqt5A==} - engines: {node: '>=18'} + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} isomorphic-timers-promises@1.0.1: resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==} @@ -5174,11 +5180,6 @@ packages: engines: {node: '>=4'} hasBin: true - jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -5257,6 +5258,9 @@ packages: lighthouse-logger@1.4.2: resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} + lighthouse-logger@2.0.1: + resolution: {integrity: sha512-ioBrW3s2i97noEmnXxmUq7cjIcVRjT5HBpAYy8zE11CxU9HqlWHHeRxfeN1tn8F7OEMVPIC9x1f8t3Z7US9ehQ==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -5272,6 +5276,9 @@ packages: resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + linkedom@0.14.26: + resolution: {integrity: sha512-mK6TrydfFA7phrnp+1j57ycBwFI5bGSW6YXlw9acHoqF+mP/y+FooEYYyniOt5Ot57FSKB3iwmnuQ1UUyNLm5A==} + load-tsconfig@0.2.5: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -5301,6 +5308,12 @@ packages: lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.uniqby@4.7.0: + resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -5361,10 +5374,6 @@ packages: magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - magic-string@0.26.7: - resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} - engines: {node: '>=12'} - magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} @@ -5401,6 +5410,9 @@ packages: md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} @@ -6236,14 +6248,6 @@ packages: resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} engines: {node: '>=12.20'} - q@1.5.1: - resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} - engines: {node: '>=0.6.0', teleport: '>=0.2.0'} - deprecated: |- - You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. - - (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) - qr.js@0.0.0: resolution: {integrity: sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==} @@ -6339,10 +6343,6 @@ packages: peerDependencies: react: '*' - react-refresh@0.13.0: - resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==} - engines: {node: '>=0.10.0'} - react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -6598,11 +6598,6 @@ packages: rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@2.78.1: - resolution: {integrity: sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==} - engines: {node: '>=10.0.0'} - hasBin: true - rollup@4.19.1: resolution: {integrity: sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -6642,9 +6637,6 @@ packages: resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} engines: {npm: '>=2.0.0'} - rxjs@7.5.7: - resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} - rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} @@ -6713,6 +6705,10 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} + set-value@4.1.0: + resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} + engines: {node: '>=11.0'} + setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} @@ -6793,6 +6789,10 @@ packages: react: ^18.0.0 react-dom: ^18.0.0 + sort-keys@5.0.0: + resolution: {integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==} + engines: {node: '>=12'} + source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -6856,10 +6856,6 @@ packages: stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} - stream-buffers@0.2.6: - resolution: {integrity: sha512-ZRpmWyuCdg0TtNKk8bEqvm13oQvXMmzXDsfD4cBgcx5LouborvU5pm3JMkdTP3HcszyUI08AM1dHMXA5r2g6Sg==} - engines: {node: '>= 0.3.0'} - stream-combiner@0.0.4: resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} @@ -7275,14 +7271,14 @@ packages: engines: {node: '>=14.17'} hasBin: true - uberproto@1.2.0: - resolution: {integrity: sha512-pGtPAQmLwh+R9w81WVHzui1FfedpQWQpiaIIfPCwhtsBez4q6DYbJFfyXPVHPUTNFnedAvNEnkoFiLuhXIR94w==} - uglify-js@3.19.1: resolution: {integrity: sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==} engines: {node: '>=0.8.0'} hasBin: true + uhyphen@0.2.0: + resolution: {integrity: sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==} + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -7483,6 +7479,11 @@ packages: vite-plugin-dynamic-import@1.5.0: resolution: {integrity: sha512-Qp85c+AVJmLa8MLni74U4BDiWpUeFNx7NJqbGZyR2XJOU7mgW0cb7nwlAMucFyM4arEd92Nfxp4j44xPi6Fu7g==} + vite-plugin-node-polyfills@0.17.0: + resolution: {integrity: sha512-iPmPn7376e5u6QvoTSJa16hf5Q0DFwHFXJk2uYpsNlmI3JdPms7hWyh55o+OysJ5jo9J5XPhLC9sMOYifwFd1w==} + peerDependencies: + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + vite-plugin-node-polyfills@0.22.0: resolution: {integrity: sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA==} peerDependencies: @@ -7512,6 +7513,10 @@ packages: peerDependencies: vite: ^2 || ^3 || ^4 || ^5 + vite-plugin-web-extension@4.1.6: + resolution: {integrity: sha512-6na2gY87AUsllZC1UE45kNpFucM+Ig/U6bVjkRK6NbqwwfDDBwFma3LM/xGekWmYoKk/+qp072jyzFYrOLF5aw==} + engines: {node: '>=16'} + vite-tsconfig-paths@4.3.2: resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} peerDependencies: @@ -7587,6 +7592,10 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + web-ext-run@0.2.1: + resolution: {integrity: sha512-5D11VcjdGkA1/xax5UWL0YeAbDySKHzWFe6EpsoPNUMw5Uk9tKk9p6GUOfcaI5N7sINKfBMZYNsTBiu5dzJB9A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + web-ext@8.2.0: resolution: {integrity: sha512-krU7rmxaG96b3Q9Enbry9/pmE/5FUGkvajCGfJCD+J79rt7JFjhVpw1Dszz4BqQkTd3y8cG5wJ3p1uC6uyAwcA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7605,6 +7614,9 @@ packages: webext-bridge@6.0.1: resolution: {integrity: sha512-GruIrN+vNwbxVCi8UW4Dqk5YkcGA9V0ZfJ57jXP9JXHbrsDs5k2N6NNYQR5e+wSCnQpGYOGAGihwUpKlhg8QIw==} + webextension-polyfill@0.10.0: + resolution: {integrity: sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==} + webextension-polyfill@0.12.0: resolution: {integrity: sha512-97TBmpoWJEE+3nFBQ4VocyCdLKfw54rFaJ6EVQYLBCXqCIpLSZkwGgASpv4oPt9gdKCJ80RJlcmNzNn008Ag6Q==} @@ -7699,6 +7711,14 @@ packages: write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + write-json-file@6.0.0: + resolution: {integrity: sha512-MNHcU3f9WxnNyR6MxsYSj64Jz0+dwIpisWKWq9gqLj/GwmA9INg3BZ3vt70/HB3GEwrnDQWr4RPrywnhNzmUFA==} + engines: {node: '>=18'} + ws@7.5.10: resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} engines: {node: '>=8.3.0'} @@ -7754,6 +7774,11 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xss@1.0.15: + resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==} + engines: {node: '>= 0.10.0'} + hasBin: true + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -8755,27 +8780,6 @@ snapshots: '@types/tough-cookie': 4.0.5 tough-cookie: 4.1.4 - '@crxjs/vite-plugin@2.0.0-beta.25': - dependencies: - '@rollup/pluginutils': 4.2.1 - '@webcomponents/custom-elements': 1.6.0 - acorn-walk: 8.3.3 - cheerio: 1.0.0-rc.12 - connect-injector: 0.4.4 - convert-source-map: 1.9.0 - debug: 4.3.6 - es-module-lexer: 0.10.5 - fast-glob: 3.3.2 - fs-extra: 10.1.0 - jsesc: 3.0.2 - magic-string: 0.26.7 - picocolors: 1.0.1 - react-refresh: 0.13.0 - rollup: 2.78.1 - rxjs: 7.5.7 - transitivePeerDependencies: - - supports-color - '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -9528,11 +9532,6 @@ snapshots: optionalDependencies: rollup: 4.19.1 - '@rollup/pluginutils@4.2.1': - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - '@rollup/pluginutils@5.1.0(rollup@4.19.1)': dependencies: '@types/estree': 1.0.5 @@ -9936,10 +9935,6 @@ snapshots: dependencies: '@types/ms': 0.7.34 - '@types/dompurify@3.0.5': - dependencies: - '@types/trusted-types': 2.0.7 - '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.5 @@ -10056,8 +10051,6 @@ snapshots: '@types/tough-cookie@4.0.5': {} - '@types/trusted-types@2.0.7': {} - '@types/unist@2.0.10': {} '@types/unist@3.0.2': {} @@ -10154,8 +10147,6 @@ snapshots: loupe: 3.1.1 tinyrainbow: 1.2.0 - '@webcomponents/custom-elements@1.6.0': {} - '@xstate/fsm@1.6.5': {} abbrev@2.0.0: {} @@ -10348,9 +10339,12 @@ snapshots: astring@1.8.6: {} + async-lock@1.4.1: {} + async@3.2.5: {} - asynckit@0.4.0: {} + asynckit@0.4.0: + optional: true at-least-node@1.0.0: {} @@ -10686,6 +10680,8 @@ snapshots: chardet@0.7.0: {} + charenc@0.0.2: {} + check-error@2.1.1: {} cheerio-select@2.1.0: @@ -10728,6 +10724,15 @@ snapshots: transitivePeerDependencies: - supports-color + chrome-launcher@1.1.0: + dependencies: + '@types/node': 22.0.0 + escape-string-regexp: 4.0.0 + is-wsl: 2.2.0 + lighthouse-logger: 2.0.1 + transitivePeerDependencies: + - supports-color + ci-info@3.9.0: {} cipher-base@1.0.4: @@ -10809,6 +10814,7 @@ snapshots: combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 + optional: true comma-separated-tokens@2.0.3: {} @@ -10854,15 +10860,6 @@ snapshots: write-file-atomic: 3.0.3 xdg-basedir: 5.1.0 - connect-injector@0.4.4: - dependencies: - debug: 2.6.9 - q: 1.5.1 - stream-buffers: 0.2.6 - uberproto: 1.2.0 - transitivePeerDependencies: - - supports-color - consola@3.2.3: {} console-browserify@1.2.0: {} @@ -10880,8 +10877,6 @@ snapshots: content-type@1.0.5: {} - convert-source-map@1.9.0: {} - convert-source-map@2.0.0: {} cookie@0.5.0: {} @@ -10942,6 +10937,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypt@0.0.2: {} + crypto-browserify@3.12.0: dependencies: browserify-cipher: 1.0.1 @@ -10989,13 +10986,18 @@ snapshots: cssesc@3.0.0: {} + cssfilter@0.0.10: {} + csso@5.0.5: dependencies: css-tree: 2.2.1 + cssom@0.5.0: {} + cssstyle@4.0.1: dependencies: rrweb-cssom: 0.6.0 + optional: true csstype@3.1.3: {} @@ -11056,6 +11058,7 @@ snapshots: dependencies: whatwg-mimetype: 4.0.0 whatwg-url: 14.0.0 + optional: true date-fns@3.6.0: {} @@ -11063,6 +11066,8 @@ snapshots: debounce@1.2.1: {} + debounce@2.1.0: {} + debug@2.6.9: dependencies: ms: 2.0.0 @@ -11075,7 +11080,8 @@ snapshots: decimal.js-light@2.5.1: {} - decimal.js@10.4.3: {} + decimal.js@10.4.3: + optional: true decode-named-character-reference@1.0.2: dependencies: @@ -11157,7 +11163,8 @@ snapshots: rimraf: 3.0.2 slash: 3.0.0 - delayed-stream@1.0.0: {} + delayed-stream@1.0.0: + optional: true delegates@1.0.0: {} @@ -11174,6 +11181,8 @@ snapshots: destroy@1.2.0: {} + detect-indent@7.0.1: {} + detect-node-es@1.1.0: {} devlop@1.1.0: @@ -11225,8 +11234,6 @@ snapshots: dependencies: domelementtype: 2.3.0 - dompurify@3.1.6: {} - domutils@3.1.0: dependencies: dom-serializer: 2.0.0 @@ -11302,8 +11309,6 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@0.10.5: {} - es-module-lexer@1.5.4: {} es6-error@4.1.1: {} @@ -11802,6 +11807,7 @@ snapshots: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + optional: true formdata-polyfill@4.0.10: dependencies: @@ -12240,9 +12246,12 @@ snapshots: html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 + optional: true html-escaper@2.0.2: {} + html-escaper@3.0.3: {} + html-void-elements@3.0.0: {} htmlparser2@8.0.2: @@ -12305,6 +12314,7 @@ snapshots: iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + optional: true ieee754@1.2.1: {} @@ -12417,6 +12427,8 @@ snapshots: dependencies: binary-extensions: 2.3.0 + is-buffer@1.1.6: {} + is-callable@1.2.7: {} is-ci@3.0.1: @@ -12483,7 +12495,14 @@ snapshots: is-plain-obj@4.1.0: {} - is-potential-custom-element-name@1.0.1: {} + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-potential-custom-element-name@1.0.1: + optional: true + + is-primitive@3.0.1: {} is-reference@3.0.2: dependencies: @@ -12529,16 +12548,7 @@ snapshots: isexe@2.0.0: {} - isomorphic-dompurify@2.14.0: - dependencies: - '@types/dompurify': 3.0.5 - dompurify: 3.1.6 - jsdom: 24.1.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate + isobject@3.0.1: {} isomorphic-timers-promises@1.0.1: {} @@ -12636,13 +12646,12 @@ snapshots: - bufferutil - supports-color - utf-8-validate + optional: true jsesc@0.5.0: {} jsesc@2.5.2: {} - jsesc@3.0.2: {} - json-bigint@1.0.0: dependencies: bignumber.js: 9.1.2 @@ -12749,6 +12758,13 @@ snapshots: transitivePeerDependencies: - supports-color + lighthouse-logger@2.0.1: + dependencies: + debug: 2.6.9 + marky: 1.2.5 + transitivePeerDependencies: + - supports-color + lilconfig@2.1.0: {} lilconfig@3.1.2: {} @@ -12757,6 +12773,14 @@ snapshots: lines-and-columns@2.0.4: {} + linkedom@0.14.26: + dependencies: + css-select: 5.1.0 + cssom: 0.5.0 + html-escaper: 3.0.3 + htmlparser2: 8.0.2 + uhyphen: 0.2.0 + load-tsconfig@0.2.5: {} locate-path@6.0.0: @@ -12777,6 +12801,10 @@ snapshots: lodash.sortby@4.7.0: {} + lodash.uniq@4.5.0: {} + + lodash.uniqby@4.7.0: {} + lodash@4.17.21: {} log-symbols@3.0.0: @@ -12830,10 +12858,6 @@ snapshots: dependencies: sourcemap-codec: 1.4.8 - magic-string@0.26.7: - dependencies: - sourcemap-codec: 1.4.8 - magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -12873,6 +12897,12 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 + md5@2.3.0: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + mdast-util-find-and-replace@3.0.1: dependencies: '@types/mdast': 4.0.4 @@ -13596,7 +13626,8 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.12: {} + nwsapi@2.2.12: + optional: true object-assign@4.1.1: {} @@ -14035,8 +14066,6 @@ snapshots: dependencies: escape-goat: 4.0.0 - q@1.5.1: {} - qr.js@0.0.0: {} qs@6.12.3: @@ -14127,8 +14156,6 @@ snapshots: qr.js: 0.0.0 react: 18.3.1 - react-refresh@0.13.0: {} - react-refresh@0.14.2: {} react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1): @@ -14440,10 +14467,6 @@ snapshots: dependencies: estree-walker: 0.6.1 - rollup@2.78.1: - optionalDependencies: - fsevents: 2.3.3 - rollup@4.19.1: dependencies: '@types/estree': 1.0.5 @@ -14470,9 +14493,11 @@ snapshots: dependencies: rrweb-snapshot: 2.0.0-alpha.16 - rrweb-cssom@0.6.0: {} + rrweb-cssom@0.6.0: + optional: true - rrweb-cssom@0.7.1: {} + rrweb-cssom@0.7.1: + optional: true rrweb-snapshot@2.0.0-alpha.16: {} @@ -14503,10 +14528,6 @@ snapshots: dependencies: tslib: 1.14.1 - rxjs@7.5.7: - dependencies: - tslib: 2.6.3 - rxjs@7.8.1: dependencies: tslib: 2.6.3 @@ -14527,6 +14548,7 @@ snapshots: saxes@6.0.0: dependencies: xmlchars: 2.2.0 + optional: true scheduler@0.23.2: dependencies: @@ -14568,6 +14590,11 @@ snapshots: gopd: 1.0.1 has-property-descriptors: 1.0.2 + set-value@4.1.0: + dependencies: + is-plain-object: 2.0.4 + is-primitive: 3.0.1 + setimmediate@1.0.5: {} setprototypeof@1.2.0: {} @@ -14648,6 +14675,10 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + sort-keys@5.0.0: + dependencies: + is-plain-obj: 4.1.0 + source-map-js@1.2.0: {} source-map-support@0.5.21: @@ -14699,8 +14730,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - stream-buffers@0.2.6: {} - stream-combiner@0.0.4: dependencies: duplexer: 0.1.2 @@ -14843,7 +14872,8 @@ snapshots: symbol-observable@1.2.0: {} - symbol-tree@3.2.4: {} + symbol-tree@3.2.4: + optional: true tabbable@6.2.0: {} @@ -14970,6 +15000,7 @@ snapshots: tr46@5.0.0: dependencies: punycode: 2.3.1 + optional: true tree-kill@1.2.2: {} @@ -15125,11 +15156,11 @@ snapshots: typescript@5.5.4: {} - uberproto@1.2.0: {} - uglify-js@3.19.1: optional: true + uhyphen@0.2.0: {} + undici-types@5.26.5: {} undici-types@6.11.1: {} @@ -15388,6 +15419,16 @@ snapshots: fast-glob: 3.3.2 magic-string: 0.30.11 + vite-plugin-node-polyfills@0.17.0(rollup@4.19.1)(vite@5.3.5(@types/node@22.0.0)): + dependencies: + '@rollup/plugin-inject': 5.0.5(rollup@4.19.1) + buffer-polyfill: buffer@6.0.3 + node-stdlib-browser: 1.2.0 + process: 0.11.10 + vite: 5.3.5(@types/node@22.0.0) + transitivePeerDependencies: + - rollup + vite-plugin-node-polyfills@0.22.0(rollup@4.19.1)(vite@5.3.5(@types/node@22.0.0)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.19.1) @@ -15438,6 +15479,32 @@ snapshots: dependencies: vite: 5.3.5(@types/node@22.0.0) + vite-plugin-web-extension@4.1.6(@types/node@22.0.0): + dependencies: + ajv: 8.16.0 + async-lock: 1.4.1 + fs-extra: 10.1.0 + json5: 2.2.3 + linkedom: 0.14.26 + lodash.uniq: 4.5.0 + lodash.uniqby: 4.7.0 + md5: 2.3.0 + vite: 5.3.5(@types/node@22.0.0) + web-ext-run: 0.2.1 + webextension-polyfill: 0.10.0 + yaml: 2.5.0 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + - utf-8-validate + vite-tsconfig-paths@4.3.2(typescript@5.5.4)(vite@5.3.5(@types/node@22.0.0)): dependencies: debug: 4.3.6 @@ -15497,6 +15564,7 @@ snapshots: w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 + optional: true watchpack@2.4.1: dependencies: @@ -15507,6 +15575,37 @@ snapshots: dependencies: defaults: 1.0.4 + web-ext-run@0.2.1: + dependencies: + '@babel/runtime': 7.24.7 + '@devicefarmer/adbkit': 3.2.6 + bunyan: 1.8.15 + chrome-launcher: 1.1.0 + debounce: 1.2.1 + es6-error: 4.1.1 + firefox-profile: 4.6.0 + fs-extra: 11.2.0 + fx-runner: 1.4.0 + mkdirp: 3.0.1 + multimatch: 6.0.0 + mz: 2.7.0 + node-notifier: 10.0.1 + parse-json: 7.1.1 + promise-toolbox: 0.21.0 + set-value: 4.1.0 + source-map-support: 0.5.21 + strip-bom: 5.0.0 + strip-json-comments: 5.0.1 + tmp: 0.2.3 + update-notifier: 6.0.2 + watchpack: 2.4.1 + ws: 8.18.0 + zip-dir: 2.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + web-ext@8.2.0: dependencies: '@babel/runtime': 7.24.7 @@ -15566,6 +15665,8 @@ snapshots: tiny-uid: 1.1.2 webextension-polyfill: 0.9.0 + webextension-polyfill@0.10.0: {} + webextension-polyfill@0.12.0: {} webextension-polyfill@0.9.0: {} @@ -15579,15 +15680,18 @@ snapshots: whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 + optional: true whatwg-mimetype@3.0.0: {} - whatwg-mimetype@4.0.0: {} + whatwg-mimetype@4.0.0: + optional: true whatwg-url@14.0.0: dependencies: tr46: 5.0.0 webidl-conversions: 7.0.0 + optional: true whatwg-url@7.1.0: dependencies: @@ -15660,6 +15764,18 @@ snapshots: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + write-json-file@6.0.0: + dependencies: + detect-indent: 7.0.1 + is-plain-obj: 4.1.0 + sort-keys: 5.0.0 + write-file-atomic: 5.0.1 + ws@7.5.10: {} ws@8.17.1: {} @@ -15668,7 +15784,8 @@ snapshots: xdg-basedir@5.1.0: {} - xml-name-validator@5.0.0: {} + xml-name-validator@5.0.0: + optional: true xml2js@0.5.0: dependencies: @@ -15677,7 +15794,13 @@ snapshots: xmlbuilder@11.0.1: {} - xmlchars@2.2.0: {} + xmlchars@2.2.0: + optional: true + + xss@1.0.15: + dependencies: + commander: 2.20.3 + cssfilter: 0.0.10 xtend@4.0.2: {}