gnoman 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +24 -0
- package/.gnoman/contracts.json +4094 -0
- package/.gnoman/exec_package/runtime-debug.jsonl +45 -0
- package/.gnoman/holds.sqlite +0 -0
- package/.gnoman/license.json +7 -0
- package/.gnoman/safes.json +37 -0
- package/.gnoman/vanity-jobs.json +67 -0
- package/.gnoman/wallets.db +0 -0
- package/.prettierrc.json +6 -0
- package/CODex_TASKS.md +124 -0
- package/LICENSE.md +164 -0
- package/README.md +95 -0
- package/assets/GnoLogo.jpg +0 -0
- package/assets/self.png +0 -0
- package/backend/controllers/contractController.ts +49 -0
- package/backend/controllers/devToolsController.ts +76 -0
- package/backend/controllers/etherscanController.ts +59 -0
- package/backend/controllers/historyController.ts +7 -0
- package/backend/controllers/keyringController.ts +134 -0
- package/backend/controllers/robinhoodController.ts +80 -0
- package/backend/controllers/safeController.ts +167 -0
- package/backend/controllers/sandboxController.ts +63 -0
- package/backend/controllers/settingsController.ts +38 -0
- package/backend/controllers/walletController.ts +151 -0
- package/backend/index.ts +133 -0
- package/backend/licenses/license_public.pem +3 -0
- package/backend/licenses/verify_license.py +43 -0
- package/backend/routes/contractRoutes.ts +11 -0
- package/backend/routes/devToolsRoutes.ts +11 -0
- package/backend/routes/etherscanRoutes.ts +11 -0
- package/backend/routes/historyRoutes.ts +8 -0
- package/backend/routes/keyringRoutes.ts +25 -0
- package/backend/routes/licenseRoutes.ts +35 -0
- package/backend/routes/robinhoodRoutes.ts +22 -0
- package/backend/routes/runtimeRoutes.ts +29 -0
- package/backend/routes/safeRoutes.ts +28 -0
- package/backend/routes/sandboxRoutes.ts +17 -0
- package/backend/routes/settingsRoutes.ts +14 -0
- package/backend/routes/walletRoutes.ts +21 -0
- package/backend/services/chainlinkService.ts +65 -0
- package/backend/services/contractRegistryService.ts +205 -0
- package/backend/services/devToolsService.ts +251 -0
- package/backend/services/diagnosticsService.ts +350 -0
- package/backend/services/etherscanService.ts +152 -0
- package/backend/services/historyService.ts +89 -0
- package/backend/services/keyringAccessor.ts +4 -0
- package/backend/services/licenseService.ts +163 -0
- package/backend/services/onchain/abiRegistry.ts +57 -0
- package/backend/services/onchain/chainlinkClient.ts +56 -0
- package/backend/services/onchain/errors.ts +16 -0
- package/backend/services/onchain/etherscanClient.ts +94 -0
- package/backend/services/onchain/index.ts +76 -0
- package/backend/services/onchain/tenderlyRpcClient.ts +74 -0
- package/backend/services/onchain/types.ts +33 -0
- package/backend/services/onchainAutomationService.ts +424 -0
- package/backend/services/robinhood/auth.ts +42 -0
- package/backend/services/robinhood/client.ts +123 -0
- package/backend/services/robinhood/integrationService.ts +140 -0
- package/backend/services/robinhood/provider.ts +22 -0
- package/backend/services/robinhood/unofficialClient.ts +66 -0
- package/backend/services/rpcService.ts +44 -0
- package/backend/services/runtimeTelemetryService.ts +158 -0
- package/backend/services/safeConfigRepository.ts +205 -0
- package/backend/services/safeService.ts +588 -0
- package/backend/services/sandboxService.ts +157 -0
- package/backend/services/secureSettingsService.ts +45 -0
- package/backend/services/transactionHoldService.ts +223 -0
- package/backend/services/vanityService.ts +293 -0
- package/backend/services/walletService.ts +290 -0
- package/backend/services/walletStore.ts +179 -0
- package/backend/types/express-async-handler.d.ts +13 -0
- package/backend/types/keyring.d.ts +19 -0
- package/backend/utils/abiResolver.ts +208 -0
- package/backend/utils/http.ts +6 -0
- package/backend/utils/secretsResolver.ts +150 -0
- package/backend/utils/signer.ts +11 -0
- package/backend/workers/vanityWorker.ts +76 -0
- package/capacitor.config.ts +13 -0
- package/cli/gnoman.ts +424 -0
- package/contracts/OracleConsumer.sol +20 -0
- package/contracts/PriceFeedConsumer.sol +22 -0
- package/dist/backend/backend/controllers/contractController.js +41 -0
- package/dist/backend/backend/controllers/contractController.js.map +1 -0
- package/dist/backend/backend/controllers/devToolsController.js +63 -0
- package/dist/backend/backend/controllers/devToolsController.js.map +1 -0
- package/dist/backend/backend/controllers/etherscanController.js +53 -0
- package/dist/backend/backend/controllers/etherscanController.js.map +1 -0
- package/dist/backend/backend/controllers/historyController.js +12 -0
- package/dist/backend/backend/controllers/historyController.js.map +1 -0
- package/dist/backend/backend/controllers/keyringController.js +126 -0
- package/dist/backend/backend/controllers/keyringController.js.map +1 -0
- package/dist/backend/backend/controllers/robinhoodController.js +69 -0
- package/dist/backend/backend/controllers/robinhoodController.js.map +1 -0
- package/dist/backend/backend/controllers/safeController.js +137 -0
- package/dist/backend/backend/controllers/safeController.js.map +1 -0
- package/dist/backend/backend/controllers/sandboxController.js +48 -0
- package/dist/backend/backend/controllers/sandboxController.js.map +1 -0
- package/dist/backend/backend/controllers/settingsController.js +34 -0
- package/dist/backend/backend/controllers/settingsController.js.map +1 -0
- package/dist/backend/backend/controllers/walletController.js +140 -0
- package/dist/backend/backend/controllers/walletController.js.map +1 -0
- package/dist/backend/backend/index.js +119 -0
- package/dist/backend/backend/index.js.map +1 -0
- package/dist/backend/backend/routes/contractRoutes.js +44 -0
- package/dist/backend/backend/routes/contractRoutes.js.map +1 -0
- package/dist/backend/backend/routes/devToolsRoutes.js +44 -0
- package/dist/backend/backend/routes/devToolsRoutes.js.map +1 -0
- package/dist/backend/backend/routes/etherscanRoutes.js +44 -0
- package/dist/backend/backend/routes/etherscanRoutes.js.map +1 -0
- package/dist/backend/backend/routes/historyRoutes.js +41 -0
- package/dist/backend/backend/routes/historyRoutes.js.map +1 -0
- package/dist/backend/backend/routes/keyringRoutes.js +18 -0
- package/dist/backend/backend/routes/keyringRoutes.js.map +1 -0
- package/dist/backend/backend/routes/licenseRoutes.js +30 -0
- package/dist/backend/backend/routes/licenseRoutes.js.map +1 -0
- package/dist/backend/backend/routes/robinhoodRoutes.js +14 -0
- package/dist/backend/backend/routes/robinhoodRoutes.js.map +1 -0
- package/dist/backend/backend/routes/runtimeRoutes.js +26 -0
- package/dist/backend/backend/routes/runtimeRoutes.js.map +1 -0
- package/dist/backend/backend/routes/safeRoutes.js +61 -0
- package/dist/backend/backend/routes/safeRoutes.js.map +1 -0
- package/dist/backend/backend/routes/sandboxRoutes.js +50 -0
- package/dist/backend/backend/routes/sandboxRoutes.js.map +1 -0
- package/dist/backend/backend/routes/settingsRoutes.js +10 -0
- package/dist/backend/backend/routes/settingsRoutes.js.map +1 -0
- package/dist/backend/backend/routes/walletRoutes.js +54 -0
- package/dist/backend/backend/routes/walletRoutes.js.map +1 -0
- package/dist/backend/backend/services/chainlinkService.js +48 -0
- package/dist/backend/backend/services/chainlinkService.js.map +1 -0
- package/dist/backend/backend/services/contractRegistryService.js +138 -0
- package/dist/backend/backend/services/contractRegistryService.js.map +1 -0
- package/dist/backend/backend/services/devToolsService.js +213 -0
- package/dist/backend/backend/services/devToolsService.js.map +1 -0
- package/dist/backend/backend/services/diagnosticsService.js +286 -0
- package/dist/backend/backend/services/diagnosticsService.js.map +1 -0
- package/dist/backend/backend/services/etherscanService.js +125 -0
- package/dist/backend/backend/services/etherscanService.js.map +1 -0
- package/dist/backend/backend/services/historyService.js +75 -0
- package/dist/backend/backend/services/historyService.js.map +1 -0
- package/dist/backend/backend/services/keyringAccessor.js +40 -0
- package/dist/backend/backend/services/keyringAccessor.js.map +1 -0
- package/dist/backend/backend/services/licenseService.js +130 -0
- package/dist/backend/backend/services/licenseService.js.map +1 -0
- package/dist/backend/backend/services/onchain/abiRegistry.js +47 -0
- package/dist/backend/backend/services/onchain/abiRegistry.js.map +1 -0
- package/dist/backend/backend/services/onchain/chainlinkClient.js +43 -0
- package/dist/backend/backend/services/onchain/chainlinkClient.js.map +1 -0
- package/dist/backend/backend/services/onchain/errors.js +13 -0
- package/dist/backend/backend/services/onchain/errors.js.map +1 -0
- package/dist/backend/backend/services/onchain/etherscanClient.js +82 -0
- package/dist/backend/backend/services/onchain/etherscanClient.js.map +1 -0
- package/dist/backend/backend/services/onchain/index.js +79 -0
- package/dist/backend/backend/services/onchain/index.js.map +1 -0
- package/dist/backend/backend/services/onchain/tenderlyRpcClient.js +60 -0
- package/dist/backend/backend/services/onchain/tenderlyRpcClient.js.map +1 -0
- package/dist/backend/backend/services/onchain/types.js +14 -0
- package/dist/backend/backend/services/onchain/types.js.map +1 -0
- package/dist/backend/backend/services/onchainAutomationService.js +316 -0
- package/dist/backend/backend/services/onchainAutomationService.js.map +1 -0
- package/dist/backend/backend/services/robinhood/auth.js +26 -0
- package/dist/backend/backend/services/robinhood/auth.js.map +1 -0
- package/dist/backend/backend/services/robinhood/client.js +73 -0
- package/dist/backend/backend/services/robinhood/client.js.map +1 -0
- package/dist/backend/backend/services/robinhood/integrationService.js +119 -0
- package/dist/backend/backend/services/robinhood/integrationService.js.map +1 -0
- package/dist/backend/backend/services/robinhood/provider.js +17 -0
- package/dist/backend/backend/services/robinhood/provider.js.map +1 -0
- package/dist/backend/backend/services/robinhood/unofficialClient.js +61 -0
- package/dist/backend/backend/services/robinhood/unofficialClient.js.map +1 -0
- package/dist/backend/backend/services/rpcService.js +48 -0
- package/dist/backend/backend/services/rpcService.js.map +1 -0
- package/dist/backend/backend/services/runtimeTelemetryService.js +96 -0
- package/dist/backend/backend/services/runtimeTelemetryService.js.map +1 -0
- package/dist/backend/backend/services/safeConfigRepository.js +147 -0
- package/dist/backend/backend/services/safeConfigRepository.js.map +1 -0
- package/dist/backend/backend/services/safeService.js +527 -0
- package/dist/backend/backend/services/safeService.js.map +1 -0
- package/dist/backend/backend/services/sandboxService.js +135 -0
- package/dist/backend/backend/services/sandboxService.js.map +1 -0
- package/dist/backend/backend/services/secureSettingsService.js +50 -0
- package/dist/backend/backend/services/secureSettingsService.js.map +1 -0
- package/dist/backend/backend/services/transactionHoldService.js +184 -0
- package/dist/backend/backend/services/transactionHoldService.js.map +1 -0
- package/dist/backend/backend/services/vanityService.js +235 -0
- package/dist/backend/backend/services/vanityService.js.map +1 -0
- package/dist/backend/backend/services/walletService.js +202 -0
- package/dist/backend/backend/services/walletService.js.map +1 -0
- package/dist/backend/backend/services/walletStore.js +132 -0
- package/dist/backend/backend/services/walletStore.js.map +1 -0
- package/dist/backend/backend/utils/abiResolver.js +182 -0
- package/dist/backend/backend/utils/abiResolver.js.map +1 -0
- package/dist/backend/backend/utils/http.js +12 -0
- package/dist/backend/backend/utils/http.js.map +1 -0
- package/dist/backend/backend/utils/secretsResolver.js +137 -0
- package/dist/backend/backend/utils/secretsResolver.js.map +1 -0
- package/dist/backend/backend/utils/signer.js +15 -0
- package/dist/backend/backend/utils/signer.js.map +1 -0
- package/dist/backend/backend/workers/vanityWorker.js +63 -0
- package/dist/backend/backend/workers/vanityWorker.js.map +1 -0
- package/dist/backend/cli/gnoman.js +387 -0
- package/dist/backend/cli/gnoman.js.map +1 -0
- package/dist/backend/modules/sandbox/abiLoader.js +78 -0
- package/dist/backend/modules/sandbox/abiLoader.js.map +1 -0
- package/dist/backend/modules/sandbox/contractSimulator.js +205 -0
- package/dist/backend/modules/sandbox/contractSimulator.js.map +1 -0
- package/dist/backend/modules/sandbox/formBuilder.js +14 -0
- package/dist/backend/modules/sandbox/formBuilder.js.map +1 -0
- package/dist/backend/modules/sandbox/index.js +24 -0
- package/dist/backend/modules/sandbox/index.js.map +1 -0
- package/dist/backend/modules/sandbox/localFork.js +103 -0
- package/dist/backend/modules/sandbox/localFork.js.map +1 -0
- package/dist/backend/modules/sandbox/sandboxManager.js +130 -0
- package/dist/backend/modules/sandbox/sandboxManager.js.map +1 -0
- package/dist/backend/modules/sandbox/types.js +3 -0
- package/dist/backend/modules/sandbox/types.js.map +1 -0
- package/dist/backend/src/core/backends/fileBackend.js +136 -0
- package/dist/backend/src/core/backends/fileBackend.js.map +1 -0
- package/dist/backend/src/core/backends/memoryBackend.js +26 -0
- package/dist/backend/src/core/backends/memoryBackend.js.map +1 -0
- package/dist/backend/src/core/backends/systemBackend.js +86 -0
- package/dist/backend/src/core/backends/systemBackend.js.map +1 -0
- package/dist/backend/src/core/backends/types.js +12 -0
- package/dist/backend/src/core/backends/types.js.map +1 -0
- package/dist/backend/src/core/keyringManager.js +178 -0
- package/dist/backend/src/core/keyringManager.js.map +1 -0
- package/dist/backend/src/utils/abiResolver.js +180 -0
- package/dist/backend/src/utils/abiResolver.js.map +1 -0
- package/dist/backend/src/utils/runtimeObservability.js +78 -0
- package/dist/backend/src/utils/runtimeObservability.js.map +1 -0
- package/dist/backend/src/utils/secretsResolver.js +138 -0
- package/dist/backend/src/utils/secretsResolver.js.map +1 -0
- package/dist/cli/backend/services/diagnosticsService.js +286 -0
- package/dist/cli/backend/services/diagnosticsService.js.map +1 -0
- package/dist/cli/backend/services/keyringAccessor.js +40 -0
- package/dist/cli/backend/services/keyringAccessor.js.map +1 -0
- package/dist/cli/backend/services/rpcService.js +48 -0
- package/dist/cli/backend/services/rpcService.js.map +1 -0
- package/dist/cli/backend/services/runtimeTelemetryService.js +96 -0
- package/dist/cli/backend/services/runtimeTelemetryService.js.map +1 -0
- package/dist/cli/backend/services/walletService.js +202 -0
- package/dist/cli/backend/services/walletService.js.map +1 -0
- package/dist/cli/backend/services/walletStore.js +132 -0
- package/dist/cli/backend/services/walletStore.js.map +1 -0
- package/dist/cli/backend/utils/http.js +12 -0
- package/dist/cli/backend/utils/http.js.map +1 -0
- package/dist/cli/backend/utils/secretsResolver.js +137 -0
- package/dist/cli/backend/utils/secretsResolver.js.map +1 -0
- package/dist/cli/cli/gnoman.js +387 -0
- package/dist/cli/cli/gnoman.js.map +1 -0
- package/dist/cli/src/core/backends/fileBackend.js +136 -0
- package/dist/cli/src/core/backends/fileBackend.js.map +1 -0
- package/dist/cli/src/core/backends/memoryBackend.js +26 -0
- package/dist/cli/src/core/backends/memoryBackend.js.map +1 -0
- package/dist/cli/src/core/backends/systemBackend.js +86 -0
- package/dist/cli/src/core/backends/systemBackend.js.map +1 -0
- package/dist/cli/src/core/backends/types.js +12 -0
- package/dist/cli/src/core/backends/types.js.map +1 -0
- package/dist/cli/src/core/keyringManager.js +178 -0
- package/dist/cli/src/core/keyringManager.js.map +1 -0
- package/dist/cli/src/utils/abiResolver.js +180 -0
- package/dist/cli/src/utils/abiResolver.js.map +1 -0
- package/dist/cli/src/utils/runtimeObservability.js +78 -0
- package/dist/cli/src/utils/runtimeObservability.js.map +1 -0
- package/dist/cli/src/utils/secretsResolver.js +138 -0
- package/dist/cli/src/utils/secretsResolver.js.map +1 -0
- package/dist/main/backend/services/keyringAccessor.js +40 -0
- package/dist/main/backend/services/keyringAccessor.js.map +1 -0
- package/dist/main/backend/utils/http.js +12 -0
- package/dist/main/backend/utils/http.js.map +1 -0
- package/dist/main/main/ipcHandlers/index.js +26 -0
- package/dist/main/main/ipcHandlers/index.js.map +1 -0
- package/dist/main/main/keyring/keyringmanager.js +101 -0
- package/dist/main/main/keyring/keyringmanager.js.map +1 -0
- package/dist/main/main/main.js +224 -0
- package/dist/main/main/main.js.map +1 -0
- package/dist/main/main/preload/index.js +19 -0
- package/dist/main/main/preload/index.js.map +1 -0
- package/dist/main/main/preload/licenseBridge.js +105 -0
- package/dist/main/main/preload/licenseBridge.js.map +1 -0
- package/dist/main/src/core/backends/fileBackend.js +136 -0
- package/dist/main/src/core/backends/fileBackend.js.map +1 -0
- package/dist/main/src/core/backends/memoryBackend.js +26 -0
- package/dist/main/src/core/backends/memoryBackend.js.map +1 -0
- package/dist/main/src/core/backends/systemBackend.js +86 -0
- package/dist/main/src/core/backends/systemBackend.js.map +1 -0
- package/dist/main/src/core/backends/types.js +12 -0
- package/dist/main/src/core/backends/types.js.map +1 -0
- package/dist/main/src/core/keyringManager.js +178 -0
- package/dist/main/src/core/keyringManager.js.map +1 -0
- package/dist/main/src/utils/abiResolver.js +180 -0
- package/dist/main/src/utils/abiResolver.js.map +1 -0
- package/dist/main/src/utils/runtimeObservability.js +78 -0
- package/dist/main/src/utils/runtimeObservability.js.map +1 -0
- package/dist/main/src/utils/secretsResolver.js +138 -0
- package/dist/main/src/utils/secretsResolver.js.map +1 -0
- package/docs/development-guide.md +203 -0
- package/docs/etherscan-chainlink-integration.md +44 -0
- package/docs/gnoman-20-user-manual-STANDARD-PRINT-READY.pdf +0 -0
- package/docs/gnoman-20-user-manual-STANDARD.pdf +0 -0
- package/docs/license-dev-guide.md +106 -0
- package/docs/robinhood-integration.md +30 -0
- package/docs/system-audit-gpt-guide.md +208 -0
- package/docs/system-robustness-audit.md +50 -0
- package/docs/user-guide.md +73 -0
- package/docs/wiki/development-guide.md +203 -0
- package/docs/wiki/license-dev-guide.md +106 -0
- package/docs/wiki/user-guide.md +73 -0
- package/eslint.config.js +85 -0
- package/gnoman2.0/.eslintrc.cjs +24 -0
- package/gnoman2.0/.prettierrc.json +6 -0
- package/gnoman2.0/CODex_TASKS.md +124 -0
- package/gnoman2.0/LICENSE.md +164 -0
- package/gnoman2.0/README.md +95 -0
- package/gnoman2.0/assets/GnoLogo.jpg +0 -0
- package/gnoman2.0/assets/self.png +0 -0
- package/gnoman2.0/backend/controllers/contractController.ts +49 -0
- package/gnoman2.0/backend/controllers/devToolsController.ts +76 -0
- package/gnoman2.0/backend/controllers/etherscanController.ts +59 -0
- package/gnoman2.0/backend/controllers/historyController.ts +7 -0
- package/gnoman2.0/backend/controllers/keyringController.ts +134 -0
- package/gnoman2.0/backend/controllers/robinhoodController.ts +80 -0
- package/gnoman2.0/backend/controllers/safeController.ts +167 -0
- package/gnoman2.0/backend/controllers/sandboxController.ts +63 -0
- package/gnoman2.0/backend/controllers/settingsController.ts +38 -0
- package/gnoman2.0/backend/controllers/walletController.ts +151 -0
- package/gnoman2.0/backend/index.ts +133 -0
- package/gnoman2.0/backend/licenses/license_public.pem +3 -0
- package/gnoman2.0/backend/licenses/verify_license.py +43 -0
- package/gnoman2.0/backend/routes/contractRoutes.ts +11 -0
- package/gnoman2.0/backend/routes/devToolsRoutes.ts +11 -0
- package/gnoman2.0/backend/routes/etherscanRoutes.ts +11 -0
- package/gnoman2.0/backend/routes/historyRoutes.ts +8 -0
- package/gnoman2.0/backend/routes/keyringRoutes.ts +25 -0
- package/gnoman2.0/backend/routes/licenseRoutes.ts +35 -0
- package/gnoman2.0/backend/routes/robinhoodRoutes.ts +22 -0
- package/gnoman2.0/backend/routes/runtimeRoutes.ts +29 -0
- package/gnoman2.0/backend/routes/safeRoutes.ts +28 -0
- package/gnoman2.0/backend/routes/sandboxRoutes.ts +17 -0
- package/gnoman2.0/backend/routes/settingsRoutes.ts +14 -0
- package/gnoman2.0/backend/routes/walletRoutes.ts +21 -0
- package/gnoman2.0/backend/services/chainlinkService.ts +65 -0
- package/gnoman2.0/backend/services/contractRegistryService.ts +205 -0
- package/gnoman2.0/backend/services/devToolsService.ts +251 -0
- package/gnoman2.0/backend/services/diagnosticsService.ts +350 -0
- package/gnoman2.0/backend/services/etherscanService.ts +152 -0
- package/gnoman2.0/backend/services/historyService.ts +89 -0
- package/gnoman2.0/backend/services/keyringAccessor.ts +4 -0
- package/gnoman2.0/backend/services/licenseService.ts +163 -0
- package/gnoman2.0/backend/services/onchain/abiRegistry.ts +57 -0
- package/gnoman2.0/backend/services/onchain/chainlinkClient.ts +56 -0
- package/gnoman2.0/backend/services/onchain/errors.ts +16 -0
- package/gnoman2.0/backend/services/onchain/etherscanClient.ts +94 -0
- package/gnoman2.0/backend/services/onchain/index.ts +76 -0
- package/gnoman2.0/backend/services/onchain/tenderlyRpcClient.ts +74 -0
- package/gnoman2.0/backend/services/onchain/types.ts +33 -0
- package/gnoman2.0/backend/services/onchainAutomationService.ts +424 -0
- package/gnoman2.0/backend/services/robinhood/auth.ts +42 -0
- package/gnoman2.0/backend/services/robinhood/client.ts +123 -0
- package/gnoman2.0/backend/services/robinhood/integrationService.ts +140 -0
- package/gnoman2.0/backend/services/robinhood/provider.ts +22 -0
- package/gnoman2.0/backend/services/robinhood/unofficialClient.ts +66 -0
- package/gnoman2.0/backend/services/rpcService.ts +44 -0
- package/gnoman2.0/backend/services/runtimeTelemetryService.ts +158 -0
- package/gnoman2.0/backend/services/safeConfigRepository.ts +205 -0
- package/gnoman2.0/backend/services/safeService.ts +588 -0
- package/gnoman2.0/backend/services/sandboxService.ts +157 -0
- package/gnoman2.0/backend/services/secureSettingsService.ts +45 -0
- package/gnoman2.0/backend/services/transactionHoldService.ts +223 -0
- package/gnoman2.0/backend/services/vanityService.ts +293 -0
- package/gnoman2.0/backend/services/walletService.ts +290 -0
- package/gnoman2.0/backend/services/walletStore.ts +179 -0
- package/gnoman2.0/backend/types/express-async-handler.d.ts +13 -0
- package/gnoman2.0/backend/types/keyring.d.ts +19 -0
- package/gnoman2.0/backend/utils/abiResolver.ts +208 -0
- package/gnoman2.0/backend/utils/http.ts +6 -0
- package/gnoman2.0/backend/utils/secretsResolver.ts +150 -0
- package/gnoman2.0/backend/utils/signer.ts +11 -0
- package/gnoman2.0/backend/workers/vanityWorker.ts +76 -0
- package/gnoman2.0/capacitor.config.ts +13 -0
- package/gnoman2.0/cli/gnoman.ts +424 -0
- package/gnoman2.0/contracts/OracleConsumer.sol +20 -0
- package/gnoman2.0/contracts/PriceFeedConsumer.sol +22 -0
- package/gnoman2.0/docs/development-guide.md +203 -0
- package/gnoman2.0/docs/etherscan-chainlink-integration.md +44 -0
- package/gnoman2.0/docs/gnoman-20-user-manual-STANDARD-PRINT-READY.pdf +0 -0
- package/gnoman2.0/docs/gnoman-20-user-manual-STANDARD.pdf +0 -0
- package/gnoman2.0/docs/license-dev-guide.md +106 -0
- package/gnoman2.0/docs/robinhood-integration.md +30 -0
- package/gnoman2.0/docs/system-audit-gpt-guide.md +208 -0
- package/gnoman2.0/docs/system-robustness-audit.md +50 -0
- package/gnoman2.0/docs/user-guide.md +73 -0
- package/gnoman2.0/docs/wiki/development-guide.md +203 -0
- package/gnoman2.0/docs/wiki/license-dev-guide.md +106 -0
- package/gnoman2.0/docs/wiki/user-guide.md +73 -0
- package/gnoman2.0/eslint.config.js +85 -0
- package/gnoman2.0/gnomon/__init__.py +0 -0
- package/gnoman2.0/gnomon/api/__init__.py +0 -0
- package/gnoman2.0/gnomon/api/etherscan_tracker.py +72 -0
- package/gnoman2.0/gnomon/core/__init__.py +0 -0
- package/gnoman2.0/gnomon/core/safe_manager.py +111 -0
- package/gnoman2.0/gnomon/tests/test_abi_resolver.py +181 -0
- package/gnoman2.0/gnomon/tests/test_safe_persistence_and_etherscan.py +97 -0
- package/gnoman2.0/gnomon/utils/__init__.py +5 -0
- package/gnoman2.0/gnomon/utils/abi_resolver.py +255 -0
- package/gnoman2.0/ios/ExportOptions.plist +16 -0
- package/gnoman2.0/ios/README.md +33 -0
- package/gnoman2.0/jest.config.ts +18 -0
- package/gnoman2.0/keyring/__init__.py +17 -0
- package/gnoman2.0/licensingServer/package.json +23 -0
- package/gnoman2.0/licensingServer/src/config/keys.ts +84 -0
- package/gnoman2.0/licensingServer/src/index.ts +30 -0
- package/gnoman2.0/licensingServer/src/lib/canonicalize.ts +5 -0
- package/gnoman2.0/licensingServer/src/lib/crypto.ts +25 -0
- package/gnoman2.0/licensingServer/src/lib/validate.ts +62 -0
- package/gnoman2.0/licensingServer/src/middleware/auth.ts +20 -0
- package/gnoman2.0/licensingServer/src/routes/licenses.ts +110 -0
- package/gnoman2.0/licensingServer/tsconfig.json +12 -0
- package/gnoman2.0/main/ipcHandlers/index.ts +23 -0
- package/gnoman2.0/main/keyring/keyringmanager.ts +154 -0
- package/gnoman2.0/main/main.ts +234 -0
- package/gnoman2.0/main/preload/index.ts +31 -0
- package/gnoman2.0/main/preload/licenseBridge.ts +73 -0
- package/gnoman2.0/modules/sandbox/abiLoader.ts +78 -0
- package/gnoman2.0/modules/sandbox/contractSimulator.ts +241 -0
- package/gnoman2.0/modules/sandbox/formBuilder.ts +16 -0
- package/gnoman2.0/modules/sandbox/index.ts +6 -0
- package/gnoman2.0/modules/sandbox/localFork.ts +129 -0
- package/gnoman2.0/modules/sandbox/safe.abi.json +82 -0
- package/gnoman2.0/modules/sandbox/sandboxManager.ts +154 -0
- package/gnoman2.0/modules/sandbox/types.ts +84 -0
- package/gnoman2.0/modules/sandbox/ui/LogViewer.tsx +30 -0
- package/gnoman2.0/modules/sandbox/ui/ParameterForm.tsx +49 -0
- package/gnoman2.0/modules/sandbox/ui/SandboxPanel.tsx +568 -0
- package/gnoman2.0/package-lock.json +10904 -0
- package/gnoman2.0/package.json +82 -0
- package/gnoman2.0/renderer/components/LicenseScreen.tsx +134 -0
- package/gnoman2.0/renderer/index.html +12 -0
- package/gnoman2.0/renderer/package-lock.json +4104 -0
- package/gnoman2.0/renderer/package.json +35 -0
- package/gnoman2.0/renderer/postcss.config.cjs +6 -0
- package/gnoman2.0/renderer/src/App.tsx +229 -0
- package/gnoman2.0/renderer/src/context/KeyringContext.tsx +217 -0
- package/gnoman2.0/renderer/src/context/SafeContext.tsx +49 -0
- package/gnoman2.0/renderer/src/context/ThemeContext.tsx +60 -0
- package/gnoman2.0/renderer/src/context/WalletContext.tsx +50 -0
- package/gnoman2.0/renderer/src/context/main.tsx +18 -0
- package/gnoman2.0/renderer/src/main.tsx +18 -0
- package/gnoman2.0/renderer/src/pages/Contracts.tsx +482 -0
- package/gnoman2.0/renderer/src/pages/Dashboard.tsx +653 -0
- package/gnoman2.0/renderer/src/pages/DeveloperTools.tsx +270 -0
- package/gnoman2.0/renderer/src/pages/History.tsx +149 -0
- package/gnoman2.0/renderer/src/pages/Keyring.tsx +449 -0
- package/gnoman2.0/renderer/src/pages/Safes.tsx +1089 -0
- package/gnoman2.0/renderer/src/pages/Sandbox.tsx +146 -0
- package/gnoman2.0/renderer/src/pages/Settings.tsx +871 -0
- package/gnoman2.0/renderer/src/pages/Wallets.tsx +752 -0
- package/gnoman2.0/renderer/src/pages/WikiGuide.tsx +75 -0
- package/gnoman2.0/renderer/src/styles.css +32 -0
- package/gnoman2.0/renderer/src/types/gnoman.d.ts +9 -0
- package/gnoman2.0/renderer/src/types/license.ts +8 -0
- package/gnoman2.0/renderer/src/types/safevault.d.ts +17 -0
- package/gnoman2.0/renderer/src/utils/backend.ts +88 -0
- package/gnoman2.0/renderer/tailwind.config.cjs +8 -0
- package/gnoman2.0/renderer/tsconfig.json +13 -0
- package/gnoman2.0/renderer/tsconfig.node.json +9 -0
- package/gnoman2.0/renderer/vite.config.ts +19 -0
- package/gnoman2.0/requests/__init__.py +35 -0
- package/gnoman2.0/scripts/build-ios.sh +30 -0
- package/gnoman2.0/scripts/copyBackendAssets.js +24 -0
- package/gnoman2.0/scripts/copyRenderer.js +87 -0
- package/gnoman2.0/scripts/launchElectron.js +51 -0
- package/gnoman2.0/src/core/backends/fileBackend.ts +154 -0
- package/gnoman2.0/src/core/backends/memoryBackend.ts +27 -0
- package/gnoman2.0/src/core/backends/systemBackend.ts +66 -0
- package/gnoman2.0/src/core/backends/types.ts +17 -0
- package/gnoman2.0/src/core/keyringManager.ts +208 -0
- package/gnoman2.0/src/utils/abiCache/.gitkeep +0 -0
- package/gnoman2.0/src/utils/abiResolver.ts +200 -0
- package/gnoman2.0/src/utils/runtimeObservability.ts +110 -0
- package/gnoman2.0/src/utils/secretsResolver.ts +144 -0
- package/gnoman2.0/tests/chainlinkService.test.ts +32 -0
- package/gnoman2.0/tests/diagnosticsService.test.ts +68 -0
- package/gnoman2.0/tests/etherscanController.test.ts +99 -0
- package/gnoman2.0/tests/etherscanService.test.ts +116 -0
- package/gnoman2.0/tests/keyringManager.test.ts +135 -0
- package/gnoman2.0/tests/onchainToolkit.test.ts +71 -0
- package/gnoman2.0/tests/robinhoodClient.test.ts +54 -0
- package/gnoman2.0/tests/robinhoodController.test.ts +81 -0
- package/gnoman2.0/tests/robinhoodIntegrationService.test.ts +50 -0
- package/gnoman2.0/tests/safeServicePersistence.test.ts +81 -0
- package/gnoman2.0/tests/test_contract_sandbox/sandbox.test.js +407 -0
- package/gnoman2.0/tests/walletController.test.ts +57 -0
- package/gnoman2.0/tsconfig.backend.json +7 -0
- package/gnoman2.0/tsconfig.cli.json +7 -0
- package/gnoman2.0/tsconfig.json +18 -0
- package/gnoman2.0/tsconfig.main.json +7 -0
- package/gnomon/__init__.py +0 -0
- package/gnomon/__pycache__/__init__.cpython-310.pyc +0 -0
- package/gnomon/api/__init__.py +0 -0
- package/gnomon/api/__pycache__/__init__.cpython-310.pyc +0 -0
- package/gnomon/api/__pycache__/etherscan_tracker.cpython-310.pyc +0 -0
- package/gnomon/api/etherscan_tracker.py +72 -0
- package/gnomon/core/__init__.py +0 -0
- package/gnomon/core/safe_manager.py +111 -0
- package/gnomon/tests/__pycache__/test_safe_persistence_and_etherscan.cpython-310-pytest-8.3.3.pyc +0 -0
- package/gnomon/tests/test_abi_resolver.py +181 -0
- package/gnomon/tests/test_safe_persistence_and_etherscan.py +97 -0
- package/gnomon/utils/__init__.py +5 -0
- package/gnomon/utils/abi_resolver.py +255 -0
- package/ios/ExportOptions.plist +16 -0
- package/ios/README.md +33 -0
- package/jest.config.ts +18 -0
- package/keyring/__init__.py +17 -0
- package/launcher.sh +57 -0
- package/license.env +2 -0
- package/licensingServer/package.json +23 -0
- package/licensingServer/src/config/keys.ts +84 -0
- package/licensingServer/src/index.ts +30 -0
- package/licensingServer/src/lib/canonicalize.ts +5 -0
- package/licensingServer/src/lib/crypto.ts +25 -0
- package/licensingServer/src/lib/validate.ts +62 -0
- package/licensingServer/src/middleware/auth.ts +20 -0
- package/licensingServer/src/routes/licenses.ts +110 -0
- package/licensingServer/tsconfig.json +12 -0
- package/main/ipcHandlers/index.ts +23 -0
- package/main/keyring/keyringmanager.ts +154 -0
- package/main/main.ts +234 -0
- package/main/preload/index.ts +31 -0
- package/main/preload/licenseBridge.ts +73 -0
- package/modules/sandbox/abiLoader.ts +78 -0
- package/modules/sandbox/contractSimulator.ts +241 -0
- package/modules/sandbox/formBuilder.ts +16 -0
- package/modules/sandbox/index.ts +6 -0
- package/modules/sandbox/localFork.ts +129 -0
- package/modules/sandbox/safe.abi.json +82 -0
- package/modules/sandbox/sandboxManager.ts +154 -0
- package/modules/sandbox/types.ts +84 -0
- package/modules/sandbox/ui/LogViewer.tsx +30 -0
- package/modules/sandbox/ui/ParameterForm.tsx +49 -0
- package/modules/sandbox/ui/SandboxPanel.tsx +568 -0
- package/package.json +82 -0
- package/renderer/components/LicenseScreen.tsx +134 -0
- package/renderer/index.html +12 -0
- package/renderer/package-lock.json +4104 -0
- package/renderer/package.json +35 -0
- package/renderer/postcss.config.cjs +6 -0
- package/renderer/src/App.tsx +229 -0
- package/renderer/src/context/KeyringContext.tsx +217 -0
- package/renderer/src/context/SafeContext.tsx +49 -0
- package/renderer/src/context/ThemeContext.tsx +60 -0
- package/renderer/src/context/WalletContext.tsx +50 -0
- package/renderer/src/context/main.tsx +18 -0
- package/renderer/src/main.tsx +18 -0
- package/renderer/src/pages/Contracts.tsx +482 -0
- package/renderer/src/pages/Dashboard.tsx +653 -0
- package/renderer/src/pages/DeveloperTools.tsx +270 -0
- package/renderer/src/pages/History.tsx +149 -0
- package/renderer/src/pages/Keyring.tsx +449 -0
- package/renderer/src/pages/Safes.tsx +1089 -0
- package/renderer/src/pages/Sandbox.tsx +146 -0
- package/renderer/src/pages/Settings.tsx +871 -0
- package/renderer/src/pages/Wallets.tsx +752 -0
- package/renderer/src/pages/WikiGuide.tsx +75 -0
- package/renderer/src/styles.css +32 -0
- package/renderer/src/types/gnoman.d.ts +9 -0
- package/renderer/src/types/license.ts +8 -0
- package/renderer/src/types/safevault.d.ts +17 -0
- package/renderer/src/utils/backend.ts +88 -0
- package/renderer/tailwind.config.cjs +8 -0
- package/renderer/tsconfig.json +13 -0
- package/renderer/tsconfig.node.json +9 -0
- package/renderer/vite.config.ts +19 -0
- package/requests/__init__.py +35 -0
- package/requests/__pycache__/__init__.cpython-310.pyc +0 -0
- package/scripts/build-ios.sh +30 -0
- package/scripts/copyBackendAssets.js +24 -0
- package/scripts/copyRenderer.js +87 -0
- package/scripts/deployBackend.sh +24 -0
- package/scripts/launchElectron.js +51 -0
- package/src/core/backends/fileBackend.ts +154 -0
- package/src/core/backends/memoryBackend.ts +27 -0
- package/src/core/backends/systemBackend.ts +66 -0
- package/src/core/backends/types.ts +17 -0
- package/src/core/keyringManager.ts +208 -0
- package/src/utils/abiCache/.gitkeep +0 -0
- package/src/utils/abiResolver.ts +200 -0
- package/src/utils/runtimeObservability.ts +110 -0
- package/src/utils/secretsResolver.ts +144 -0
- package/tests/chainlinkService.test.ts +32 -0
- package/tests/diagnosticsService.test.ts +68 -0
- package/tests/etherscanController.test.ts +99 -0
- package/tests/etherscanService.test.ts +116 -0
- package/tests/keyringManager.test.ts +135 -0
- package/tests/onchainToolkit.test.ts +71 -0
- package/tests/robinhoodClient.test.ts +54 -0
- package/tests/robinhoodController.test.ts +81 -0
- package/tests/robinhoodIntegrationService.test.ts +50 -0
- package/tests/safeServicePersistence.test.ts +81 -0
- package/tests/test_contract_sandbox/sandbox.test.js +407 -0
- package/tests/walletController.test.ts +57 -0
- package/touch +14 -0
- package/tsconfig.backend.json +7 -0
- package/tsconfig.cli.json +7 -0
- package/tsconfig.json +18 -0
- package/tsconfig.main.json +7 -0
- package/webhook-shim.js +50 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
|
+
import process from 'process';
|
|
6
|
+
import keyringManager from '../src/core/keyringManager';
|
|
7
|
+
import type { KeyringBackendName } from '../src/core/backends/types';
|
|
8
|
+
import {
|
|
9
|
+
exportWallet,
|
|
10
|
+
importWalletFromEncryptedJson,
|
|
11
|
+
listWalletMetadata
|
|
12
|
+
} from '../backend/services/walletService';
|
|
13
|
+
import {
|
|
14
|
+
runSystemDiagnostics,
|
|
15
|
+
type DiagnosticReport,
|
|
16
|
+
type DiagnosticCheck
|
|
17
|
+
} from '../backend/services/diagnosticsService';
|
|
18
|
+
|
|
19
|
+
const AVAILABLE_BACKENDS: KeyringBackendName[] = ['system', 'file', 'memory'];
|
|
20
|
+
|
|
21
|
+
type CommandHandler = (args: string[]) => Promise<void>;
|
|
22
|
+
|
|
23
|
+
const maskSecret = (value: string | null) => {
|
|
24
|
+
if (!value) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (value.length <= 4) {
|
|
28
|
+
return '*'.repeat(value.length);
|
|
29
|
+
}
|
|
30
|
+
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const takeOption = (args: string[], option: string) => {
|
|
34
|
+
const index = args.indexOf(option);
|
|
35
|
+
if (index === -1) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const value = args[index + 1];
|
|
39
|
+
if (typeof value !== 'string') {
|
|
40
|
+
throw new Error(`Option ${option} requires a value.`);
|
|
41
|
+
}
|
|
42
|
+
args.splice(index, 2);
|
|
43
|
+
return value;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const takeFlag = (args: string[], option: string) => {
|
|
47
|
+
const index = args.indexOf(option);
|
|
48
|
+
if (index === -1) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
args.splice(index, 1);
|
|
52
|
+
return true;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const ensureBackend = async (backend?: string) => {
|
|
56
|
+
if (!backend) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!AVAILABLE_BACKENDS.includes(backend as KeyringBackendName)) {
|
|
60
|
+
throw new Error(`Unsupported backend '${backend}'. Use one of: ${AVAILABLE_BACKENDS.join(', ')}`);
|
|
61
|
+
}
|
|
62
|
+
await keyringManager.switchBackend(backend as KeyringBackendName);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const ensureFileOutput = async (filePath: string, data: string) => {
|
|
66
|
+
const directory = path.dirname(filePath);
|
|
67
|
+
await fs.mkdir(directory, { recursive: true, mode: 0o700 });
|
|
68
|
+
await fs.writeFile(filePath, data, 'utf8');
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const readSource = async (source: string) => {
|
|
72
|
+
if (source === '-' || source === '/dev/stdin') {
|
|
73
|
+
return new Promise<string>((resolve, reject) => {
|
|
74
|
+
let buffer = '';
|
|
75
|
+
process.stdin.setEncoding('utf8');
|
|
76
|
+
process.stdin.on('data', (chunk) => {
|
|
77
|
+
buffer += chunk.toString();
|
|
78
|
+
});
|
|
79
|
+
process.stdin.on('end', () => resolve(buffer));
|
|
80
|
+
process.stdin.on('error', (error) => reject(error));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return fs.readFile(source, 'utf8');
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const parseEnvFile = (content: string) => {
|
|
87
|
+
const records: Record<string, string> = {};
|
|
88
|
+
const lines = content.split(/\r?\n/);
|
|
89
|
+
for (const raw of lines) {
|
|
90
|
+
const line = raw.trim();
|
|
91
|
+
if (line.length === 0 || line.startsWith('#')) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
95
|
+
if (!match) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const [, key, remainder] = match;
|
|
99
|
+
let value = remainder.trim();
|
|
100
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
101
|
+
value = value.slice(1, -1).replace(/\\"/g, '"');
|
|
102
|
+
}
|
|
103
|
+
records[key] = value;
|
|
104
|
+
}
|
|
105
|
+
return records;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const serializeEnv = (records: Record<string, string>) =>
|
|
109
|
+
Object.entries(records)
|
|
110
|
+
.map(([key, value]) => `${key}="${value.replace(/"/g, '\\"')}"`)
|
|
111
|
+
.join('\n');
|
|
112
|
+
|
|
113
|
+
const encryptWithGpg = async (data: string, recipient: string, output: string) => {
|
|
114
|
+
return new Promise<void>((resolve, reject) => {
|
|
115
|
+
const child = spawn('gpg', ['--batch', '--yes', '--encrypt', '--recipient', recipient, '--output', output], {
|
|
116
|
+
stdio: ['pipe', 'inherit', 'inherit']
|
|
117
|
+
});
|
|
118
|
+
child.on('error', (error) => reject(error));
|
|
119
|
+
child.on('exit', (code) => {
|
|
120
|
+
if (code === 0) {
|
|
121
|
+
resolve();
|
|
122
|
+
} else {
|
|
123
|
+
reject(new Error(`gpg exited with code ${code}`));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
child.stdin.end(data, 'utf8');
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const keyringHandlers: Record<string, CommandHandler> = {
|
|
131
|
+
async backend(args) {
|
|
132
|
+
const action = args.shift();
|
|
133
|
+
if (!action || action === 'list') {
|
|
134
|
+
await keyringManager.list();
|
|
135
|
+
console.log(`Active backend: ${keyringManager.currentBackend()}`);
|
|
136
|
+
console.log(`Available: ${AVAILABLE_BACKENDS.join(', ')}`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (action === 'switch') {
|
|
140
|
+
const target = args.shift();
|
|
141
|
+
if (!target) {
|
|
142
|
+
throw new Error('Backend name is required.');
|
|
143
|
+
}
|
|
144
|
+
await ensureBackend(target);
|
|
145
|
+
console.log(`Switched to backend: ${keyringManager.currentBackend()}`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`Unsupported backend action '${action}'.`);
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
async list(args) {
|
|
152
|
+
const backend = takeOption(args, '--backend');
|
|
153
|
+
await ensureBackend(backend);
|
|
154
|
+
const secrets = await keyringManager.list();
|
|
155
|
+
if (Object.keys(secrets).length === 0) {
|
|
156
|
+
console.log('No keyring entries found.');
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
for (const [key, value] of Object.entries(secrets)) {
|
|
160
|
+
console.log(`${key}: ${maskSecret(value)}`);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
async set(args) {
|
|
165
|
+
const backend = takeOption(args, '--backend');
|
|
166
|
+
const key = args.shift();
|
|
167
|
+
const value = args.shift();
|
|
168
|
+
if (!key || typeof value !== 'string') {
|
|
169
|
+
throw new Error('Usage: gnoman keyring set <key> <value>');
|
|
170
|
+
}
|
|
171
|
+
await ensureBackend(backend);
|
|
172
|
+
await keyringManager.set(key, value);
|
|
173
|
+
console.log(`Stored secret '${key}'.`);
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
async add(args) {
|
|
177
|
+
await keyringHandlers.set(args);
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
async edit(args) {
|
|
181
|
+
await keyringHandlers.set(args);
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
async get(args) {
|
|
185
|
+
const backend = takeOption(args, '--backend');
|
|
186
|
+
const key = args.shift();
|
|
187
|
+
if (!key) {
|
|
188
|
+
throw new Error('Usage: gnoman keyring get <key>');
|
|
189
|
+
}
|
|
190
|
+
await ensureBackend(backend);
|
|
191
|
+
const value = await keyringManager.get(key);
|
|
192
|
+
if (value === null) {
|
|
193
|
+
console.error('Secret not found.');
|
|
194
|
+
process.exitCode = 1;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
console.log(value);
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
async delete(args) {
|
|
201
|
+
const backend = takeOption(args, '--backend');
|
|
202
|
+
const key = args.shift();
|
|
203
|
+
if (!key) {
|
|
204
|
+
throw new Error('Usage: gnoman keyring delete <key>');
|
|
205
|
+
}
|
|
206
|
+
await ensureBackend(backend);
|
|
207
|
+
await keyringManager.delete(key);
|
|
208
|
+
console.log(`Deleted secret '${key}'.`);
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
async remove(args) {
|
|
212
|
+
await keyringHandlers.delete(args);
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
async export(args) {
|
|
216
|
+
const backend = takeOption(args, '--backend');
|
|
217
|
+
const format = (takeOption(args, '--format') ?? 'json').toLowerCase();
|
|
218
|
+
const output = takeOption(args, '--output');
|
|
219
|
+
const gpgRecipient = takeOption(args, '--gpg');
|
|
220
|
+
await ensureBackend(backend);
|
|
221
|
+
const secrets = await keyringManager.list();
|
|
222
|
+
let payload: string;
|
|
223
|
+
if (format === 'env') {
|
|
224
|
+
payload = `${serializeEnv(secrets)}\n`;
|
|
225
|
+
} else if (format === 'json') {
|
|
226
|
+
payload = `${JSON.stringify(secrets, null, 2)}\n`;
|
|
227
|
+
} else {
|
|
228
|
+
throw new Error(`Unsupported export format '${format}'. Use env or json.`);
|
|
229
|
+
}
|
|
230
|
+
if (gpgRecipient) {
|
|
231
|
+
if (!output) {
|
|
232
|
+
throw new Error('The --output option is required when using --gpg.');
|
|
233
|
+
}
|
|
234
|
+
await encryptWithGpg(payload, gpgRecipient, output);
|
|
235
|
+
console.log(`Exported secrets to ${output} using GPG recipient ${gpgRecipient}.`);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (output) {
|
|
239
|
+
await ensureFileOutput(output, payload);
|
|
240
|
+
console.log(`Exported secrets to ${output}.`);
|
|
241
|
+
} else {
|
|
242
|
+
process.stdout.write(payload);
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
async import(args) {
|
|
247
|
+
const backend = takeOption(args, '--backend');
|
|
248
|
+
const format = (takeOption(args, '--format') ?? 'json').toLowerCase();
|
|
249
|
+
const source = args.shift();
|
|
250
|
+
if (!source) {
|
|
251
|
+
throw new Error('Usage: gnoman keyring import <file> [--format env|json]');
|
|
252
|
+
}
|
|
253
|
+
await ensureBackend(backend);
|
|
254
|
+
const content = await readSource(source);
|
|
255
|
+
let records: Record<string, string>;
|
|
256
|
+
if (format === 'env') {
|
|
257
|
+
records = parseEnvFile(content);
|
|
258
|
+
} else if (format === 'json') {
|
|
259
|
+
const parsed = JSON.parse(content);
|
|
260
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
261
|
+
throw new Error('Invalid JSON payload for keyring import.');
|
|
262
|
+
}
|
|
263
|
+
records = Object.fromEntries(
|
|
264
|
+
Object.entries(parsed).filter(([, value]) => typeof value === 'string') as [string, string][]
|
|
265
|
+
);
|
|
266
|
+
} else {
|
|
267
|
+
throw new Error(`Unsupported import format '${format}'. Use env or json.`);
|
|
268
|
+
}
|
|
269
|
+
for (const [key, value] of Object.entries(records)) {
|
|
270
|
+
await keyringManager.set(key, value);
|
|
271
|
+
}
|
|
272
|
+
console.log(`Imported ${Object.keys(records).length} secrets into backend ${keyringManager.currentBackend()}.`);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const walletHandlers: Record<string, CommandHandler> = {
|
|
277
|
+
async list(_args) {
|
|
278
|
+
const wallets = await listWalletMetadata();
|
|
279
|
+
if (wallets.length === 0) {
|
|
280
|
+
console.log('No wallets stored.');
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
for (const wallet of wallets) {
|
|
284
|
+
console.log(`${wallet.address} (${wallet.alias ?? 'unnamed'})`);
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
async export(args) {
|
|
289
|
+
const address = args.shift();
|
|
290
|
+
const password = takeOption(args, '--password');
|
|
291
|
+
const output = takeOption(args, '--output');
|
|
292
|
+
if (!address || !password) {
|
|
293
|
+
throw new Error('Usage: gnoman wallets export <address> --password <password> [--output <file>]');
|
|
294
|
+
}
|
|
295
|
+
const keystore = await exportWallet(address, password);
|
|
296
|
+
if (output) {
|
|
297
|
+
await ensureFileOutput(output, `${keystore}\n`);
|
|
298
|
+
console.log(`Exported wallet ${address} to ${output}.`);
|
|
299
|
+
} else {
|
|
300
|
+
process.stdout.write(`${keystore}\n`);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
async import(args) {
|
|
305
|
+
const source = args.shift();
|
|
306
|
+
const password = takeOption(args, '--password');
|
|
307
|
+
const alias = takeOption(args, '--alias');
|
|
308
|
+
const hidden = takeFlag(args, '--hidden');
|
|
309
|
+
if (!source || !password) {
|
|
310
|
+
throw new Error('Usage: gnoman wallets import <file> --password <password> [--alias <alias>] [--hidden]');
|
|
311
|
+
}
|
|
312
|
+
const json = await readSource(source);
|
|
313
|
+
const wallet = await importWalletFromEncryptedJson({ json, password, alias, hidden });
|
|
314
|
+
console.log(`Imported wallet ${wallet.address} (${wallet.alias ?? 'unnamed'}).`);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const printDiagnosticReport = (report: DiagnosticReport, { verbose = false } = {}) => {
|
|
319
|
+
const icon: Record<DiagnosticCheck['status'], string> = {
|
|
320
|
+
ok: '✅',
|
|
321
|
+
warn: '⚠️',
|
|
322
|
+
error: '❌'
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
console.log('GNOMAN system diagnostics');
|
|
326
|
+
console.log(`Generated: ${report.generatedAt}`);
|
|
327
|
+
console.log(
|
|
328
|
+
`Environment: ${report.environment.platform}/${report.environment.arch} · Node ${report.environment.nodeVersion} (recommended ${report.environment.recommendedNodeVersion})`
|
|
329
|
+
);
|
|
330
|
+
console.log(
|
|
331
|
+
`Summary: ${report.summary.ok} ok, ${report.summary.warn} warn, ${report.summary.error} error`
|
|
332
|
+
);
|
|
333
|
+
console.log('');
|
|
334
|
+
|
|
335
|
+
for (const check of report.checks) {
|
|
336
|
+
console.log(`${icon[check.status]} ${check.label}`);
|
|
337
|
+
if (check.detail) {
|
|
338
|
+
console.log(` ${check.detail}`);
|
|
339
|
+
}
|
|
340
|
+
if (check.suggestion) {
|
|
341
|
+
console.log(` Suggestion: ${check.suggestion}`);
|
|
342
|
+
}
|
|
343
|
+
if (verbose && check.metadata) {
|
|
344
|
+
console.log(` Metadata: ${JSON.stringify(check.metadata)}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const diagnosticsHandlers: Record<string, CommandHandler> = {
|
|
350
|
+
async run(args) {
|
|
351
|
+
const jsonOutput = takeFlag(args, '--json');
|
|
352
|
+
const autoFix = takeFlag(args, '--fix');
|
|
353
|
+
const verbose = takeFlag(args, '--verbose');
|
|
354
|
+
const skipGpg = takeFlag(args, '--skip-gpg');
|
|
355
|
+
const report = await runSystemDiagnostics({ autoFix, skipGpg });
|
|
356
|
+
if (jsonOutput) {
|
|
357
|
+
console.log(JSON.stringify(report, null, 2));
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
printDiagnosticReport(report, { verbose });
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
async list(args) {
|
|
364
|
+
await diagnosticsHandlers.run(args);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const printHelp = () => {
|
|
369
|
+
console.log(`GNOMAN CLI
|
|
370
|
+
|
|
371
|
+
Usage:
|
|
372
|
+
gnoman keyring <command> [...args]
|
|
373
|
+
gnoman wallets <command> [...args]
|
|
374
|
+
gnoman diagnostics <command> [...args]
|
|
375
|
+
|
|
376
|
+
Keyring commands:
|
|
377
|
+
keyring backend list
|
|
378
|
+
keyring backend switch <system|file|memory>
|
|
379
|
+
keyring list [--backend <name>]
|
|
380
|
+
keyring set <key> <value> [--backend <name>]
|
|
381
|
+
keyring get <key> [--backend <name>]
|
|
382
|
+
keyring delete <key> [--backend <name>]
|
|
383
|
+
keyring export [--format env|json] [--output <file>] [--gpg <recipient>] [--backend <name>]
|
|
384
|
+
keyring import <file|-> [--format env|json] [--backend <name>]
|
|
385
|
+
|
|
386
|
+
Wallet commands:
|
|
387
|
+
wallets list
|
|
388
|
+
wallets export <address> --password <password> [--output <file>]
|
|
389
|
+
wallets import <file|-> --password <password> [--alias <alias>] [--hidden]
|
|
390
|
+
|
|
391
|
+
Diagnostics commands:
|
|
392
|
+
diagnostics run [--json] [--verbose] [--fix] [--skip-gpg]
|
|
393
|
+
`);
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const handlers: Record<string, Record<string, CommandHandler>> = {
|
|
397
|
+
keyring: keyringHandlers,
|
|
398
|
+
wallets: walletHandlers,
|
|
399
|
+
diagnostics: diagnosticsHandlers
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const main = async () => {
|
|
403
|
+
const args = process.argv.slice(2);
|
|
404
|
+
const namespace = args.shift();
|
|
405
|
+
if (!namespace) {
|
|
406
|
+
printHelp();
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const group = handlers[namespace as keyof typeof handlers];
|
|
410
|
+
if (!group) {
|
|
411
|
+
throw new Error(`Unknown command group '${namespace}'.`);
|
|
412
|
+
}
|
|
413
|
+
const subcommand = args.shift() ?? 'list';
|
|
414
|
+
const handler = group[subcommand];
|
|
415
|
+
if (!handler) {
|
|
416
|
+
throw new Error(`Unknown ${namespace} command '${subcommand}'.`);
|
|
417
|
+
}
|
|
418
|
+
await handler(args);
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
main().catch((error) => {
|
|
422
|
+
console.error(error instanceof Error ? error.message : error);
|
|
423
|
+
process.exitCode = 1;
|
|
424
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
contract OracleConsumer {
|
|
5
|
+
uint256 public data;
|
|
6
|
+
|
|
7
|
+
event Requested(bytes32 requestId, string jobId, string url, string path);
|
|
8
|
+
event Fulfilled(bytes32 requestId, uint256 value);
|
|
9
|
+
|
|
10
|
+
function requestData(string memory jobId, string memory url, string memory path) external returns (bytes32) {
|
|
11
|
+
bytes32 requestId = keccak256(abi.encodePacked(block.timestamp, msg.sender, jobId, url, path));
|
|
12
|
+
emit Requested(requestId, jobId, url, path);
|
|
13
|
+
return requestId;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function fulfill(bytes32 requestId, uint256 value) external {
|
|
17
|
+
data = value;
|
|
18
|
+
emit Fulfilled(requestId, value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
interface AggregatorV3Interface {
|
|
5
|
+
function latestRoundData()
|
|
6
|
+
external
|
|
7
|
+
view
|
|
8
|
+
returns (uint80, int256, uint256, uint256, uint80);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
contract PriceFeedConsumer {
|
|
12
|
+
AggregatorV3Interface internal priceFeed;
|
|
13
|
+
|
|
14
|
+
constructor(address feedAddress) {
|
|
15
|
+
priceFeed = AggregatorV3Interface(feedAddress);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getLatestPrice() external view returns (int256) {
|
|
19
|
+
(, int256 price, , , ) = priceFeed.latestRoundData();
|
|
20
|
+
return price;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# GNOMAN 2.0 Development Guide
|
|
2
|
+
|
|
3
|
+
This guide documents the authoritative workflow for standing up a GNOMAN 2.0
|
|
4
|
+
workstation, exercising the offline licensing stack, and producing builds that
|
|
5
|
+
match what ships to customers. Every path is written relative to the repository
|
|
6
|
+
root (the directory that contains `package.json`).
|
|
7
|
+
|
|
8
|
+
> ℹ️ A byte-for-byte copy of this guide lives at
|
|
9
|
+
> `docs/wiki/development-guide.md` for the in-app wiki. Whenever you update this
|
|
10
|
+
> file, mirror the edits in the wiki directory so desktop users and GitHub
|
|
11
|
+
> readers see the same information.
|
|
12
|
+
|
|
13
|
+
## 1. Tooling prerequisites
|
|
14
|
+
|
|
15
|
+
| Tool | Required version | Notes |
|
|
16
|
+
| ---- | ---------------- | ----- |
|
|
17
|
+
| Node.js | 18 LTS | Bundles npm 9, which is required by the build scripts. |
|
|
18
|
+
| npm | 9.x | Installed with Node.js. |
|
|
19
|
+
| Python | 3.10 or newer | Powers the Ed25519 licensing utilities. |
|
|
20
|
+
| pip package | `cryptography` | Install with `pip install cryptography`. |
|
|
21
|
+
| Native build chain | OS specific | Xcode Command Line Tools on macOS, `build-essential` on Linux, or Windows Build Tools to compile `better-sqlite3`. The AES keyring runs entirely in user space (no native bindings). |
|
|
22
|
+
|
|
23
|
+
Clone the repository and install dependencies:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
(cd renderer && npm install)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The root install triggers the renderer install via the `postinstall` hook, but
|
|
31
|
+
running both commands explicitly surfaces dependency errors sooner.
|
|
32
|
+
|
|
33
|
+
## 2. Environment configuration
|
|
34
|
+
|
|
35
|
+
1. Copy the template to create a working `.env`:
|
|
36
|
+
```bash
|
|
37
|
+
cp .env.example .env
|
|
38
|
+
```
|
|
39
|
+
2. Adjust variables as needed:
|
|
40
|
+
- `PORT` controls the Express API port (defaults to `4399`).
|
|
41
|
+
- `VITE_DEV_SERVER_URL` points the Electron shell at the renderer dev server
|
|
42
|
+
during development.
|
|
43
|
+
- `LICENSE_PRIVATE_KEY` points to the Ed25519 signing key used by
|
|
44
|
+
`backend/licenses/gen_license.py`. The default
|
|
45
|
+
`backend/licenses/license_private.pem` is resolved relative to the
|
|
46
|
+
repository root. Keep the actual private key outside of source control.
|
|
47
|
+
|
|
48
|
+
### 2.1 AES keyring management
|
|
49
|
+
|
|
50
|
+
The backend, main process, and renderer now rely on a unified keyring manager
|
|
51
|
+
that can hot-swap between the system keychain, an AES-GCM encrypted file store,
|
|
52
|
+
or an in-memory fallback. Use the REST endpoints to administer secrets without
|
|
53
|
+
restarting the app:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# List masked secrets for the active backend
|
|
57
|
+
curl http://127.0.0.1:${PORT:-4399}/api/keyring | jq
|
|
58
|
+
|
|
59
|
+
# Store a secret
|
|
60
|
+
curl -X POST http://127.0.0.1:${PORT:-4399}/api/keyring/RPC_URL \
|
|
61
|
+
-H 'Content-Type: application/json' \
|
|
62
|
+
-d '{"value":"https://sepolia.infura.io/v3/..."}'
|
|
63
|
+
|
|
64
|
+
# Reveal a secret (returns the decrypted payload)
|
|
65
|
+
curl http://127.0.0.1:${PORT:-4399}/api/keyring/RPC_URL | jq
|
|
66
|
+
|
|
67
|
+
# Remove a secret
|
|
68
|
+
curl -X DELETE http://127.0.0.1:${PORT:-4399}/api/keyring/RPC_URL
|
|
69
|
+
|
|
70
|
+
# Inspect the active backend and available backends
|
|
71
|
+
curl http://127.0.0.1:${PORT:-4399}/api/keyring/backend | jq
|
|
72
|
+
|
|
73
|
+
# Switch to another backend and reload configuration in place
|
|
74
|
+
curl -X POST http://127.0.0.1:${PORT:-4399}/api/keyring/backend/file
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
When the system keychain is unavailable (for example, inside a sandboxed CI
|
|
78
|
+
runner), the manager automatically falls back to the encrypted file store and,
|
|
79
|
+
if needed, to the in-memory backend while logging warnings so you know secrets
|
|
80
|
+
may not persist between restarts.
|
|
81
|
+
|
|
82
|
+
## 3. Running the stack locally
|
|
83
|
+
|
|
84
|
+
Use separate terminals so logs stay readable.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm run dev:backend # Express API at http://localhost:4399
|
|
88
|
+
npm run dev:renderer # Vite dev server at http://localhost:5173
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If you prefer to start both web stacks together, run `npm run dev`, which wraps
|
|
92
|
+
the two commands above with `concurrently`.
|
|
93
|
+
|
|
94
|
+
Launch the Electron shell after the TypeScript projects finish compiling:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm run dev:electron # Builds backend/main/renderer and opens the desktop window
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The Electron shell loads the renderer URL in development and the packaged
|
|
101
|
+
`dist/renderer/index.html` file after a production build.
|
|
102
|
+
|
|
103
|
+
## 4. Offline licensing workflows
|
|
104
|
+
|
|
105
|
+
GNOMAN 2.0 keeps the private key offline and validates tokens locally. The
|
|
106
|
+
preload bridge (`main/preload/licenseBridge.ts`) invokes the existing Python
|
|
107
|
+
verifier and persists successful validations under `.safevault/license.env`.
|
|
108
|
+
|
|
109
|
+
### 4.1 Generate an Ed25519 keypair (one-time)
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
python backend/licenses/make_keys.py
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The command writes two files:
|
|
116
|
+
|
|
117
|
+
- `backend/licenses/license_private.pem` – keep this file offline and untracked.
|
|
118
|
+
- `backend/licenses/license_public.pem` – commit this file; it ships with the
|
|
119
|
+
application and is used by the verifier.
|
|
120
|
+
|
|
121
|
+
### 4.2 Issue a license token
|
|
122
|
+
|
|
123
|
+
Run the issuer from the repository root so relative paths resolve correctly:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
python backend/licenses/gen_license.py \
|
|
127
|
+
--priv backend/licenses/license_private.pem \
|
|
128
|
+
--id workstation-001 \
|
|
129
|
+
--product GNOMAN \
|
|
130
|
+
--version 2.0.0 \
|
|
131
|
+
--days 365
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The script prints two representations:
|
|
135
|
+
|
|
136
|
+
- **RAW TOKEN** – base64url payload and signature separated by a dot.
|
|
137
|
+
- **HUMAN-FRIENDLY** – dashed Base32 string that is easier to transcribe.
|
|
138
|
+
|
|
139
|
+
Either format can be supplied to the desktop client. Store the value somewhere
|
|
140
|
+
secure so you do not need to reissue it later.
|
|
141
|
+
|
|
142
|
+
### 4.3 Validate a token without the UI
|
|
143
|
+
|
|
144
|
+
Use the Python helper to verify a token directly from the command line. The
|
|
145
|
+
verifier returns `True` for a valid token and `False` otherwise.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
python -c "import sys; from backend.licenses.verify_license import verify_token; print(verify_token(sys.argv[1], sys.argv[2], 'GNOMAN', '2.0.0'))" backend/licenses/license_public.pem <token>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Replace `<token>` with either the raw token or a Base32 string that decodes to
|
|
152
|
+
one. The helper resolves relative paths with respect to the repository root, so
|
|
153
|
+
invoking it from other directories works as long as you supply the correct
|
|
154
|
+
inputs.
|
|
155
|
+
|
|
156
|
+
### 4.4 Desktop activation flow
|
|
157
|
+
|
|
158
|
+
1. Launch the Electron shell (`npm run dev:electron`) and navigate to the
|
|
159
|
+
license screen if it does not appear automatically.
|
|
160
|
+
2. Enter either token representation. The preload bridge runs
|
|
161
|
+
`verify_license.py` with the checked-in public key.
|
|
162
|
+
3. When verification succeeds, the preload writes `.safevault/license.env` with:
|
|
163
|
+
```
|
|
164
|
+
LICENSE_KEY=<raw token>
|
|
165
|
+
VALIDATED_AT=<unix timestamp>
|
|
166
|
+
```
|
|
167
|
+
4. On subsequent launches the preload re-verifies the stored token. If it has
|
|
168
|
+
expired or the verification fails, the renderer prompts for a new license.
|
|
169
|
+
|
|
170
|
+
For headless automation or regression tests, the REST endpoint
|
|
171
|
+
`POST /api/license` remains available. It performs the same Ed25519 checks using
|
|
172
|
+
Node.js and persists JSON metadata under `.gnoman/license.json` for backwards
|
|
173
|
+
compatibility.
|
|
174
|
+
|
|
175
|
+
## 5. Build, lint, and packaging commands
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
| ------- | ----------- |
|
|
179
|
+
| `npm run lint` | Run ESLint across the backend, main process, renderer, and shared modules. |
|
|
180
|
+
| `npm run build:backend` | Compile the Express API to `dist/backend`. |
|
|
181
|
+
| `npm run build:main` | Compile the Electron main process to `dist/main`. |
|
|
182
|
+
| `npm run build:renderer` | Build the renderer UI into `renderer/dist`. |
|
|
183
|
+
| `npm run build` | Clean and produce all distributable artifacts (backend, main, renderer). |
|
|
184
|
+
| `npm start` | Rebuild and launch the packaged Electron shell. |
|
|
185
|
+
| `npm run start:backend` | Run the compiled backend directly from `dist/backend/index.js`. |
|
|
186
|
+
|
|
187
|
+
Distribution builds live under the `dist/` directory. The `scripts/copyRenderer.js`
|
|
188
|
+
helper copies the renderer bundle into `dist/main/` so the packaged Electron app
|
|
189
|
+
can load it from disk.
|
|
190
|
+
|
|
191
|
+
## 6. Troubleshooting checklist
|
|
192
|
+
|
|
193
|
+
| Symptom | Suggested fix |
|
|
194
|
+
| ------- | -------------- |
|
|
195
|
+
| `ModuleNotFoundError: No module named 'cryptography'` | Install the Python dependency with `pip install cryptography`. |
|
|
196
|
+
| `python3` not found when validating a license | Ensure Python 3.10+ is installed and available on your `PATH`. Update the preload bridge to point at the correct executable if you use pyenv. |
|
|
197
|
+
| `better-sqlite3` fails to compile | Install the platform build tools (Xcode CLI tools, `build-essential`, or Windows Build Tools) before running `npm install` again. |
|
|
198
|
+
| Renderer cannot reach the backend | Confirm `npm run dev:backend` is running and the port matches `renderer/src/config/api.ts`. |
|
|
199
|
+
| License verification unexpectedly fails | Delete `.safevault/license.env` and re-run activation to ensure the stored token has not been corrupted. |
|
|
200
|
+
| Electron window opens without UI in production mode | Run `npm run build:renderer` before launching `npm start` so the packaged assets exist. |
|
|
201
|
+
|
|
202
|
+
Following these conventions keeps every workstation aligned with the offline
|
|
203
|
+
licensing flow and build system that GNOMAN 2.0 expects in production.
|