From 994bc94935edfeea6049d60a21aeeb59324f378c Mon Sep 17 00:00:00 2001 From: PhilReact Date: Sun, 27 Jul 2025 06:43:38 +0300 Subject: [PATCH] started testing sending --- electron/package-lock.json | 365 +++++++++++++++++++++++++++-- electron/package.json | 16 +- electron/src/lite-node/index.ts | 205 ++++++++++++++++ electron/src/lite-node/protocol.ts | 42 ++++ electron/src/preload.ts | 10 + electron/src/setup.ts | 16 ++ electron/src/test-lite-node.ts | 18 ++ electron/tsconfig.json | 3 +- 8 files changed, 656 insertions(+), 19 deletions(-) create mode 100644 electron/src/lite-node/index.ts create mode 100644 electron/src/lite-node/protocol.ts create mode 100644 electron/src/test-lite-node.ts diff --git a/electron/package-lock.json b/electron/package-lock.json index b3b1a6b..0317f38 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -1,29 +1,37 @@ { "name": "qortal-hub", - "version": "0.5.2", + "version": "0.5.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "qortal-hub", - "version": "0.5.2", + "version": "0.5.4", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", + "@noble/curves": "^1.9.4", + "@noble/ed25519": "^2.3.0", + "@stablelib/ed25519": "^2.0.2", + "@stablelib/x25519": "^2.0.1", "adm-zip": "^0.5.16", + "bs58": "^6.0.0", "chokidar": "^3.6.0", "electron-is-dev": "~2.0.0", "electron-serve": "~1.1.0", "electron-unhandled": "~4.0.1", "electron-updater": "^5.3.0", - "electron-window-state": "^5.0.3" + "electron-window-state": "^5.0.3", + "tweetnacl": "^1.0.3" }, "devDependencies": { "@electron/notarize": "^2.5.0", + "@types/node": "^24.1.0", "electron": "^32.3.1", "electron-builder": "^25.1.8", "shelljs": "^0.8.5", - "typescript": "^5.0.4" + "ts-node": "^10.9.2", + "typescript": "^5.8.3" } }, "node_modules/@capacitor-community/electron": { @@ -85,6 +93,19 @@ "tslib": "^2.1.0" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@develar/schema-utils": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", @@ -705,6 +726,34 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", @@ -773,6 +822,42 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/@noble/curves": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.4.tgz", + "integrity": "sha512-2bKONnuM53lINoDrSmK8qP8W271ms7pygDhZt4SiLOoLwBtoHqeCFi6RG42V8zd3mLHuJFhU/Bmaqo4nX0/kBw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/ed25519": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-2.3.0.tgz", + "integrity": "sha512-M7dvXL2B92/M7dw9+gzuydL8qn/jiqNHaoR3Q+cb1q1GHV7uwE17WCyFMG+Y+TZb5izcaXk5TdJRrDUxHXL78A==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@npmcli/fs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", @@ -878,6 +963,91 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@stablelib/binary": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-2.0.1.tgz", + "integrity": "sha512-U9iAO8lXgEDONsA0zPPSgcf3HUBNAqHiJmSHgZz62OvC3Hi2Bhc5kTnQ3S1/L+sthDTHtCMhcEiklmIly6uQ3w==", + "license": "MIT", + "dependencies": { + "@stablelib/int": "^2.0.1" + } + }, + "node_modules/@stablelib/bytes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-2.0.1.tgz", + "integrity": "sha512-QIzI6V7nkJA5CjOZ7GoceBd4CIKrJoC471VaI6jh1xPQ2cMhkhQK4HddyzCXOR2y+fBF3/5B2HO3FXXI9C+Xzg==", + "license": "MIT" + }, + "node_modules/@stablelib/ed25519": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-2.0.2.tgz", + "integrity": "sha512-d/lJ5sgzhtmpMIbKFWfev+i6WebBdIzzBpMzXtZdvUijoksjXosYFNqytoMj7cRshNj+/XTLYnnVMdZfd+penw==", + "license": "MIT", + "dependencies": { + "@stablelib/random": "^2.0.1", + "@stablelib/sha512": "^2.0.1", + "@stablelib/wipe": "^2.0.1" + } + }, + "node_modules/@stablelib/hash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-2.0.0.tgz", + "integrity": "sha512-u3WPSqGido8lwJuMcrBgM5K54LrPGhkWAdtsyccf7dGsLixAZUds77zOAbu7bvKPwQlmoByH0txBi5rTmEKuHg==", + "license": "MIT" + }, + "node_modules/@stablelib/int": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-2.0.1.tgz", + "integrity": "sha512-Ht63fQp3wz/F8U4AlXEPb7hfJOIILs8Lq55jgtD7KueWtyjhVuzcsGLSTAWtZs3XJDZYdF1WcSKn+kBtbzupww==", + "license": "MIT" + }, + "node_modules/@stablelib/keyagreement": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-2.0.1.tgz", + "integrity": "sha512-2+tWBLCMtWlHQ7GqjD5L+lQRyWtun4Lou0IOdTML8zuTuAS0EgihnHFx+4uMZwYU1In40J/WlpyKSLidHfStRQ==", + "license": "MIT", + "dependencies": { + "@stablelib/bytes": "^2.0.1" + } + }, + "node_modules/@stablelib/random": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-2.0.1.tgz", + "integrity": "sha512-W6GAtXEEs7r+dSbuBsvoFmlyL3gLxle41tQkjKu17dDWtDdjhVUbtRfRCQcCUeczwkgjQxMPopgwYEvxXtHXGw==", + "license": "MIT", + "dependencies": { + "@stablelib/binary": "^2.0.1", + "@stablelib/wipe": "^2.0.1" + } + }, + "node_modules/@stablelib/sha512": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-2.0.1.tgz", + "integrity": "sha512-DUNe5cbnoH3sSIN+MG04RvTCLXtkbyy/SnQxiNO+GgF/KSXkkUSlF6mUVvCUdZBZ2X3NgogR+tAvaRSn8wxnLw==", + "license": "MIT", + "dependencies": { + "@stablelib/binary": "^2.0.1", + "@stablelib/hash": "^2.0.0", + "@stablelib/wipe": "^2.0.1" + } + }, + "node_modules/@stablelib/wipe": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-2.0.1.tgz", + "integrity": "sha512-1eU2K9EgOcV4qc9jcP6G72xxZxEm5PfeI5H55l08W95b4oRJaqhmlWRc4xZAm6IVSKhVNxMi66V67hCzzuMTAg==", + "license": "MIT" + }, + "node_modules/@stablelib/x25519": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-2.0.1.tgz", + "integrity": "sha512-qi04HS2puHaBf50kM/kes5QcZFGsx8yF0YmCjLCOa/LPmnBaKEKX9ZR82OnnCwMn72YH13R/bBZgr/UP0aPFfA==", + "license": "MIT", + "dependencies": { + "@stablelib/keyagreement": "^2.0.1", + "@stablelib/random": "^2.0.1", + "@stablelib/wipe": "^2.0.1" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -901,6 +1071,34 @@ "node": ">= 10" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -958,12 +1156,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", + "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/plist": { @@ -1042,6 +1240,32 @@ "dev": true, "license": "ISC" }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/adm-zip": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", @@ -1441,6 +1665,13 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1506,6 +1737,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "license": "MIT" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1619,6 +1856,15 @@ "node": ">=8" } }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -2294,6 +2540,13 @@ "node": ">= 10" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2458,6 +2711,16 @@ "license": "MIT", "optional": true }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-compare": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", @@ -4278,6 +4541,13 @@ "node": ">=10" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, "node_modules/make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", @@ -5862,12 +6132,62 @@ "utf8-byte-length": "^1.0.1" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -5890,9 +6210,9 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5904,9 +6224,9 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, "node_modules/unique-filename": { @@ -5976,6 +6296,13 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/verror": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", @@ -6155,6 +6482,16 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/electron/package.json b/electron/package.json index 12aade9..32996b2 100644 --- a/electron/package.json +++ b/electron/package.json @@ -38,20 +38,28 @@ }, "dependencies": { "@capacitor-community/electron": "^5.0.0", + "@noble/curves": "^1.9.4", + "@noble/ed25519": "^2.3.0", + "@stablelib/ed25519": "^2.0.2", + "@stablelib/x25519": "^2.0.1", "adm-zip": "^0.5.16", + "bs58": "^6.0.0", "chokidar": "^3.6.0", "electron-is-dev": "~2.0.0", "electron-serve": "~1.1.0", "electron-unhandled": "~4.0.1", "electron-updater": "^5.3.0", - "electron-window-state": "^5.0.3" + "electron-window-state": "^5.0.3", + "tweetnacl": "^1.0.3" }, "devDependencies": { + "@electron/notarize": "^2.5.0", + "@types/node": "^24.1.0", "electron": "^32.3.1", "electron-builder": "^25.1.8", - "@electron/notarize": "^2.5.0", - "typescript": "^5.0.4", - "shelljs": "^0.8.5" + "shelljs": "^0.8.5", + "ts-node": "^10.9.2", + "typescript": "^5.8.3" }, "keywords": [ "capacitor", diff --git a/electron/src/lite-node/index.ts b/electron/src/lite-node/index.ts new file mode 100644 index 0000000..f16a96a --- /dev/null +++ b/electron/src/lite-node/index.ts @@ -0,0 +1,205 @@ +import net from 'net'; +import crypto from 'crypto'; +import { ed25519, x25519 } from '@noble/curves/ed25519'; +import { sha512 } from '@noble/hashes/sha512'; + +export const SEED_PEERS = ['127.0.0.1']; + +export enum MessageType { + HELLO = 0, + CHALLENGE = 2, + RESPONSE = 3, +} + +function parseMessage(buffer: Buffer) { + if (buffer.length < 17) return null; + if (buffer.subarray(0, 4).toString('ascii') !== 'QORT') return null; + + const messageType = buffer.readUInt32BE(4); + const payloadLength = buffer.readUInt32BE(9); + const checksum = buffer.subarray(13, 17); + const payload = buffer.subarray(17, 17 + payloadLength); + + const expectedChecksum = crypto + .createHash('sha256') + .update(payload) + .digest() + .subarray(0, 4); + if (!checksum.equals(expectedChecksum)) return null; + + return { + messageType, + payload, + totalLength: 17 + payloadLength, + }; +} + +function createHelloPayload(): Buffer { + const timestamp = Buffer.alloc(8); + timestamp.writeBigInt64BE(BigInt(Date.now())); + + const version = Buffer.from('qortal-5.0.2'); + const address = Buffer.from('lite-node'); + const versionLen = Buffer.alloc(4); + const addressLen = Buffer.alloc(4); + + versionLen.writeUInt32BE(version.length); + addressLen.writeUInt32BE(address.length); + + return Buffer.concat([timestamp, versionLen, version, addressLen, address]); +} + +function createChallengePayload( + publicKey: Uint8Array, + challenge: Uint8Array +): Buffer { + return Buffer.concat([Buffer.from(publicKey), Buffer.from(challenge)]); +} + +function encodeFramedMessage(type: number, payload: Buffer): Buffer { + const header = Buffer.from('QORT'); + const typeBuf = Buffer.alloc(4); + typeBuf.writeUInt32BE(type); + const hasId = Buffer.from([0]); + const length = Buffer.alloc(4); + length.writeUInt32BE(payload.length); + const checksum = crypto + .createHash('sha256') + .update(payload) + .digest() + .subarray(0, 4); + return Buffer.concat([header, typeBuf, hasId, length, checksum, payload]); +} + +function ed25519ToX25519Private(edPrivateKey: Uint8Array): Uint8Array { + const seed = edPrivateKey.slice(0, 32); + const hash = sha512(seed); + const h = new Uint8Array(hash); + h[0] &= 248; + h[31] &= 127; + h[31] |= 64; + return h.slice(0, 32); +} + +function ed25519ToX25519Public(edPublicKey: Uint8Array): Uint8Array { + return ed25519.utils.toMontgomery(edPublicKey); +} + +export class LiteNodeClient { + private socket: net.Socket | null = null; + private buffer = Buffer.alloc(0); + + private edPrivateKey: Uint8Array; + private edPublicKey: Uint8Array; + private xPrivateKey: Uint8Array; + private xPublicKey: Uint8Array; + + private theirEdPublicKey: Uint8Array | null = null; + private theirXPublicKey: Uint8Array | null = null; + private theirChallenge: Uint8Array | null = null; + private ourChallenge = crypto.randomBytes(32); + + constructor( + private host: string, + private port: number = 12392 + ) { + const edSeed = ed25519.utils.randomPrivateKey(); // 32-byte seed + const edPublicKey = ed25519.getPublicKey(edSeed); + + const edPrivateKey = new Uint8Array(64); + edPrivateKey.set(edSeed); + edPrivateKey.set(edPublicKey, 32); + + this.edPrivateKey = edPrivateKey; + this.edPublicKey = edPublicKey; + + this.xPrivateKey = ed25519ToX25519Private(this.edPrivateKey); + this.xPublicKey = x25519.getPublicKey(this.xPrivateKey); + } + + private handleChallenge(payload: Buffer) { + this.theirEdPublicKey = payload.subarray(0, 32); + this.theirXPublicKey = ed25519ToX25519Public(this.theirEdPublicKey); + this.theirChallenge = payload.subarray(32, 64); + + const sharedSecret = x25519.getSharedSecret( + this.xPrivateKey, + this.theirXPublicKey + ); + const combined = Buffer.concat([ + Buffer.from(sharedSecret), + this.theirChallenge, + ]); + const responseHash = crypto.createHash('sha256').update(combined).digest(); + + const nonce = Buffer.alloc(4); + nonce.writeUInt32BE(0); + const responsePayload = Buffer.concat([nonce, responseHash]); + + console.log( + '🔐 Shared secret (hex):', + Buffer.from(sharedSecret).toString('hex') + ); + + this.sendMessage(MessageType.RESPONSE, responsePayload); + } + + connect(): Promise { + return new Promise((resolve, reject) => { + this.socket = net.createConnection( + { host: this.host, port: this.port }, + () => { + console.log(`✅ Connected to ${this.host}:${this.port}`); + const helloPayload = createHelloPayload(); + this.sendMessage(MessageType.HELLO, helloPayload); + resolve(); + } + ); + + this.socket.on('data', (data: Buffer) => { + this.buffer = Buffer.concat([this.buffer, data]); + while (this.buffer.length >= 17) { + const parsed = parseMessage(this.buffer); + if (!parsed) break; + + const { messageType, payload, totalLength } = parsed; + this.buffer = this.buffer.subarray(totalLength); + + switch (messageType) { + case MessageType.HELLO: + this.sendMessage( + MessageType.CHALLENGE, + createChallengePayload(this.edPublicKey, this.ourChallenge) + ); + break; + + case MessageType.CHALLENGE: + this.handleChallenge(payload); + break; + + default: + console.warn(`⚠️ Unhandled message type: ${messageType}`); + } + } + }); + + this.socket.on('error', (err) => { + console.error('❌ Socket error:', err); + reject(err); + }); + + this.socket.on('end', () => console.log('🔌 Disconnected')); + this.socket.on('timeout', () => console.warn('⏳ Socket timeout')); + }); + } + + sendMessage(type: MessageType, payload: Buffer) { + if (!this.socket) throw new Error('Socket not connected'); + const framed = encodeFramedMessage(type, payload); + this.socket.write(framed); + } + + close() { + this.socket?.end(); + } +} diff --git a/electron/src/lite-node/protocol.ts b/electron/src/lite-node/protocol.ts new file mode 100644 index 0000000..df41caf --- /dev/null +++ b/electron/src/lite-node/protocol.ts @@ -0,0 +1,42 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import crypto from 'crypto'; + +export function encodeMessage(type: number, payload: any): Buffer { + // For demo purposes, we assume payload is JSON + const payloadBuffer = Buffer.from(JSON.stringify(payload), 'utf-8'); + const payloadLength = payloadBuffer.length; + + const buffer = Buffer.alloc(4 + 8 + payloadLength); // type + nonce + payload + + buffer.writeInt32BE(type, 0); + + // Random nonce (8 bytes) + const nonce = crypto.randomBytes(8); + nonce.copy(buffer, 4); + + // Payload + payloadBuffer.copy(buffer, 12); + + return buffer; +} + +export function decodeMessage(buffer: Buffer): { + type: number; + nonce: Buffer; + payload: any; +} { + const type = buffer.readInt32BE(0); + const nonce = buffer.subarray(4, 12); + const payloadBuffer = buffer.subarray(12); + let payload; + + try { + payload = JSON.parse(payloadBuffer.toString('utf-8')); + } catch { + payload = payloadBuffer; + } + + return { type, nonce, payload }; +} diff --git a/electron/src/preload.ts b/electron/src/preload.ts index ddb33bc..6f7b5b9 100644 --- a/electron/src/preload.ts +++ b/electron/src/preload.ts @@ -1,3 +1,7 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + require('./rt/electron-rt'); // ------------------- User Preload starts here ------------------- @@ -63,4 +67,10 @@ contextBridge.exposeInMainWorld('walletStorage', { }, }); +contextBridge.exposeInMainWorld('liteNode', { + connect: () => ipcRenderer.invoke('liteNode:connect'), + send: (type: number, payload: any) => + ipcRenderer.invoke('liteNode:send', type, payload), +}); + ipcRenderer.send('test-ipc'); diff --git a/electron/src/setup.ts b/electron/src/setup.ts index 118da78..0b152ff 100644 --- a/electron/src/setup.ts +++ b/electron/src/setup.ts @@ -1,3 +1,7 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import type { CapacitorElectronConfig } from '@capacitor-community/electron'; import { CapElectronEventEmitter, @@ -5,6 +9,7 @@ import { setupCapacitorElectronPlugins, } from '@capacitor-community/electron'; import chokidar from 'chokidar'; + import type { MenuItemConstructorOptions } from 'electron'; import { app, @@ -23,6 +28,7 @@ import windowStateKeeper from 'electron-window-state'; const AdmZip = require('adm-zip'); import { join } from 'path'; import { myCapacitorApp } from '.'; +import { LiteNodeClient } from './lite-node'; const fs = require('fs'); const path = require('path'); @@ -477,3 +483,13 @@ ipcMain.handle( return true; } ); + +const liteNode = new LiteNodeClient('your.qortal.peer.ip'); + +ipcMain.handle('liteNode:connect', async () => { + await liteNode.connect(); +}); + +ipcMain.handle('liteNode:send', async (_event, type: number, payload: any) => { + liteNode.sendMessage(type, payload); +}); diff --git a/electron/src/test-lite-node.ts b/electron/src/test-lite-node.ts new file mode 100644 index 0000000..af30512 --- /dev/null +++ b/electron/src/test-lite-node.ts @@ -0,0 +1,18 @@ +import { LiteNodeClient, SEED_PEERS } from './lite-node'; + +async function main() { + console.log('test'); + for (const ip of SEED_PEERS) { + const client = new LiteNodeClient(ip); + try { + await client.connect(); + // console.log(`Successfully connected to ${ip}`); + // Optionally send HELLO message here + break; + } catch (err) { + console.warn(`Failed to connect to ${ip}:`, err); + } + } +} + +main(); diff --git a/electron/tsconfig.json b/electron/tsconfig.json index 508f26c..4ab8873 100644 --- a/electron/tsconfig.json +++ b/electron/tsconfig.json @@ -11,6 +11,7 @@ "typeRoots": ["./node_modules/@types"], "allowJs": true, "rootDir": ".", - "skipLibCheck": true + "skipLibCheck": true, + "types": ["node"] } }