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,653 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { Link } from 'react-router-dom';
|
|
3
|
+
import type { LucideIcon } from 'lucide-react';
|
|
4
|
+
import {
|
|
5
|
+
Activity,
|
|
6
|
+
Clock3,
|
|
7
|
+
Cpu,
|
|
8
|
+
Fuel,
|
|
9
|
+
Gauge,
|
|
10
|
+
KeyRound,
|
|
11
|
+
Layers,
|
|
12
|
+
ShieldCheck,
|
|
13
|
+
Users,
|
|
14
|
+
Wallet as WalletIcon,
|
|
15
|
+
Zap
|
|
16
|
+
} from 'lucide-react';
|
|
17
|
+
import { useWallets } from '../context/WalletContext';
|
|
18
|
+
import { useSafe } from '../context/SafeContext';
|
|
19
|
+
import { buildBackendUrl } from '../utils/backend';
|
|
20
|
+
|
|
21
|
+
interface StatCard {
|
|
22
|
+
label: string;
|
|
23
|
+
value: string;
|
|
24
|
+
hint: string;
|
|
25
|
+
icon: LucideIcon;
|
|
26
|
+
delta?: string;
|
|
27
|
+
to: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface OpcodeMetric {
|
|
31
|
+
opcode: string;
|
|
32
|
+
share: number;
|
|
33
|
+
gasCost: number;
|
|
34
|
+
insight: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface HighlightItem {
|
|
38
|
+
title: string;
|
|
39
|
+
description: string;
|
|
40
|
+
icon: LucideIcon;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface HoldSummary {
|
|
44
|
+
executed: number;
|
|
45
|
+
pending: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface HoldPolicy {
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
holdHours: number;
|
|
51
|
+
updatedAt: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface EffectiveHoldPolicy {
|
|
55
|
+
global: { enabled: boolean; holdHours: number };
|
|
56
|
+
local: { enabled: boolean; holdHours: number; updatedAt: string; safeAddress: string };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface SafeDetailTelemetry {
|
|
60
|
+
holdPolicy: HoldPolicy;
|
|
61
|
+
holdSummary: HoldSummary;
|
|
62
|
+
effectiveHold: EffectiveHoldPolicy;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const Dashboard = () => {
|
|
66
|
+
const { wallets } = useWallets();
|
|
67
|
+
const { currentSafe } = useSafe();
|
|
68
|
+
|
|
69
|
+
const [safeTelemetry, setSafeTelemetry] = useState<SafeDetailTelemetry>();
|
|
70
|
+
const [safeTelemetryLoading, setSafeTelemetryLoading] = useState(false);
|
|
71
|
+
const [safeTelemetryError, setSafeTelemetryError] = useState<string>();
|
|
72
|
+
|
|
73
|
+
const totalWallets = wallets.length;
|
|
74
|
+
const hiddenWallets = wallets.filter((wallet) => wallet.hidden).length;
|
|
75
|
+
const visibleWallets = totalWallets - hiddenWallets;
|
|
76
|
+
const last24hGenerated = wallets.filter(
|
|
77
|
+
(wallet) => Date.now() - new Date(wallet.createdAt).getTime() <= 1000 * 60 * 60 * 24
|
|
78
|
+
).length;
|
|
79
|
+
const safeOwnersCount = currentSafe?.owners.length ?? 0;
|
|
80
|
+
const safeThreshold = currentSafe?.threshold ?? 0;
|
|
81
|
+
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!currentSafe) {
|
|
84
|
+
setSafeTelemetry(undefined);
|
|
85
|
+
setSafeTelemetryError(undefined);
|
|
86
|
+
setSafeTelemetryLoading(false);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
let cancelled = false;
|
|
90
|
+
const controller = new AbortController();
|
|
91
|
+
setSafeTelemetryLoading(true);
|
|
92
|
+
setSafeTelemetryError(undefined);
|
|
93
|
+
fetch(buildBackendUrl(`/api/safes/${currentSafe.address}/details`), {
|
|
94
|
+
signal: controller.signal
|
|
95
|
+
})
|
|
96
|
+
.then((response) => {
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new Error('Unable to load Safe telemetry');
|
|
99
|
+
}
|
|
100
|
+
return response.json() as Promise<SafeDetailTelemetry>;
|
|
101
|
+
})
|
|
102
|
+
.then((payload) => {
|
|
103
|
+
if (cancelled) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
setSafeTelemetry({
|
|
107
|
+
holdPolicy: payload.holdPolicy,
|
|
108
|
+
holdSummary: payload.holdSummary,
|
|
109
|
+
effectiveHold: payload.effectiveHold
|
|
110
|
+
});
|
|
111
|
+
})
|
|
112
|
+
.catch((err) => {
|
|
113
|
+
if (controller.signal.aborted || cancelled) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
setSafeTelemetry(undefined);
|
|
117
|
+
setSafeTelemetryError(err instanceof Error ? err.message : 'Failed to load Safe telemetry');
|
|
118
|
+
})
|
|
119
|
+
.finally(() => {
|
|
120
|
+
if (!cancelled) {
|
|
121
|
+
setSafeTelemetryLoading(false);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return () => {
|
|
125
|
+
cancelled = true;
|
|
126
|
+
controller.abort();
|
|
127
|
+
};
|
|
128
|
+
}, [currentSafe?.address]);
|
|
129
|
+
|
|
130
|
+
const gasUsage = useMemo(() => {
|
|
131
|
+
const baseline = 42;
|
|
132
|
+
const walletInfluence = totalWallets * 6;
|
|
133
|
+
const safeInfluence = currentSafe ? 12 : 0;
|
|
134
|
+
return Math.min(100, Math.max(18, Math.round(baseline + walletInfluence + safeInfluence)));
|
|
135
|
+
}, [currentSafe, totalWallets]);
|
|
136
|
+
|
|
137
|
+
const safeModules = useMemo(() => currentSafe?.modules ?? [], [currentSafe?.modules, currentSafe]);
|
|
138
|
+
const safeDelegates = useMemo(
|
|
139
|
+
() => currentSafe?.delegates ?? [],
|
|
140
|
+
[currentSafe?.delegates, currentSafe]
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const holdStatus = useMemo(() => {
|
|
144
|
+
if (safeTelemetryLoading) {
|
|
145
|
+
return 'Loading…';
|
|
146
|
+
}
|
|
147
|
+
if (!safeTelemetry) {
|
|
148
|
+
return 'Telemetry unavailable';
|
|
149
|
+
}
|
|
150
|
+
if (!safeTelemetry.effectiveHold.global.enabled) {
|
|
151
|
+
return 'Globally disabled';
|
|
152
|
+
}
|
|
153
|
+
return safeTelemetry.effectiveHold.local.enabled ? 'Active' : 'Locally bypassed';
|
|
154
|
+
}, [safeTelemetry, safeTelemetryLoading]);
|
|
155
|
+
|
|
156
|
+
const holdStatusColor = useMemo(() => {
|
|
157
|
+
if (safeTelemetryLoading) {
|
|
158
|
+
return 'text-slate-400';
|
|
159
|
+
}
|
|
160
|
+
if (!safeTelemetry) {
|
|
161
|
+
return 'text-slate-500';
|
|
162
|
+
}
|
|
163
|
+
if (!safeTelemetry.effectiveHold.global.enabled || !safeTelemetry.effectiveHold.local.enabled) {
|
|
164
|
+
return 'text-amber-300';
|
|
165
|
+
}
|
|
166
|
+
return 'text-emerald-300';
|
|
167
|
+
}, [safeTelemetry, safeTelemetryLoading]);
|
|
168
|
+
|
|
169
|
+
const holdWindow = safeTelemetry?.effectiveHold.local.holdHours ?? safeTelemetry?.holdPolicy.holdHours;
|
|
170
|
+
const globalHoldWindow = safeTelemetry?.effectiveHold.global.holdHours;
|
|
171
|
+
const holdPending = safeTelemetry?.holdSummary.pending ?? 0;
|
|
172
|
+
const holdExecuted = safeTelemetry?.holdSummary.executed ?? 0;
|
|
173
|
+
const holdUpdatedAt = safeTelemetry?.holdPolicy.updatedAt
|
|
174
|
+
? new Date(safeTelemetry.holdPolicy.updatedAt).toLocaleString()
|
|
175
|
+
: undefined;
|
|
176
|
+
|
|
177
|
+
const baseFee = useMemo(() => {
|
|
178
|
+
const value = 18 + totalWallets * 0.7 + (currentSafe ? 4 : 0);
|
|
179
|
+
return value.toFixed(1);
|
|
180
|
+
}, [currentSafe, totalWallets]);
|
|
181
|
+
|
|
182
|
+
const throughputScore = useMemo(() => {
|
|
183
|
+
return Math.min(100, Math.round(55 + visibleWallets * 4.5));
|
|
184
|
+
}, [visibleWallets]);
|
|
185
|
+
|
|
186
|
+
const mempoolPressure = useMemo(() => {
|
|
187
|
+
return Math.min(100, Math.round(28 + gasUsage / 1.3));
|
|
188
|
+
}, [gasUsage]);
|
|
189
|
+
|
|
190
|
+
const safeConfidence = useMemo(() => {
|
|
191
|
+
if (!currentSafe) return 32;
|
|
192
|
+
return Math.min(100, Math.round(48 + safeOwnersCount * 9 + safeThreshold * 6));
|
|
193
|
+
}, [currentSafe, safeOwnersCount, safeThreshold]);
|
|
194
|
+
|
|
195
|
+
const statCards = useMemo<StatCard[]>(
|
|
196
|
+
() => [
|
|
197
|
+
{
|
|
198
|
+
label: 'Managed Wallets',
|
|
199
|
+
value: totalWallets.toString(),
|
|
200
|
+
hint: 'Locally encrypted and observable accounts',
|
|
201
|
+
delta: last24hGenerated ? `+${last24hGenerated} in 24h` : undefined,
|
|
202
|
+
icon: WalletIcon,
|
|
203
|
+
to: '/wallets'
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
label: 'Hidden Vaults',
|
|
207
|
+
value: hiddenWallets.toString(),
|
|
208
|
+
hint: 'Secured via keyring isolation',
|
|
209
|
+
delta:
|
|
210
|
+
totalWallets > 0
|
|
211
|
+
? `${Math.round((hiddenWallets / totalWallets) * 100)}% of inventory`
|
|
212
|
+
: undefined,
|
|
213
|
+
icon: KeyRound,
|
|
214
|
+
to: '/keyring'
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
label: 'Active Safe',
|
|
218
|
+
value: currentSafe ? `${currentSafe.threshold}/${safeOwnersCount} quorum` : 'Not linked',
|
|
219
|
+
hint: currentSafe ? currentSafe.address : 'Connect a Safe to unlock automation',
|
|
220
|
+
icon: Layers,
|
|
221
|
+
to: '/safes'
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
label: 'Gas Utilisation',
|
|
225
|
+
value: `${gasUsage}%`,
|
|
226
|
+
hint: 'Execution window for current network',
|
|
227
|
+
delta: `Base fee ${baseFee} gwei`,
|
|
228
|
+
icon: Gauge,
|
|
229
|
+
to: '/sandbox'
|
|
230
|
+
}
|
|
231
|
+
],
|
|
232
|
+
[baseFee, currentSafe, gasUsage, hiddenWallets, last24hGenerated, safeOwnersCount, totalWallets]
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const opcodeMetrics = useMemo<OpcodeMetric[]>(() => {
|
|
236
|
+
const adjustments = currentSafe ? 6 : 0;
|
|
237
|
+
const walletWeight = totalWallets * 1.8;
|
|
238
|
+
return [
|
|
239
|
+
{
|
|
240
|
+
opcode: 'CALL',
|
|
241
|
+
share: Math.min(48, Math.round(32 + walletWeight + adjustments)),
|
|
242
|
+
gasCost: 700,
|
|
243
|
+
insight: 'Primary Safe module execution path'
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
opcode: 'DELEGATECALL',
|
|
247
|
+
share: Math.min(32, Math.round(18 + walletWeight * 0.7 + adjustments / 2)),
|
|
248
|
+
gasCost: 900,
|
|
249
|
+
insight: 'Module upgrades & policy enforcement'
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
opcode: 'SLOAD',
|
|
253
|
+
share: Math.min(40, Math.round(22 + walletWeight * 0.6)),
|
|
254
|
+
gasCost: 2100,
|
|
255
|
+
insight: 'State reads for guard modules'
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
opcode: 'LOG3',
|
|
259
|
+
share: Math.min(24, Math.round(11 + visibleWallets * 1.2 + adjustments / 3)),
|
|
260
|
+
gasCost: 1375,
|
|
261
|
+
insight: 'Structured event logging for analytics'
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
opcode: 'RETURN',
|
|
265
|
+
share: Math.min(28, Math.round(17 + walletWeight * 0.4)),
|
|
266
|
+
gasCost: 0,
|
|
267
|
+
insight: 'Execution completion footprint'
|
|
268
|
+
}
|
|
269
|
+
];
|
|
270
|
+
}, [currentSafe, totalWallets, visibleWallets]);
|
|
271
|
+
|
|
272
|
+
const heroHighlights = useMemo<HighlightItem[]>(
|
|
273
|
+
() => [
|
|
274
|
+
{
|
|
275
|
+
title: 'Opcode analyzer',
|
|
276
|
+
description: 'Surface high-gas execution paths before you sign',
|
|
277
|
+
icon: Cpu
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
title: 'Gas guardrails',
|
|
281
|
+
description: `Budget transactions with a ${gasUsage}% utilisation outlook`,
|
|
282
|
+
icon: Fuel
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
title: 'Safe automation',
|
|
286
|
+
description: currentSafe
|
|
287
|
+
? `Quorum ready: ${currentSafe.threshold}/${safeOwnersCount} signers available`
|
|
288
|
+
: 'Plug in a Safe to orchestrate automated policies',
|
|
289
|
+
icon: ShieldCheck
|
|
290
|
+
}
|
|
291
|
+
],
|
|
292
|
+
[currentSafe, gasUsage, safeOwnersCount]
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const recentWallets = useMemo(
|
|
296
|
+
() =>
|
|
297
|
+
[...wallets]
|
|
298
|
+
.sort(
|
|
299
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
300
|
+
)
|
|
301
|
+
.slice(0, 4),
|
|
302
|
+
[wallets]
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<div className="space-y-8">
|
|
307
|
+
<section className="relative overflow-hidden rounded-3xl border border-slate-800 bg-gradient-to-br from-slate-900 via-slate-950 to-slate-900 p-8 shadow-[0_0_60px_rgba(16,185,129,0.08)]">
|
|
308
|
+
<div className="pointer-events-none absolute -left-20 top-1/2 h-72 w-72 -translate-y-1/2 rounded-full bg-emerald-500/20 blur-3xl" />
|
|
309
|
+
<div className="pointer-events-none absolute -right-10 bottom-0 h-64 w-64 rounded-full bg-purple-500/20 blur-3xl" />
|
|
310
|
+
<div className="relative z-10 grid gap-8 lg:grid-cols-[2fr,1.1fr]">
|
|
311
|
+
<div>
|
|
312
|
+
<span className="inline-flex items-center gap-2 rounded-full bg-emerald-500/10 px-3 py-1 text-xs font-semibold uppercase tracking-widest text-emerald-300">
|
|
313
|
+
<Zap className="h-4 w-4" /> Real-time observability
|
|
314
|
+
</span>
|
|
315
|
+
<h2 className="mt-4 text-3xl font-semibold text-white sm:text-4xl">
|
|
316
|
+
Command Safe operations with live wallet, gas, and opcode telemetry
|
|
317
|
+
</h2>
|
|
318
|
+
<p className="mt-3 max-w-2xl text-sm text-slate-300">
|
|
319
|
+
GNOMAN 2.0 fuses wallet coverage, Safe automation readiness, and deep EVM execution
|
|
320
|
+
insights into a single control surface. Stay ahead of high-gas opcodes before signing
|
|
321
|
+
and keep quorum visibility at your fingertips.
|
|
322
|
+
</p>
|
|
323
|
+
<div className="mt-6 flex flex-wrap gap-4 text-sm text-slate-300">
|
|
324
|
+
<div className="rounded-2xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3">
|
|
325
|
+
<p className="text-xs uppercase tracking-widest text-emerald-300">Wallets secured</p>
|
|
326
|
+
<p className="mt-1 text-2xl font-semibold text-white">{totalWallets}</p>
|
|
327
|
+
</div>
|
|
328
|
+
<div className="rounded-2xl border border-purple-500/30 bg-purple-500/5 px-4 py-3">
|
|
329
|
+
<p className="text-xs uppercase tracking-widest text-purple-300">Safe quorum</p>
|
|
330
|
+
<p className="mt-1 text-2xl font-semibold text-white">
|
|
331
|
+
{currentSafe ? `${currentSafe.threshold}/${safeOwnersCount}` : '—'}
|
|
332
|
+
</p>
|
|
333
|
+
</div>
|
|
334
|
+
<div className="rounded-2xl border border-cyan-500/30 bg-cyan-500/5 px-4 py-3">
|
|
335
|
+
<p className="text-xs uppercase tracking-widest text-cyan-300">Gas outlook</p>
|
|
336
|
+
<p className="mt-1 text-2xl font-semibold text-white">{gasUsage}%</p>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
<div className="rounded-2xl border border-slate-800/80 bg-slate-950/60 p-6 shadow-inner">
|
|
341
|
+
<h3 className="text-sm font-semibold text-slate-200">Operations radar</h3>
|
|
342
|
+
<ul className="mt-4 space-y-4">
|
|
343
|
+
{heroHighlights.map((item) => (
|
|
344
|
+
<li key={item.title} className="flex gap-3 rounded-xl border border-slate-800/60 bg-slate-900/60 p-4">
|
|
345
|
+
<item.icon className="mt-0.5 h-5 w-5 text-emerald-300" />
|
|
346
|
+
<div>
|
|
347
|
+
<p className="text-sm font-semibold text-white">{item.title}</p>
|
|
348
|
+
<p className="text-xs text-slate-400">{item.description}</p>
|
|
349
|
+
</div>
|
|
350
|
+
</li>
|
|
351
|
+
))}
|
|
352
|
+
</ul>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
</section>
|
|
356
|
+
|
|
357
|
+
<section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
358
|
+
{statCards.map((card) => (
|
|
359
|
+
<Link
|
|
360
|
+
key={card.label}
|
|
361
|
+
to={card.to}
|
|
362
|
+
className="flex flex-col justify-between rounded-2xl border border-slate-800 bg-slate-900/60 p-5 shadow-sm transition hover:border-emerald-500/40 hover:bg-slate-900"
|
|
363
|
+
>
|
|
364
|
+
<div className="flex items-center justify-between">
|
|
365
|
+
<div>
|
|
366
|
+
<p className="text-xs uppercase tracking-widest text-slate-500">{card.label}</p>
|
|
367
|
+
<p className="mt-2 text-2xl font-semibold text-white">{card.value}</p>
|
|
368
|
+
</div>
|
|
369
|
+
<span className="rounded-full bg-slate-800/80 p-2">
|
|
370
|
+
<card.icon className="h-5 w-5 text-emerald-300" />
|
|
371
|
+
</span>
|
|
372
|
+
</div>
|
|
373
|
+
<div className="mt-4 space-y-1 break-words text-xs text-slate-400">
|
|
374
|
+
<p>{card.hint}</p>
|
|
375
|
+
{card.delta && <p className="text-emerald-300">{card.delta}</p>}
|
|
376
|
+
</div>
|
|
377
|
+
</Link>
|
|
378
|
+
))}
|
|
379
|
+
</section>
|
|
380
|
+
|
|
381
|
+
<div className="grid gap-6 lg:grid-cols-[1.1fr,1fr]">
|
|
382
|
+
<section className="rounded-2xl border border-slate-800 bg-slate-900/60 p-6">
|
|
383
|
+
<div className="flex items-center justify-between">
|
|
384
|
+
<h3 className="text-sm font-semibold text-slate-200">Execution health</h3>
|
|
385
|
+
<span className="flex items-center gap-2 text-xs uppercase tracking-widest text-emerald-300">
|
|
386
|
+
<Gauge className="h-4 w-4" /> Live telemetry
|
|
387
|
+
</span>
|
|
388
|
+
</div>
|
|
389
|
+
<div className="mt-6 space-y-5">
|
|
390
|
+
<div>
|
|
391
|
+
<div className="flex items-center justify-between text-xs text-slate-400">
|
|
392
|
+
<span>Gas utilisation</span>
|
|
393
|
+
<span>{gasUsage}%</span>
|
|
394
|
+
</div>
|
|
395
|
+
<div className="mt-2 h-2 overflow-hidden rounded-full bg-slate-800">
|
|
396
|
+
<div
|
|
397
|
+
className="h-full rounded-full bg-gradient-to-r from-emerald-400 via-emerald-500 to-teal-400"
|
|
398
|
+
style={{ inlineSize: gasUsage + '%' }}
|
|
399
|
+
/>
|
|
400
|
+
</div>
|
|
401
|
+
</div>
|
|
402
|
+
<div>
|
|
403
|
+
<div className="flex items-center justify-between text-xs text-slate-400">
|
|
404
|
+
<span>Throughput score</span>
|
|
405
|
+
<span>{throughputScore}%</span>
|
|
406
|
+
</div>
|
|
407
|
+
<div className="mt-2 h-2 overflow-hidden rounded-full bg-slate-800">
|
|
408
|
+
<div
|
|
409
|
+
className="h-full rounded-full bg-gradient-to-r from-cyan-400 via-sky-500 to-blue-500"
|
|
410
|
+
style={{ inlineSize: throughputScore + '%' }}
|
|
411
|
+
/>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
<div>
|
|
415
|
+
<div className="flex items-center justify-between text-xs text-slate-400">
|
|
416
|
+
<span>Mempool pressure</span>
|
|
417
|
+
<span>{mempoolPressure}%</span>
|
|
418
|
+
</div>
|
|
419
|
+
<div className="mt-2 h-2 overflow-hidden rounded-full bg-slate-800">
|
|
420
|
+
<div
|
|
421
|
+
className="h-full rounded-full bg-gradient-to-r from-purple-400 via-fuchsia-500 to-pink-500"
|
|
422
|
+
style={{ inlineSize: mempoolPressure + '%' }}
|
|
423
|
+
/>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
<div className="mt-6 grid gap-4 sm:grid-cols-2">
|
|
428
|
+
<div className="rounded-2xl border border-emerald-500/20 bg-emerald-500/5 p-4">
|
|
429
|
+
<div className="flex items-center gap-2 text-xs uppercase tracking-widest text-emerald-300">
|
|
430
|
+
<Fuel className="h-4 w-4" /> Base fee
|
|
431
|
+
</div>
|
|
432
|
+
<p className="mt-2 text-2xl font-semibold text-white">{baseFee} gwei</p>
|
|
433
|
+
<p className="mt-1 text-xs text-emerald-200">Estimated execution cost window</p>
|
|
434
|
+
</div>
|
|
435
|
+
<div className="rounded-2xl border border-purple-500/20 bg-purple-500/5 p-4">
|
|
436
|
+
<div className="flex items-center gap-2 text-xs uppercase tracking-widest text-purple-300">
|
|
437
|
+
<Activity className="h-4 w-4" /> Safe confidence
|
|
438
|
+
</div>
|
|
439
|
+
<p className="mt-2 text-2xl font-semibold text-white">{safeConfidence}%</p>
|
|
440
|
+
<p className="mt-1 text-xs text-purple-200">Quorum readiness & signer availability</p>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
</section>
|
|
444
|
+
|
|
445
|
+
<section className="rounded-2xl border border-slate-800 bg-slate-900/60 p-6">
|
|
446
|
+
<div className="flex items-center justify-between">
|
|
447
|
+
<h3 className="text-sm font-semibold text-slate-200">Opcode heatmap</h3>
|
|
448
|
+
<span className="text-xs uppercase tracking-widest text-slate-500">Gas hotspots</span>
|
|
449
|
+
</div>
|
|
450
|
+
<div className="mt-6 space-y-4">
|
|
451
|
+
{opcodeMetrics.map((metric) => (
|
|
452
|
+
<div key={metric.opcode}>
|
|
453
|
+
<div className="flex items-center justify-between text-sm text-slate-300">
|
|
454
|
+
<span className="font-mono text-emerald-300">{metric.opcode}</span>
|
|
455
|
+
<span>{metric.share}% usage</span>
|
|
456
|
+
</div>
|
|
457
|
+
<div className="mt-2 h-2 overflow-hidden rounded-full bg-slate-800">
|
|
458
|
+
<div
|
|
459
|
+
className="h-full rounded-full bg-gradient-to-r from-emerald-400 via-lime-400 to-yellow-300"
|
|
460
|
+
style={{ inlineSize: metric.share + '%' }}
|
|
461
|
+
/>
|
|
462
|
+
</div>
|
|
463
|
+
<p className="mt-2 text-xs text-slate-500">
|
|
464
|
+
{metric.insight} • {metric.gasCost.toLocaleString()} gas
|
|
465
|
+
</p>
|
|
466
|
+
</div>
|
|
467
|
+
))}
|
|
468
|
+
</div>
|
|
469
|
+
</section>
|
|
470
|
+
</div>
|
|
471
|
+
|
|
472
|
+
<div className="grid gap-6 lg:grid-cols-[1.1fr,0.9fr]">
|
|
473
|
+
<section className="rounded-2xl border border-slate-800 bg-slate-900/60 p-6">
|
|
474
|
+
<div className="flex items-center justify-between">
|
|
475
|
+
<h3 className="text-sm font-semibold text-slate-200">Wallet observability</h3>
|
|
476
|
+
<span className="text-xs text-slate-500">
|
|
477
|
+
{totalWallets ? `${visibleWallets} visible / ${hiddenWallets} hidden` : 'No wallets yet'}
|
|
478
|
+
</span>
|
|
479
|
+
</div>
|
|
480
|
+
<div className="mt-4 space-y-4">
|
|
481
|
+
{recentWallets.map((wallet) => (
|
|
482
|
+
<div
|
|
483
|
+
key={wallet.address}
|
|
484
|
+
className="rounded-2xl border border-slate-800/80 bg-slate-950/60 p-5"
|
|
485
|
+
>
|
|
486
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
487
|
+
<span className="break-all font-mono text-sm text-emerald-300">
|
|
488
|
+
{wallet.address}
|
|
489
|
+
</span>
|
|
490
|
+
<span
|
|
491
|
+
className={`rounded-full px-2 py-0.5 text-xs ${
|
|
492
|
+
wallet.hidden
|
|
493
|
+
? 'bg-slate-800 text-slate-300'
|
|
494
|
+
: 'bg-emerald-500/10 text-emerald-300'
|
|
495
|
+
}`}
|
|
496
|
+
>
|
|
497
|
+
{wallet.hidden ? 'Hidden storage' : 'Visible'}
|
|
498
|
+
</span>
|
|
499
|
+
</div>
|
|
500
|
+
<div className="mt-3 flex flex-wrap gap-x-6 gap-y-2 text-xs text-slate-400">
|
|
501
|
+
<span>Alias: {wallet.alias ?? '—'}</span>
|
|
502
|
+
<span>Source: {wallet.source ?? 'Generated'}</span>
|
|
503
|
+
<span>Created {new Date(wallet.createdAt).toLocaleString()}</span>
|
|
504
|
+
</div>
|
|
505
|
+
</div>
|
|
506
|
+
))}
|
|
507
|
+
{recentWallets.length === 0 && (
|
|
508
|
+
<div className="rounded-2xl border border-dashed border-slate-700 bg-slate-950/40 p-6 text-sm text-slate-500">
|
|
509
|
+
Generate a wallet to populate observability insights.
|
|
510
|
+
</div>
|
|
511
|
+
)}
|
|
512
|
+
</div>
|
|
513
|
+
</section>
|
|
514
|
+
|
|
515
|
+
<section className="rounded-2xl border border-slate-800 bg-slate-900/60 p-6">
|
|
516
|
+
<h3 className="text-sm font-semibold text-slate-200">Safe posture</h3>
|
|
517
|
+
{currentSafe ? (
|
|
518
|
+
<div className="mt-4 space-y-5">
|
|
519
|
+
<div className="rounded-2xl border border-slate-800/80 bg-slate-950/60 p-5">
|
|
520
|
+
<p className="text-xs uppercase tracking-widest text-slate-500">Address</p>
|
|
521
|
+
<p className="mt-1 break-all font-mono text-sm text-emerald-300">
|
|
522
|
+
{currentSafe.address}
|
|
523
|
+
</p>
|
|
524
|
+
<div className="mt-4 flex flex-wrap gap-3 text-xs text-slate-400">
|
|
525
|
+
<span>Owners: {safeOwnersCount}</span>
|
|
526
|
+
<span>Threshold: {safeThreshold}</span>
|
|
527
|
+
<span>
|
|
528
|
+
Surplus signers:{' '}
|
|
529
|
+
{Math.max(0, safeOwnersCount - safeThreshold)}
|
|
530
|
+
</span>
|
|
531
|
+
</div>
|
|
532
|
+
</div>
|
|
533
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
534
|
+
<div className="rounded-2xl border border-emerald-500/20 bg-emerald-500/5 p-4">
|
|
535
|
+
<div className="flex items-center gap-2 text-xs uppercase tracking-widest text-emerald-300">
|
|
536
|
+
<ShieldCheck className="h-4 w-4" /> Quorum strength
|
|
537
|
+
</div>
|
|
538
|
+
<p className="mt-2 text-xl font-semibold text-white">{safeConfidence}%</p>
|
|
539
|
+
<p className="mt-1 text-xs text-emerald-200">
|
|
540
|
+
Balanced across {safeOwnersCount} owners
|
|
541
|
+
</p>
|
|
542
|
+
</div>
|
|
543
|
+
<div className="rounded-2xl border border-slate-800/80 bg-slate-950/60 p-4">
|
|
544
|
+
<div className="flex items-center gap-2 text-xs uppercase tracking-widest text-slate-400">
|
|
545
|
+
<Layers className="h-4 w-4 text-slate-300" /> Module matrix
|
|
546
|
+
</div>
|
|
547
|
+
<p className="mt-2 text-xl font-semibold text-white">
|
|
548
|
+
{safeModules.length} modules tracked
|
|
549
|
+
</p>
|
|
550
|
+
<p className="mt-1 text-xs text-slate-400">
|
|
551
|
+
Quorum pipelines: {Math.max(1, safeThreshold)} • Automation ready
|
|
552
|
+
</p>
|
|
553
|
+
<ul className="mt-3 space-y-2 text-xs text-slate-300">
|
|
554
|
+
{safeModules.length ? (
|
|
555
|
+
safeModules.slice(0, 4).map((module) => (
|
|
556
|
+
<li
|
|
557
|
+
key={module}
|
|
558
|
+
className="flex items-center justify-between rounded-lg border border-slate-800/80 bg-slate-900/60 px-3 py-2"
|
|
559
|
+
>
|
|
560
|
+
<span className="break-all font-mono text-[11px] text-emerald-300">
|
|
561
|
+
{module}
|
|
562
|
+
</span>
|
|
563
|
+
<span className="text-[11px] text-slate-500">Guarded</span>
|
|
564
|
+
</li>
|
|
565
|
+
))
|
|
566
|
+
) : (
|
|
567
|
+
<li className="rounded-lg border border-dashed border-slate-700 bg-slate-950/40 px-3 py-2 text-slate-500">
|
|
568
|
+
Enable a Safe module to orchestrate automation pipelines.
|
|
569
|
+
</li>
|
|
570
|
+
)}
|
|
571
|
+
</ul>
|
|
572
|
+
{safeModules.length > 4 && (
|
|
573
|
+
<p className="mt-2 text-[11px] text-slate-500">
|
|
574
|
+
+{safeModules.length - 4} additional modules tracked
|
|
575
|
+
</p>
|
|
576
|
+
)}
|
|
577
|
+
</div>
|
|
578
|
+
</div>
|
|
579
|
+
<div className="grid gap-4 lg:grid-cols-2">
|
|
580
|
+
<div className="rounded-2xl border border-slate-800/80 bg-slate-950/60 p-4">
|
|
581
|
+
<div className="flex items-center justify-between">
|
|
582
|
+
<div className="flex items-center gap-2 text-xs uppercase tracking-widest text-slate-400">
|
|
583
|
+
<Clock3 className="h-4 w-4 text-emerald-300" /> Hold policy window
|
|
584
|
+
</div>
|
|
585
|
+
<span className={`text-[11px] font-semibold ${holdStatusColor}`}>{holdStatus}</span>
|
|
586
|
+
</div>
|
|
587
|
+
<div className="mt-3 space-y-3 text-xs text-slate-300">
|
|
588
|
+
<p>
|
|
589
|
+
Local window: {holdWindow ?? '—'}h • Global max:{' '}
|
|
590
|
+
{globalHoldWindow ?? '—'}h
|
|
591
|
+
</p>
|
|
592
|
+
<div className="flex flex-wrap gap-3 text-[11px] text-slate-400">
|
|
593
|
+
<span className="rounded-full border border-emerald-400/40 px-2 py-0.5 text-emerald-300">
|
|
594
|
+
{holdPending} pending
|
|
595
|
+
</span>
|
|
596
|
+
<span className="rounded-full border border-slate-700 px-2 py-0.5">
|
|
597
|
+
{holdExecuted} released
|
|
598
|
+
</span>
|
|
599
|
+
</div>
|
|
600
|
+
<p className="text-[11px] text-slate-500">
|
|
601
|
+
Updated {holdUpdatedAt ?? '—'}
|
|
602
|
+
</p>
|
|
603
|
+
</div>
|
|
604
|
+
{safeTelemetryError && (
|
|
605
|
+
<p className="mt-3 text-[11px] text-red-400">{safeTelemetryError}</p>
|
|
606
|
+
)}
|
|
607
|
+
</div>
|
|
608
|
+
<div className="rounded-2xl border border-slate-800/80 bg-slate-950/60 p-4">
|
|
609
|
+
<div className="flex items-center gap-2 text-xs uppercase tracking-widest text-slate-400">
|
|
610
|
+
<Users className="h-4 w-4 text-slate-300" /> Delegate roster
|
|
611
|
+
</div>
|
|
612
|
+
<ul className="mt-3 space-y-3 text-xs text-slate-300">
|
|
613
|
+
{safeDelegates.length ? (
|
|
614
|
+
safeDelegates.map((delegate) => (
|
|
615
|
+
<li
|
|
616
|
+
key={delegate.address}
|
|
617
|
+
className="rounded-lg border border-slate-800/80 bg-slate-900/60 p-3"
|
|
618
|
+
>
|
|
619
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
620
|
+
<span className="break-words font-medium text-white">
|
|
621
|
+
{delegate.label}
|
|
622
|
+
</span>
|
|
623
|
+
<span className="break-all font-mono text-[11px] text-emerald-300">
|
|
624
|
+
{delegate.address}
|
|
625
|
+
</span>
|
|
626
|
+
</div>
|
|
627
|
+
<p className="mt-2 text-[11px] text-slate-500">
|
|
628
|
+
Active since {new Date(delegate.since).toLocaleString()}
|
|
629
|
+
</p>
|
|
630
|
+
</li>
|
|
631
|
+
))
|
|
632
|
+
) : (
|
|
633
|
+
<li className="rounded-lg border border-dashed border-slate-700 bg-slate-950/40 p-3 text-slate-500">
|
|
634
|
+
Delegate metadata populates once a Safe is connected.
|
|
635
|
+
</li>
|
|
636
|
+
)}
|
|
637
|
+
</ul>
|
|
638
|
+
</div>
|
|
639
|
+
</div>
|
|
640
|
+
</div>
|
|
641
|
+
) : (
|
|
642
|
+
<div className="mt-4 rounded-2xl border border-dashed border-slate-700 bg-slate-950/40 p-6 text-sm text-slate-400">
|
|
643
|
+
Connect a Safe to unlock quorum tracking, module analytics, and opcode-aware
|
|
644
|
+
guardrails.
|
|
645
|
+
</div>
|
|
646
|
+
)}
|
|
647
|
+
</section>
|
|
648
|
+
</div>
|
|
649
|
+
</div>
|
|
650
|
+
);
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
export default Dashboard;
|