diff --git a/jest.config.js b/jest.config.js index a0f57a89..95c72a1b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -28,6 +28,6 @@ module.exports = { '^.+\\.js$': 'babel-jest', }, transformIgnorePatterns: [ - '/node_modules/(?!(@scure|@noble|micro-key-producer|micro-packed)/)', + '/node_modules/(?!(@scure|@noble|micro-key-producer|micro-packed|@openlv|websocket-mqtt|ts-pattern)/)', ], }; diff --git a/package-lock.json b/package-lock.json index ca580b2f..97b0f990 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,8 @@ "@ledgerhq/hw-app-eth": "^7.8.8", "@ledgerhq/hw-transport-node-hid": "^6.33.5", "@metamask/browser-passworder": "^6.0.0", + "@openlv/core": "^0.0.2", + "@openlv/session": "^0.0.3", "@scure/bip39": "^2.2.0", "@x402/core": "^2.12.0", "@x402/evm": "^2.12.0", @@ -34,14 +36,17 @@ "@babel/preset-env": "^8.0.2", "@eslint/js": "^10.0.1", "@playwright/test": "^1.60.0", + "aedes": "^0.51.3", "babel-jest": "^30.4.1", "dotenv-cli": "^11.0.0", "electron": "^43.0.0", "electron-builder": "^26.8.1", + "esbuild": "^0.28.1", "eslint": "^10.4.0", "globals": "^17.6.0", "jest": "^30.4.2", - "prettier": "^3.8.3" + "prettier": "^3.8.3", + "ws": "^8.21.0" }, "engines": { "node": ">=18" @@ -1469,6 +1474,16 @@ "@babel/core": "^8.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-8.0.0.tgz", @@ -1842,6 +1857,448 @@ "node": ">=18" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -3829,11 +4286,125 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@openlv/core": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@openlv/core/-/core-0.0.2.tgz", + "integrity": "sha512-Q7ISpgQX8YkKw25hs76SgDjsIosFkiA/28P/p9b+MvpnN8cymCJDauWA31SSNSyMOrsOS/iMK4I5VHCcwwC5RA==", + "license": "LGPL-3.0-only", + "dependencies": { + "@noble/ciphers": "^1.3.0", + "@noble/curves": "^1.9.7", + "eventemitter3": "^5.0.1" + } + }, + "node_modules/@openlv/core/node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@openlv/core/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@openlv/session": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@openlv/session/-/session-0.0.3.tgz", + "integrity": "sha512-s5Q6BIYAXEnmGuOIW3IQYbY1qW9YS5R5ytgwEjSYWJHiJCOVBu8gcNCQ9NIZ9wI6XLlprKFSdHkw6pzP7pAx4g==", + "license": "LGPL-3.0-only", + "dependencies": { + "@openlv/core": "0.0.2", + "@openlv/signaling": "0.0.3", + "@openlv/transport": "0.0.3", + "eventemitter3": "^5.0.1", + "globals": "^16.2.0", + "ts-pattern": "^5" + } + }, + "node_modules/@openlv/session/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@openlv/signaling": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@openlv/signaling/-/signaling-0.0.3.tgz", + "integrity": "sha512-U2WBRN05DjC6keeTWG7p2WAcm71XDkHjqC8GMpU6LeCcmoqAHIO/rfLcRZxpr3E+BImSblLVe6nwuImAN/v5tg==", + "license": "LGPL-3.0-only", + "dependencies": { + "@openlv/core": "0.0.2", + "eventemitter3": "^5", + "globals": "^16", + "gun": "^0.2020.1241", + "ts-pattern": "^5", + "websocket-mqtt": "0.0.7" + } + }, + "node_modules/@openlv/signaling/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@openlv/transport": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@openlv/transport/-/transport-0.0.3.tgz", + "integrity": "sha512-nqQnYk/jATPx25zIHFG409sVlNRrDYjxrqXFkmr+zmSlbBSq29Blk/XzwK/7xCcaiDf4tZu+hnf2V0b2YU2IuQ==", + "license": "LGPL-3.0-only", + "dependencies": { + "@openlv/core": "0.0.2", + "eventemitter3": "^5.0.1", + "globals": "^16.2.0", + "ts-pattern": "^5" + } + }, + "node_modules/@openlv/transport/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@peculiar/asn1-schema": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@peculiar/utils": "^2.0.2", @@ -3845,7 +4416,7 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -3858,7 +4429,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -3868,7 +4439,7 @@ "version": "1.7.1", "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.7.1.tgz", "integrity": "sha512-ODOov0sGMJMf3jPonOkgGqPknTsu+DdQ7kD++gz8aI+aFMOMHFbWAA2taqXXVTdP+OTOQR/znGvSpmkeI0WTYQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.7.0", @@ -4490,6 +5061,16 @@ "undici-types": "~8.3.0" } }, + "node_modules/@types/readable-stream": { + "version": "4.0.24", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.24.tgz", + "integrity": "sha512-NRvUNC/JFGPJvqdAfEve8oginbM6V08u5NzLWpG8MwA2kTPOLnqk+wpwuPT+mp3aUsxyuT6m2gnrPuHYCruzEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", @@ -4911,6 +5492,19 @@ } } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.17.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", @@ -4934,6 +5528,88 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/aedes": { + "version": "0.51.3", + "resolved": "https://registry.npmjs.org/aedes/-/aedes-0.51.3.tgz", + "integrity": "sha512-aQfiI9w3RbqnowNCdcGMmCtxBFXN9bhJFcuZm24U5/NU06V3MCl42jWK2GUnu8rOypR2Ahi/aEcgq3w7CMcycg==", + "dev": true, + "license": "MIT", + "dependencies": { + "aedes-packet": "^3.0.0", + "aedes-persistence": "^9.1.2", + "end-of-stream": "^1.4.4", + "fastfall": "^1.5.1", + "fastparallel": "^2.4.1", + "fastseries": "^2.0.0", + "hyperid": "^3.2.0", + "mqemitter": "^6.0.0", + "mqtt-packet": "^9.0.0", + "retimer": "^4.0.0", + "reusify": "^1.0.4", + "uuid": "^10.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/aedes" + } + }, + "node_modules/aedes-packet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aedes-packet/-/aedes-packet-3.0.0.tgz", + "integrity": "sha512-swASey0BxGs4/npZGWoiVDmnEyPvVFIRY6l2LVKL4rbiW8IhcIGDLfnb20Qo8U20itXlitAKPQ3MVTEbOGG5ZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mqtt-packet": "^7.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/aedes-packet/node_modules/mqtt-packet": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-7.1.2.tgz", + "integrity": "sha512-FFZbcZ2omsf4c5TxEQfcX9hI+JzDpDKPT46OmeIBpVA7+t32ey25UNqlqNXTmeZOr5BLsSIERpQQLsFWJS94SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/aedes-persistence": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/aedes-persistence/-/aedes-persistence-9.1.2.tgz", + "integrity": "sha512-2Wlr5pwIK0eQOkiTwb8ZF6C20s8UPUlnsJ4kXYePZ3JlQl0NbBA176mzM8wY294BJ5wybpNc9P5XEQxqadRNcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aedes-packet": "^3.0.0", + "qlobber": "^7.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/aedes/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/aes-js": { "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", @@ -5309,7 +5985,7 @@ "version": "3.0.10", "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "pvtsutils": "^1.3.6", @@ -7126,6 +7802,48 @@ "license": "MIT", "optional": true }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -7510,6 +8228,16 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -7614,6 +8342,20 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-unique-numbers": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", + "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.1.0" + } + }, "node_modules/fast-uri": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", @@ -7631,6 +8373,37 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fastfall": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", + "integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "reusify": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fastparallel": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz", + "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4", + "xtend": "^4.0.2" + } + }, + "node_modules/fastseries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-2.0.0.tgz", + "integrity": "sha512-XBU9RXeoYc2/VnvMhplAxEmZLfIk7cvTBu+xwoBuTI8pL19E03cmca17QQycKIdxgwCeFA/a4u27gv1h3ya5LQ==", + "dev": true, + "license": "ISC" + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -8114,6 +8887,42 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/gun": { + "version": "0.2020.1241", + "resolved": "https://registry.npmjs.org/gun/-/gun-0.2020.1241.tgz", + "integrity": "sha512-rmGqLuJj4fAuZ/0lddCvXHbENPkEnBOBYpq+kXHrwQ5RdNtQ5p0Io99lD1qUXMFmtwNacQ/iqo3VTmjmMyAYZg==", + "license": "(Zlib OR MIT OR Apache-2.0)", + "dependencies": { + "ws": "^7.2.1" + }, + "engines": { + "node": ">=0.8.4" + }, + "optionalDependencies": { + "@peculiar/webcrypto": "^1.1.1" + } + }, + "node_modules/gun/node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -8308,6 +9117,29 @@ "node": ">=10.17.0" } }, + "node_modules/hyperid": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hyperid/-/hyperid-3.3.0.tgz", + "integrity": "sha512-7qhCVT4MJIoEsNcbhglhdmBKb09QtcmJNiIQGq7js/Khf5FtQQ9bzcAuloeqBeee7XD7JqDeve9KNlQya5tSGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.2.1", + "uuid": "^8.3.2", + "uuid-parse": "^1.1.0" + } + }, + "node_modules/hyperid/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -10756,6 +11588,97 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "license": "MIT" }, + "node_modules/mqemitter": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/mqemitter/-/mqemitter-6.0.2.tgz", + "integrity": "sha512-8RGlznQx/Nb1xC3xKUFXHWov7pn7JdH++YVwlr6SLT6k3ft1h+ImGqZdVudbdKruFckIq9wheq9s4hgCivJDow==", + "dev": true, + "license": "ISC", + "dependencies": { + "fastparallel": "^2.4.1", + "qlobber": "^8.0.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mqemitter/node_modules/qlobber": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/qlobber/-/qlobber-8.0.1.tgz", + "integrity": "sha512-O+Wd1chXj5YE1DwmD+ae0bXiSLehmnS3czlC1R9FL/Nt/3q8uMS1bIHmg2lJfCoiimCxClWM8AAuJrF0EvNiog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/mqtt-packet": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz", + "integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt-packet/node_modules/bl": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.6.tgz", + "integrity": "sha512-jLsPgN/YSvPUg9UX0Kd73CXpm2Psg9FxMeCSXnk3WBO3CMT10JMwijubhGfHCnFu6TPn1ei3b975dxv7K2pWVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/mqtt-packet/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/mqtt-packet/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -11599,6 +12522,16 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -11691,7 +12624,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -11701,12 +12634,22 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=16.0.0" } }, + "node_modules/qlobber": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/qlobber/-/qlobber-7.0.1.tgz", + "integrity": "sha512-FsFg9lMuMEFNKmTO9nV7tlyPhx8BmskPPjH2akWycuYVTtWaVwhW5yCHLJQ6Q+3mvw5cFX2vMfW2l9z2SiYAbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/qrcode": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", @@ -12056,6 +12999,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/retimer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retimer/-/retimer-4.0.0.tgz", + "integrity": "sha512-fZIVtvbOsQsxNSDhpdPOX4lx5Ss2ni+S72AUBitARpFhtA3UzrAjQ6gDtypB2/+l7L+1VQgAgpvAKY66mElH0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "worker-timers": "^7.0.75" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -12065,6 +13018,17 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -12748,6 +13712,12 @@ "utf8-byte-length": "^1.0.1" } }, + "node_modules/ts-pattern": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.9.0.tgz", + "integrity": "sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==", + "license": "MIT" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -13037,6 +14007,13 @@ "uuid": "dist-node/bin/uuid" } }, + "node_modules/uuid-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", + "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==", + "dev": true, + "license": "MIT" + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -13138,7 +14115,7 @@ "version": "1.9.2", "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.9.2.tgz", "integrity": "sha512-gsXecm82UQNlTBURJGuqOWy1Ww08S3kZUcr3aOJS02Pk0xLtkfeUAVC0u0xhgdonFme80edSJUIJyuvL/7250Q==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.7.0", @@ -13148,6 +14125,12 @@ "tslib": "^2.8.1" } }, + "node_modules/websocket-mqtt": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/websocket-mqtt/-/websocket-mqtt-0.0.7.tgz", + "integrity": "sha512-+33fT52HJ3IlJdybH/em5TNmswwxcDCSyubernwVCaXKf7/RCEg95Lr2U51Cgev1/dqi9dUgOyozhUK/09e4IA==", + "license": "LGPL-3.0" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13180,6 +14163,43 @@ "node": ">=0.10.0" } }, + "node_modules/worker-timers": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", + "integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.8", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-broker": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz", + "integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "fast-unique-numbers": "^8.0.13", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-worker": { + "version": "7.0.71", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz", + "integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -13281,6 +14301,16 @@ "node": ">=8.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index d876d461..c89c3078 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,9 @@ "radicle:reset": "rm -rf radicle-data && echo 'Radicle data reset.'", "identity:reset": "rm -rf ant-data ipfs-data radicle-data identity-data && echo 'All identity data reset (ant, ipfs, radicle, vault).'", "dapp:reset": "node scripts/reset-dapp-permissions.js", + "vendor:openlv": "node scripts/bundle-openlv.js", + "bridge:serve": "node scripts/serve-bridge.js", + "openlv:ios-harness": "node scripts/openlv-ios-harness.js", "serve:updates": "node scripts/serve-updates.js", "start:test-updater": "ENABLE_DEV_UPDATER=true npm start", "postinstall": "electron-builder install-app-deps" @@ -212,14 +215,17 @@ "@babel/preset-env": "^8.0.2", "@eslint/js": "^10.0.1", "@playwright/test": "^1.60.0", + "aedes": "^0.51.3", "babel-jest": "^30.4.1", "dotenv-cli": "^11.0.0", "electron": "^43.0.0", "electron-builder": "^26.8.1", + "esbuild": "^0.28.1", "eslint": "^10.4.0", "globals": "^17.6.0", "jest": "^30.4.2", - "prettier": "^3.8.3" + "prettier": "^3.8.3", + "ws": "^8.21.0" }, "dependencies": { "@adraffy/ens-normalize": "^1.11.1", @@ -230,6 +236,8 @@ "@ledgerhq/hw-app-eth": "^7.8.8", "@ledgerhq/hw-transport-node-hid": "^6.33.5", "@metamask/browser-passworder": "^6.0.0", + "@openlv/core": "^0.0.2", + "@openlv/session": "^0.0.3", "@scure/bip39": "^2.2.0", "@x402/core": "^2.12.0", "@x402/evm": "^2.12.0", diff --git a/scripts/build.js b/scripts/build.js index ac9eceb9..b11095af 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -58,6 +58,24 @@ if (archs.length === 0) { else archs.push('arm64', 'x64'); // Linux defaults to both } +// Distributables must not ship the interim remote-signing bridge origin +// (personal test deployment — see the pre-merge checklist on PR #159). +// Override for local experiments only: FREEDOM_ALLOW_INTERIM_BRIDGE=1. +if (dist && process.env.FREEDOM_ALLOW_INTERIM_BRIDGE !== '1') { + const remoteSession = fs.readFileSync( + path.join(__dirname, '..', 'src', 'renderer', 'lib', 'wallet', 'remote-session.js'), + 'utf8' + ); + if (remoteSession.includes('florianglatz.eth.limo')) { + console.error( + 'Error: BRIDGE_ORIGIN in src/renderer/lib/wallet/remote-session.js still points at the ' + + 'interim test deployment. Deploy freedom-bridge to the production origin and update the ' + + 'constant before building a distributable (FREEDOM_ALLOW_INTERIM_BRIDGE=1 to override locally).' + ); + process.exit(1); + } +} + // 1. Check binaries for the target platform/arch const checkArgs = [`--${platform}`, ...archs.map((a) => `--${a}`)].join(' '); console.log(`\n→ Checking binaries: npm run check-binaries -- ${checkArgs}\n`); diff --git a/scripts/bundle-openlv.js b/scripts/bundle-openlv.js new file mode 100644 index 00000000..d8d898b3 --- /dev/null +++ b/scripts/bundle-openlv.js @@ -0,0 +1,126 @@ +/** + * Bundle the @openlv/* packages (LGPL-3.0) into a single ES module for the + * chrome renderer, which loads plain `type="module"` scripts and cannot + * resolve bare npm specifiers. + * + * The output (src/renderer/vendor/openlv.esm.js) is committed like the + * other vendor files; re-run this script after bumping the @openlv + * dependencies: + * + * node scripts/bundle-openlv.js + * + * Keeping the LGPL code in one clearly-labelled, regenerable file (rather + * than mixed into app bundles) is also what makes it trivially replaceable, + * as the LGPL asks. + * + * `connectSession` is deliberately left out so tree-shaking drops the + * gundb/ntfy signaling backends it would drag in via dynamic imports — + * the client role (bridge page) instead calls `createSession` with the + * decoded URI parameters and the explicit mqtt layer, which is the same + * thing minus the dynamic protocol lookup. + * + * A second flavor, openlv.iife.js (`window.OpenLV`), is built for freedom + * mobile's hidden-WKWebView engine: WKWebView refuses ES-module imports + * from file:// pages (opaque origin + CORS), but classic scripts load + * fine, and file:// stays a secure context so `crypto.subtle` works. + * + * The bridge page (solardev-xyz/freedom-bridge) and freedom mobile + * (solardev-xyz/freedom-browser-ios) vendor their own copies; when + * their sibling checkouts are present they are refreshed automatically + * from this one build, so the repos can't drift. + */ + +const fs = require('fs'); +const path = require('path'); + +const esbuild = require('esbuild'); + +const openlvVersion = require( + path.join(__dirname, '..', 'node_modules', '@openlv', 'session', 'package.json') +).version; + +const ENTRY = ` +export { createSession, SESSION_STATE } from '@openlv/session'; +export { encodeConnectionURL, decodeConnectionURL, OPENLV_PROTOCOL_VERSION } from '@openlv/core'; +export { mqtt } from '@openlv/signaling/mqtt'; +export { webrtc } from '@openlv/transport/webrtc'; +`; + +const banner = (filename) => `/*! + * ${filename} — bundled from @openlv/session@${openlvVersion} and its + * dependencies (https://github.com/v3xlabs/open-lavatory, LGPL-3.0-only). + * Generated by scripts/bundle-openlv.js — do not edit by hand. + */`; + +// The same surface serves both roles: freedom's renderer hosts sessions +// (shows the QR); the bridge page joins them (client role — createSession +// with the URI's `h` parameter takes that path). Built once, copied — +// the copies can never drift. +const ESM_OUTPUT = path.join(__dirname, '..', 'src', 'renderer', 'vendor', 'openlv.esm.js'); +// Intermediate only — the iife flavor's sole home is the iOS repo. +const IIFE_OUTPUT = path.join(require('os').tmpdir(), 'openlv.iife.js'); + +// Sibling checkouts vendoring their own copies — synced when present +// (dev machines), reported otherwise (CI). +const SIBLING_COPIES = [ + { + from: ESM_OUTPUT, + to: path.join(__dirname, '..', '..', 'freedom-bridge', 'openlv.esm.js'), + }, + { + from: IIFE_OUTPUT, + to: path.join( + __dirname, '..', '..', 'nodes', 'swarm-mobile-ios', + 'Freedom', 'Freedom', 'Wallet', 'OpenLV', 'openlv.iife.js', + ), + }, +]; + +async function main() { + const shared = { + stdin: { + contents: ENTRY, + resolveDir: path.join(__dirname, '..'), + sourcefile: 'openlv-entry.js', + }, + bundle: true, + platform: 'browser', + target: 'es2022', + legalComments: 'inline', + minify: true, + }; + + await esbuild.build({ + ...shared, + format: 'esm', + outfile: ESM_OUTPUT, + banner: { js: banner('openlv.esm.js') }, + }); + + await esbuild.build({ + ...shared, + format: 'iife', + globalName: 'OpenLV', + outfile: IIFE_OUTPUT, + banner: { js: banner('openlv.iife.js') }, + }); + + const outputs = [ESM_OUTPUT]; + for (const { from, to } of SIBLING_COPIES) { + if (fs.existsSync(path.dirname(to))) { + fs.copyFileSync(from, to); + outputs.push(to); + } else { + console.log(`sibling checkout not found — copy ${from} to ${to} by hand`); + } + } + + for (const file of outputs) { + console.log(`Wrote ${file} (${(fs.statSync(file).size / 1024).toFixed(0)} KiB)`); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/scripts/openlv-ios-harness.js b/scripts/openlv-ios-harness.js new file mode 100644 index 00000000..0391d637 --- /dev/null +++ b/scripts/openlv-ios-harness.js @@ -0,0 +1,179 @@ +#!/usr/bin/env node +/** + * Cross-stack test host for the freedom-mobile (iOS) openlv wallet + * endpoint. Plays the "freedom desktop" role over the real openlv + * stack: a local MQTT broker for signaling plus a headless Chromium + * page running the same vendored `openlv.esm.js` the renderer uses + * (Node has no WebRTC, so the host session lives in a browser context, + * exactly like the remote-signing E2E). + * + * The iOS simulator shares the Mac's loopback, so the XCTest suite + * reaches both the control endpoints and the broker at 127.0.0.1. + * + * Control surface (http://127.0.0.1:8798): + * GET /uri → {uri} — openlv:// URI of the current host session + * GET /state → {phase, uri, exchanges: [{method, response}], error} + * GET /reset → reloads the host page, starting a fresh session + * (each XCTest consumes one session; call this first) + * + * Once the wallet endpoint links up, the host sends the same sequence a + * desktop signing job produces — eth_requestAccounts, the + * wallet_switchEthereumChain pre-flight, then personal_sign against the + * connected account — and records every response for the XCTest to + * assert on. + * + * Run from the repo root: `npm run openlv:ios-harness` + */ + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const { chromium } = require('@playwright/test'); +const { startLocalMqttBroker } = require('../test/helpers/local-mqtt-broker'); +const { WEBRTC_LOCAL_SWITCH } = require('../test/helpers/webrtc'); + +const PORT = Number(process.env.OPENLV_HARNESS_PORT) || 8798; + +const MESSAGE = 'freedom openlv ios harness'; + +function buildHostPage(signalingUrl) { + return ` +`; +} + +async function main() { + const broker = await startLocalMqttBroker(); + let state; + const resetState = () => { + state = { phase: 'starting', uri: null, exchanges: [], error: null }; + }; + resetState(); + let page = null; + + const esmBundle = fs.readFileSync( + path.join(__dirname, '..', 'src', 'renderer', 'vendor', 'openlv.esm.js') + ); + const hostPage = buildHostPage(broker.url); + + const server = http.createServer((req, res) => { + const respond = (status, type, body) => { + res.writeHead(status, { 'content-type': type }); + res.end(body); + }; + const url = new URL(req.url, `http://127.0.0.1:${PORT}`); + switch (url.pathname) { + case '/uri': + return respond(200, 'application/json', JSON.stringify({ uri: state.uri })); + case '/state': + return respond(200, 'application/json', JSON.stringify(state)); + // /reset[?mode=tx] — fresh host session; mode picks the request + // sequence the host sends (default: personal_sign; tx: broadcast). + case '/reset': { + if (!page) return respond(503, 'text/plain', 'host page not up yet'); + const mode = url.searchParams.get('mode'); + resetState(); + page + .goto(`http://127.0.0.1:${PORT}/${mode ? `?mode=${encodeURIComponent(mode)}` : ''}`) + .then(() => respond(200, 'application/json', '{"ok":true}')) + .catch((err) => respond(500, 'text/plain', String(err))); + return undefined; + } + case '/': + return respond(200, 'text/html', hostPage); + case '/openlv.esm.js': + return respond(200, 'text/javascript', esmBundle); + default: + return respond(404, 'text/plain', 'not found'); + } + }); + await new Promise((resolve) => server.listen(PORT, '127.0.0.1', resolve)); + + // Raw loopback ICE candidates instead of mDNS names, so the WebKit + // peer can pair against them. + const browser = await chromium.launch({ args: [WEBRTC_LOCAL_SWITCH] }); + page = await browser.newPage(); + page.on('console', (message) => console.log('[host page]', message.text())); + await page.exposeFunction('__report', (updateJson) => { + const update = JSON.parse(updateJson); + if (update.exchange) { + state.exchanges.push(update.exchange); + } else { + Object.assign(state, update); + } + console.log('[harness]', updateJson.slice(0, 300)); + }); + await page.goto(`http://127.0.0.1:${PORT}/`); + + console.log(`[harness] control surface at http://127.0.0.1:${PORT} (uri, state)`); + console.log(`[harness] signaling broker at ${broker.url}`); + + const shutdown = async () => { + await browser.close().catch(() => {}); + await broker.close().catch(() => {}); + server.close(); + process.exit(0); + }; + process.on('SIGINT', shutdown); + process.on('SIGTERM', shutdown); +} + +main().catch((err) => { + console.error('[harness] failed to start:', err); + process.exit(1); +}); diff --git a/scripts/serve-bridge.js b/scripts/serve-bridge.js new file mode 100644 index 00000000..1d6d4302 --- /dev/null +++ b/scripts/serve-bridge.js @@ -0,0 +1,55 @@ +/** + * Serve the wallet bridge page on a local port — for development and + * the remote-signing E2E test. Static files only. + * + * The page lives in its own repo (solardev-xyz/freedom-bridge, deployed + * independently to Swarm); this expects a sibling checkout, overridable + * via FREEDOM_BRIDGE_DIR. + * + * node scripts/serve-bridge.js [port] (default 8797) + */ + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const BRIDGE_DIR = + process.env.FREEDOM_BRIDGE_DIR || path.join(__dirname, '..', '..', 'freedom-bridge'); + +/** False when the sibling checkout is missing — callers skip or error. */ +function bridgeAvailable() { + return fs.existsSync(path.join(BRIDGE_DIR, 'index.html')); +} +const MIME = { + '.html': 'text/html; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', +}; + +function createBridgeServer() { + if (!bridgeAvailable()) { + throw new Error( + `freedom-bridge checkout not found at ${BRIDGE_DIR} — clone ` + + 'github.com/solardev-xyz/freedom-bridge next to this repo, or set FREEDOM_BRIDGE_DIR' + ); + } + return http.createServer((req, res) => { + const urlPath = new URL(req.url, 'http://localhost').pathname; + const rel = urlPath === '/' ? 'index.html' : urlPath.slice(1); + const file = path.join(BRIDGE_DIR, rel); + if (!file.startsWith(BRIDGE_DIR) || !fs.existsSync(file) || !fs.statSync(file).isFile()) { + res.writeHead(404).end('not found'); + return; + } + res.writeHead(200, { 'Content-Type': MIME[path.extname(file)] || 'application/octet-stream' }); + fs.createReadStream(file).pipe(res); + }); +} + +module.exports = { createBridgeServer, bridgeAvailable }; + +if (require.main === module) { + const port = Number(process.argv[2]) || 8797; + createBridgeServer().listen(port, '127.0.0.1', () => { + console.log(`Bridge page at http://127.0.0.1:${port}/`); + }); +} diff --git a/src/main/identity-manager.js b/src/main/identity-manager.js index 5b56dd4f..fbf76b16 100644 --- a/src/main/identity-manager.js +++ b/src/main/identity-manager.js @@ -286,7 +286,7 @@ async function getUserWalletKey(walletIndex) { throw new Error(`Wallet with index ${walletIndex} does not exist`); } if (record.type !== WALLET_TYPES.MNEMONIC) { - throw new Error('Hardware wallet accounts have no derivable private key'); + throw new Error('This account has no derivable private key — the key never leaves its device'); } const identity = await loadIdentityModule(); @@ -793,6 +793,13 @@ async function exportMnemonic() { const WALLET_TYPES = { MNEMONIC: 'mnemonic', LEDGER: 'ledger', + REMOTE: 'remote', // phone / other device signing over openlv +}; + +/** User-facing labels for device account types (auto-names, error text). */ +const DEVICE_LABELS = { + [WALLET_TYPES.LEDGER]: 'Ledger', + [WALLET_TYPES.REMOTE]: 'Phone', }; /** @@ -931,9 +938,9 @@ async function getDerivedWallets() { const type = wallet.type || WALLET_TYPES.MNEMONIC; let address = null; - if (type === WALLET_TYPES.LEDGER) { - // Hardware accounts: the address was read from the device when the - // account was added; there is nothing to derive locally. + if (type !== WALLET_TYPES.MNEMONIC) { + // Device accounts (Ledger, phone): the address was read from the + // device when the account was added; nothing to derive locally. address = wallet.address || null; } else if (mnemonic) { // Derive address from mnemonic @@ -961,25 +968,23 @@ async function getDerivedWallets() { } /** - * Add a Ledger hardware-wallet account to the wallet list. + * Add a device account (Ledger, phone) to the wallet list. * - * The address comes from the device during account discovery and is + * The address comes from the device when the account is added and is * persisted — it can never be re-derived locally. Does not require the * vault to be unlocked (no mnemonic involved), only that a vault exists * so there is a wallet list to add to. * - * @param {string} name - Display name ('' → auto "Ledger N") - * @param {string} address - Checksummed address read from the device - * @param {string} path - Derivation path in device format (e.g. "44'/60'/0'/0/0") - * @returns {Promise<{index: number, name: string, address: string, type: string, path: string}>} + * @param {string} type - WALLET_TYPES.LEDGER or WALLET_TYPES.REMOTE + * @param {string} name - Display name ('' → auto "