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.
Files changed (606) hide show
  1. package/.eslintrc.cjs +24 -0
  2. package/.gnoman/contracts.json +4094 -0
  3. package/.gnoman/exec_package/runtime-debug.jsonl +45 -0
  4. package/.gnoman/holds.sqlite +0 -0
  5. package/.gnoman/license.json +7 -0
  6. package/.gnoman/safes.json +37 -0
  7. package/.gnoman/vanity-jobs.json +67 -0
  8. package/.gnoman/wallets.db +0 -0
  9. package/.prettierrc.json +6 -0
  10. package/CODex_TASKS.md +124 -0
  11. package/LICENSE.md +164 -0
  12. package/README.md +95 -0
  13. package/assets/GnoLogo.jpg +0 -0
  14. package/assets/self.png +0 -0
  15. package/backend/controllers/contractController.ts +49 -0
  16. package/backend/controllers/devToolsController.ts +76 -0
  17. package/backend/controllers/etherscanController.ts +59 -0
  18. package/backend/controllers/historyController.ts +7 -0
  19. package/backend/controllers/keyringController.ts +134 -0
  20. package/backend/controllers/robinhoodController.ts +80 -0
  21. package/backend/controllers/safeController.ts +167 -0
  22. package/backend/controllers/sandboxController.ts +63 -0
  23. package/backend/controllers/settingsController.ts +38 -0
  24. package/backend/controllers/walletController.ts +151 -0
  25. package/backend/index.ts +133 -0
  26. package/backend/licenses/license_public.pem +3 -0
  27. package/backend/licenses/verify_license.py +43 -0
  28. package/backend/routes/contractRoutes.ts +11 -0
  29. package/backend/routes/devToolsRoutes.ts +11 -0
  30. package/backend/routes/etherscanRoutes.ts +11 -0
  31. package/backend/routes/historyRoutes.ts +8 -0
  32. package/backend/routes/keyringRoutes.ts +25 -0
  33. package/backend/routes/licenseRoutes.ts +35 -0
  34. package/backend/routes/robinhoodRoutes.ts +22 -0
  35. package/backend/routes/runtimeRoutes.ts +29 -0
  36. package/backend/routes/safeRoutes.ts +28 -0
  37. package/backend/routes/sandboxRoutes.ts +17 -0
  38. package/backend/routes/settingsRoutes.ts +14 -0
  39. package/backend/routes/walletRoutes.ts +21 -0
  40. package/backend/services/chainlinkService.ts +65 -0
  41. package/backend/services/contractRegistryService.ts +205 -0
  42. package/backend/services/devToolsService.ts +251 -0
  43. package/backend/services/diagnosticsService.ts +350 -0
  44. package/backend/services/etherscanService.ts +152 -0
  45. package/backend/services/historyService.ts +89 -0
  46. package/backend/services/keyringAccessor.ts +4 -0
  47. package/backend/services/licenseService.ts +163 -0
  48. package/backend/services/onchain/abiRegistry.ts +57 -0
  49. package/backend/services/onchain/chainlinkClient.ts +56 -0
  50. package/backend/services/onchain/errors.ts +16 -0
  51. package/backend/services/onchain/etherscanClient.ts +94 -0
  52. package/backend/services/onchain/index.ts +76 -0
  53. package/backend/services/onchain/tenderlyRpcClient.ts +74 -0
  54. package/backend/services/onchain/types.ts +33 -0
  55. package/backend/services/onchainAutomationService.ts +424 -0
  56. package/backend/services/robinhood/auth.ts +42 -0
  57. package/backend/services/robinhood/client.ts +123 -0
  58. package/backend/services/robinhood/integrationService.ts +140 -0
  59. package/backend/services/robinhood/provider.ts +22 -0
  60. package/backend/services/robinhood/unofficialClient.ts +66 -0
  61. package/backend/services/rpcService.ts +44 -0
  62. package/backend/services/runtimeTelemetryService.ts +158 -0
  63. package/backend/services/safeConfigRepository.ts +205 -0
  64. package/backend/services/safeService.ts +588 -0
  65. package/backend/services/sandboxService.ts +157 -0
  66. package/backend/services/secureSettingsService.ts +45 -0
  67. package/backend/services/transactionHoldService.ts +223 -0
  68. package/backend/services/vanityService.ts +293 -0
  69. package/backend/services/walletService.ts +290 -0
  70. package/backend/services/walletStore.ts +179 -0
  71. package/backend/types/express-async-handler.d.ts +13 -0
  72. package/backend/types/keyring.d.ts +19 -0
  73. package/backend/utils/abiResolver.ts +208 -0
  74. package/backend/utils/http.ts +6 -0
  75. package/backend/utils/secretsResolver.ts +150 -0
  76. package/backend/utils/signer.ts +11 -0
  77. package/backend/workers/vanityWorker.ts +76 -0
  78. package/capacitor.config.ts +13 -0
  79. package/cli/gnoman.ts +424 -0
  80. package/contracts/OracleConsumer.sol +20 -0
  81. package/contracts/PriceFeedConsumer.sol +22 -0
  82. package/dist/backend/backend/controllers/contractController.js +41 -0
  83. package/dist/backend/backend/controllers/contractController.js.map +1 -0
  84. package/dist/backend/backend/controllers/devToolsController.js +63 -0
  85. package/dist/backend/backend/controllers/devToolsController.js.map +1 -0
  86. package/dist/backend/backend/controllers/etherscanController.js +53 -0
  87. package/dist/backend/backend/controllers/etherscanController.js.map +1 -0
  88. package/dist/backend/backend/controllers/historyController.js +12 -0
  89. package/dist/backend/backend/controllers/historyController.js.map +1 -0
  90. package/dist/backend/backend/controllers/keyringController.js +126 -0
  91. package/dist/backend/backend/controllers/keyringController.js.map +1 -0
  92. package/dist/backend/backend/controllers/robinhoodController.js +69 -0
  93. package/dist/backend/backend/controllers/robinhoodController.js.map +1 -0
  94. package/dist/backend/backend/controllers/safeController.js +137 -0
  95. package/dist/backend/backend/controllers/safeController.js.map +1 -0
  96. package/dist/backend/backend/controllers/sandboxController.js +48 -0
  97. package/dist/backend/backend/controllers/sandboxController.js.map +1 -0
  98. package/dist/backend/backend/controllers/settingsController.js +34 -0
  99. package/dist/backend/backend/controllers/settingsController.js.map +1 -0
  100. package/dist/backend/backend/controllers/walletController.js +140 -0
  101. package/dist/backend/backend/controllers/walletController.js.map +1 -0
  102. package/dist/backend/backend/index.js +119 -0
  103. package/dist/backend/backend/index.js.map +1 -0
  104. package/dist/backend/backend/routes/contractRoutes.js +44 -0
  105. package/dist/backend/backend/routes/contractRoutes.js.map +1 -0
  106. package/dist/backend/backend/routes/devToolsRoutes.js +44 -0
  107. package/dist/backend/backend/routes/devToolsRoutes.js.map +1 -0
  108. package/dist/backend/backend/routes/etherscanRoutes.js +44 -0
  109. package/dist/backend/backend/routes/etherscanRoutes.js.map +1 -0
  110. package/dist/backend/backend/routes/historyRoutes.js +41 -0
  111. package/dist/backend/backend/routes/historyRoutes.js.map +1 -0
  112. package/dist/backend/backend/routes/keyringRoutes.js +18 -0
  113. package/dist/backend/backend/routes/keyringRoutes.js.map +1 -0
  114. package/dist/backend/backend/routes/licenseRoutes.js +30 -0
  115. package/dist/backend/backend/routes/licenseRoutes.js.map +1 -0
  116. package/dist/backend/backend/routes/robinhoodRoutes.js +14 -0
  117. package/dist/backend/backend/routes/robinhoodRoutes.js.map +1 -0
  118. package/dist/backend/backend/routes/runtimeRoutes.js +26 -0
  119. package/dist/backend/backend/routes/runtimeRoutes.js.map +1 -0
  120. package/dist/backend/backend/routes/safeRoutes.js +61 -0
  121. package/dist/backend/backend/routes/safeRoutes.js.map +1 -0
  122. package/dist/backend/backend/routes/sandboxRoutes.js +50 -0
  123. package/dist/backend/backend/routes/sandboxRoutes.js.map +1 -0
  124. package/dist/backend/backend/routes/settingsRoutes.js +10 -0
  125. package/dist/backend/backend/routes/settingsRoutes.js.map +1 -0
  126. package/dist/backend/backend/routes/walletRoutes.js +54 -0
  127. package/dist/backend/backend/routes/walletRoutes.js.map +1 -0
  128. package/dist/backend/backend/services/chainlinkService.js +48 -0
  129. package/dist/backend/backend/services/chainlinkService.js.map +1 -0
  130. package/dist/backend/backend/services/contractRegistryService.js +138 -0
  131. package/dist/backend/backend/services/contractRegistryService.js.map +1 -0
  132. package/dist/backend/backend/services/devToolsService.js +213 -0
  133. package/dist/backend/backend/services/devToolsService.js.map +1 -0
  134. package/dist/backend/backend/services/diagnosticsService.js +286 -0
  135. package/dist/backend/backend/services/diagnosticsService.js.map +1 -0
  136. package/dist/backend/backend/services/etherscanService.js +125 -0
  137. package/dist/backend/backend/services/etherscanService.js.map +1 -0
  138. package/dist/backend/backend/services/historyService.js +75 -0
  139. package/dist/backend/backend/services/historyService.js.map +1 -0
  140. package/dist/backend/backend/services/keyringAccessor.js +40 -0
  141. package/dist/backend/backend/services/keyringAccessor.js.map +1 -0
  142. package/dist/backend/backend/services/licenseService.js +130 -0
  143. package/dist/backend/backend/services/licenseService.js.map +1 -0
  144. package/dist/backend/backend/services/onchain/abiRegistry.js +47 -0
  145. package/dist/backend/backend/services/onchain/abiRegistry.js.map +1 -0
  146. package/dist/backend/backend/services/onchain/chainlinkClient.js +43 -0
  147. package/dist/backend/backend/services/onchain/chainlinkClient.js.map +1 -0
  148. package/dist/backend/backend/services/onchain/errors.js +13 -0
  149. package/dist/backend/backend/services/onchain/errors.js.map +1 -0
  150. package/dist/backend/backend/services/onchain/etherscanClient.js +82 -0
  151. package/dist/backend/backend/services/onchain/etherscanClient.js.map +1 -0
  152. package/dist/backend/backend/services/onchain/index.js +79 -0
  153. package/dist/backend/backend/services/onchain/index.js.map +1 -0
  154. package/dist/backend/backend/services/onchain/tenderlyRpcClient.js +60 -0
  155. package/dist/backend/backend/services/onchain/tenderlyRpcClient.js.map +1 -0
  156. package/dist/backend/backend/services/onchain/types.js +14 -0
  157. package/dist/backend/backend/services/onchain/types.js.map +1 -0
  158. package/dist/backend/backend/services/onchainAutomationService.js +316 -0
  159. package/dist/backend/backend/services/onchainAutomationService.js.map +1 -0
  160. package/dist/backend/backend/services/robinhood/auth.js +26 -0
  161. package/dist/backend/backend/services/robinhood/auth.js.map +1 -0
  162. package/dist/backend/backend/services/robinhood/client.js +73 -0
  163. package/dist/backend/backend/services/robinhood/client.js.map +1 -0
  164. package/dist/backend/backend/services/robinhood/integrationService.js +119 -0
  165. package/dist/backend/backend/services/robinhood/integrationService.js.map +1 -0
  166. package/dist/backend/backend/services/robinhood/provider.js +17 -0
  167. package/dist/backend/backend/services/robinhood/provider.js.map +1 -0
  168. package/dist/backend/backend/services/robinhood/unofficialClient.js +61 -0
  169. package/dist/backend/backend/services/robinhood/unofficialClient.js.map +1 -0
  170. package/dist/backend/backend/services/rpcService.js +48 -0
  171. package/dist/backend/backend/services/rpcService.js.map +1 -0
  172. package/dist/backend/backend/services/runtimeTelemetryService.js +96 -0
  173. package/dist/backend/backend/services/runtimeTelemetryService.js.map +1 -0
  174. package/dist/backend/backend/services/safeConfigRepository.js +147 -0
  175. package/dist/backend/backend/services/safeConfigRepository.js.map +1 -0
  176. package/dist/backend/backend/services/safeService.js +527 -0
  177. package/dist/backend/backend/services/safeService.js.map +1 -0
  178. package/dist/backend/backend/services/sandboxService.js +135 -0
  179. package/dist/backend/backend/services/sandboxService.js.map +1 -0
  180. package/dist/backend/backend/services/secureSettingsService.js +50 -0
  181. package/dist/backend/backend/services/secureSettingsService.js.map +1 -0
  182. package/dist/backend/backend/services/transactionHoldService.js +184 -0
  183. package/dist/backend/backend/services/transactionHoldService.js.map +1 -0
  184. package/dist/backend/backend/services/vanityService.js +235 -0
  185. package/dist/backend/backend/services/vanityService.js.map +1 -0
  186. package/dist/backend/backend/services/walletService.js +202 -0
  187. package/dist/backend/backend/services/walletService.js.map +1 -0
  188. package/dist/backend/backend/services/walletStore.js +132 -0
  189. package/dist/backend/backend/services/walletStore.js.map +1 -0
  190. package/dist/backend/backend/utils/abiResolver.js +182 -0
  191. package/dist/backend/backend/utils/abiResolver.js.map +1 -0
  192. package/dist/backend/backend/utils/http.js +12 -0
  193. package/dist/backend/backend/utils/http.js.map +1 -0
  194. package/dist/backend/backend/utils/secretsResolver.js +137 -0
  195. package/dist/backend/backend/utils/secretsResolver.js.map +1 -0
  196. package/dist/backend/backend/utils/signer.js +15 -0
  197. package/dist/backend/backend/utils/signer.js.map +1 -0
  198. package/dist/backend/backend/workers/vanityWorker.js +63 -0
  199. package/dist/backend/backend/workers/vanityWorker.js.map +1 -0
  200. package/dist/backend/cli/gnoman.js +387 -0
  201. package/dist/backend/cli/gnoman.js.map +1 -0
  202. package/dist/backend/modules/sandbox/abiLoader.js +78 -0
  203. package/dist/backend/modules/sandbox/abiLoader.js.map +1 -0
  204. package/dist/backend/modules/sandbox/contractSimulator.js +205 -0
  205. package/dist/backend/modules/sandbox/contractSimulator.js.map +1 -0
  206. package/dist/backend/modules/sandbox/formBuilder.js +14 -0
  207. package/dist/backend/modules/sandbox/formBuilder.js.map +1 -0
  208. package/dist/backend/modules/sandbox/index.js +24 -0
  209. package/dist/backend/modules/sandbox/index.js.map +1 -0
  210. package/dist/backend/modules/sandbox/localFork.js +103 -0
  211. package/dist/backend/modules/sandbox/localFork.js.map +1 -0
  212. package/dist/backend/modules/sandbox/sandboxManager.js +130 -0
  213. package/dist/backend/modules/sandbox/sandboxManager.js.map +1 -0
  214. package/dist/backend/modules/sandbox/types.js +3 -0
  215. package/dist/backend/modules/sandbox/types.js.map +1 -0
  216. package/dist/backend/src/core/backends/fileBackend.js +136 -0
  217. package/dist/backend/src/core/backends/fileBackend.js.map +1 -0
  218. package/dist/backend/src/core/backends/memoryBackend.js +26 -0
  219. package/dist/backend/src/core/backends/memoryBackend.js.map +1 -0
  220. package/dist/backend/src/core/backends/systemBackend.js +86 -0
  221. package/dist/backend/src/core/backends/systemBackend.js.map +1 -0
  222. package/dist/backend/src/core/backends/types.js +12 -0
  223. package/dist/backend/src/core/backends/types.js.map +1 -0
  224. package/dist/backend/src/core/keyringManager.js +178 -0
  225. package/dist/backend/src/core/keyringManager.js.map +1 -0
  226. package/dist/backend/src/utils/abiResolver.js +180 -0
  227. package/dist/backend/src/utils/abiResolver.js.map +1 -0
  228. package/dist/backend/src/utils/runtimeObservability.js +78 -0
  229. package/dist/backend/src/utils/runtimeObservability.js.map +1 -0
  230. package/dist/backend/src/utils/secretsResolver.js +138 -0
  231. package/dist/backend/src/utils/secretsResolver.js.map +1 -0
  232. package/dist/cli/backend/services/diagnosticsService.js +286 -0
  233. package/dist/cli/backend/services/diagnosticsService.js.map +1 -0
  234. package/dist/cli/backend/services/keyringAccessor.js +40 -0
  235. package/dist/cli/backend/services/keyringAccessor.js.map +1 -0
  236. package/dist/cli/backend/services/rpcService.js +48 -0
  237. package/dist/cli/backend/services/rpcService.js.map +1 -0
  238. package/dist/cli/backend/services/runtimeTelemetryService.js +96 -0
  239. package/dist/cli/backend/services/runtimeTelemetryService.js.map +1 -0
  240. package/dist/cli/backend/services/walletService.js +202 -0
  241. package/dist/cli/backend/services/walletService.js.map +1 -0
  242. package/dist/cli/backend/services/walletStore.js +132 -0
  243. package/dist/cli/backend/services/walletStore.js.map +1 -0
  244. package/dist/cli/backend/utils/http.js +12 -0
  245. package/dist/cli/backend/utils/http.js.map +1 -0
  246. package/dist/cli/backend/utils/secretsResolver.js +137 -0
  247. package/dist/cli/backend/utils/secretsResolver.js.map +1 -0
  248. package/dist/cli/cli/gnoman.js +387 -0
  249. package/dist/cli/cli/gnoman.js.map +1 -0
  250. package/dist/cli/src/core/backends/fileBackend.js +136 -0
  251. package/dist/cli/src/core/backends/fileBackend.js.map +1 -0
  252. package/dist/cli/src/core/backends/memoryBackend.js +26 -0
  253. package/dist/cli/src/core/backends/memoryBackend.js.map +1 -0
  254. package/dist/cli/src/core/backends/systemBackend.js +86 -0
  255. package/dist/cli/src/core/backends/systemBackend.js.map +1 -0
  256. package/dist/cli/src/core/backends/types.js +12 -0
  257. package/dist/cli/src/core/backends/types.js.map +1 -0
  258. package/dist/cli/src/core/keyringManager.js +178 -0
  259. package/dist/cli/src/core/keyringManager.js.map +1 -0
  260. package/dist/cli/src/utils/abiResolver.js +180 -0
  261. package/dist/cli/src/utils/abiResolver.js.map +1 -0
  262. package/dist/cli/src/utils/runtimeObservability.js +78 -0
  263. package/dist/cli/src/utils/runtimeObservability.js.map +1 -0
  264. package/dist/cli/src/utils/secretsResolver.js +138 -0
  265. package/dist/cli/src/utils/secretsResolver.js.map +1 -0
  266. package/dist/main/backend/services/keyringAccessor.js +40 -0
  267. package/dist/main/backend/services/keyringAccessor.js.map +1 -0
  268. package/dist/main/backend/utils/http.js +12 -0
  269. package/dist/main/backend/utils/http.js.map +1 -0
  270. package/dist/main/main/ipcHandlers/index.js +26 -0
  271. package/dist/main/main/ipcHandlers/index.js.map +1 -0
  272. package/dist/main/main/keyring/keyringmanager.js +101 -0
  273. package/dist/main/main/keyring/keyringmanager.js.map +1 -0
  274. package/dist/main/main/main.js +224 -0
  275. package/dist/main/main/main.js.map +1 -0
  276. package/dist/main/main/preload/index.js +19 -0
  277. package/dist/main/main/preload/index.js.map +1 -0
  278. package/dist/main/main/preload/licenseBridge.js +105 -0
  279. package/dist/main/main/preload/licenseBridge.js.map +1 -0
  280. package/dist/main/src/core/backends/fileBackend.js +136 -0
  281. package/dist/main/src/core/backends/fileBackend.js.map +1 -0
  282. package/dist/main/src/core/backends/memoryBackend.js +26 -0
  283. package/dist/main/src/core/backends/memoryBackend.js.map +1 -0
  284. package/dist/main/src/core/backends/systemBackend.js +86 -0
  285. package/dist/main/src/core/backends/systemBackend.js.map +1 -0
  286. package/dist/main/src/core/backends/types.js +12 -0
  287. package/dist/main/src/core/backends/types.js.map +1 -0
  288. package/dist/main/src/core/keyringManager.js +178 -0
  289. package/dist/main/src/core/keyringManager.js.map +1 -0
  290. package/dist/main/src/utils/abiResolver.js +180 -0
  291. package/dist/main/src/utils/abiResolver.js.map +1 -0
  292. package/dist/main/src/utils/runtimeObservability.js +78 -0
  293. package/dist/main/src/utils/runtimeObservability.js.map +1 -0
  294. package/dist/main/src/utils/secretsResolver.js +138 -0
  295. package/dist/main/src/utils/secretsResolver.js.map +1 -0
  296. package/docs/development-guide.md +203 -0
  297. package/docs/etherscan-chainlink-integration.md +44 -0
  298. package/docs/gnoman-20-user-manual-STANDARD-PRINT-READY.pdf +0 -0
  299. package/docs/gnoman-20-user-manual-STANDARD.pdf +0 -0
  300. package/docs/license-dev-guide.md +106 -0
  301. package/docs/robinhood-integration.md +30 -0
  302. package/docs/system-audit-gpt-guide.md +208 -0
  303. package/docs/system-robustness-audit.md +50 -0
  304. package/docs/user-guide.md +73 -0
  305. package/docs/wiki/development-guide.md +203 -0
  306. package/docs/wiki/license-dev-guide.md +106 -0
  307. package/docs/wiki/user-guide.md +73 -0
  308. package/eslint.config.js +85 -0
  309. package/gnoman2.0/.eslintrc.cjs +24 -0
  310. package/gnoman2.0/.prettierrc.json +6 -0
  311. package/gnoman2.0/CODex_TASKS.md +124 -0
  312. package/gnoman2.0/LICENSE.md +164 -0
  313. package/gnoman2.0/README.md +95 -0
  314. package/gnoman2.0/assets/GnoLogo.jpg +0 -0
  315. package/gnoman2.0/assets/self.png +0 -0
  316. package/gnoman2.0/backend/controllers/contractController.ts +49 -0
  317. package/gnoman2.0/backend/controllers/devToolsController.ts +76 -0
  318. package/gnoman2.0/backend/controllers/etherscanController.ts +59 -0
  319. package/gnoman2.0/backend/controllers/historyController.ts +7 -0
  320. package/gnoman2.0/backend/controllers/keyringController.ts +134 -0
  321. package/gnoman2.0/backend/controllers/robinhoodController.ts +80 -0
  322. package/gnoman2.0/backend/controllers/safeController.ts +167 -0
  323. package/gnoman2.0/backend/controllers/sandboxController.ts +63 -0
  324. package/gnoman2.0/backend/controllers/settingsController.ts +38 -0
  325. package/gnoman2.0/backend/controllers/walletController.ts +151 -0
  326. package/gnoman2.0/backend/index.ts +133 -0
  327. package/gnoman2.0/backend/licenses/license_public.pem +3 -0
  328. package/gnoman2.0/backend/licenses/verify_license.py +43 -0
  329. package/gnoman2.0/backend/routes/contractRoutes.ts +11 -0
  330. package/gnoman2.0/backend/routes/devToolsRoutes.ts +11 -0
  331. package/gnoman2.0/backend/routes/etherscanRoutes.ts +11 -0
  332. package/gnoman2.0/backend/routes/historyRoutes.ts +8 -0
  333. package/gnoman2.0/backend/routes/keyringRoutes.ts +25 -0
  334. package/gnoman2.0/backend/routes/licenseRoutes.ts +35 -0
  335. package/gnoman2.0/backend/routes/robinhoodRoutes.ts +22 -0
  336. package/gnoman2.0/backend/routes/runtimeRoutes.ts +29 -0
  337. package/gnoman2.0/backend/routes/safeRoutes.ts +28 -0
  338. package/gnoman2.0/backend/routes/sandboxRoutes.ts +17 -0
  339. package/gnoman2.0/backend/routes/settingsRoutes.ts +14 -0
  340. package/gnoman2.0/backend/routes/walletRoutes.ts +21 -0
  341. package/gnoman2.0/backend/services/chainlinkService.ts +65 -0
  342. package/gnoman2.0/backend/services/contractRegistryService.ts +205 -0
  343. package/gnoman2.0/backend/services/devToolsService.ts +251 -0
  344. package/gnoman2.0/backend/services/diagnosticsService.ts +350 -0
  345. package/gnoman2.0/backend/services/etherscanService.ts +152 -0
  346. package/gnoman2.0/backend/services/historyService.ts +89 -0
  347. package/gnoman2.0/backend/services/keyringAccessor.ts +4 -0
  348. package/gnoman2.0/backend/services/licenseService.ts +163 -0
  349. package/gnoman2.0/backend/services/onchain/abiRegistry.ts +57 -0
  350. package/gnoman2.0/backend/services/onchain/chainlinkClient.ts +56 -0
  351. package/gnoman2.0/backend/services/onchain/errors.ts +16 -0
  352. package/gnoman2.0/backend/services/onchain/etherscanClient.ts +94 -0
  353. package/gnoman2.0/backend/services/onchain/index.ts +76 -0
  354. package/gnoman2.0/backend/services/onchain/tenderlyRpcClient.ts +74 -0
  355. package/gnoman2.0/backend/services/onchain/types.ts +33 -0
  356. package/gnoman2.0/backend/services/onchainAutomationService.ts +424 -0
  357. package/gnoman2.0/backend/services/robinhood/auth.ts +42 -0
  358. package/gnoman2.0/backend/services/robinhood/client.ts +123 -0
  359. package/gnoman2.0/backend/services/robinhood/integrationService.ts +140 -0
  360. package/gnoman2.0/backend/services/robinhood/provider.ts +22 -0
  361. package/gnoman2.0/backend/services/robinhood/unofficialClient.ts +66 -0
  362. package/gnoman2.0/backend/services/rpcService.ts +44 -0
  363. package/gnoman2.0/backend/services/runtimeTelemetryService.ts +158 -0
  364. package/gnoman2.0/backend/services/safeConfigRepository.ts +205 -0
  365. package/gnoman2.0/backend/services/safeService.ts +588 -0
  366. package/gnoman2.0/backend/services/sandboxService.ts +157 -0
  367. package/gnoman2.0/backend/services/secureSettingsService.ts +45 -0
  368. package/gnoman2.0/backend/services/transactionHoldService.ts +223 -0
  369. package/gnoman2.0/backend/services/vanityService.ts +293 -0
  370. package/gnoman2.0/backend/services/walletService.ts +290 -0
  371. package/gnoman2.0/backend/services/walletStore.ts +179 -0
  372. package/gnoman2.0/backend/types/express-async-handler.d.ts +13 -0
  373. package/gnoman2.0/backend/types/keyring.d.ts +19 -0
  374. package/gnoman2.0/backend/utils/abiResolver.ts +208 -0
  375. package/gnoman2.0/backend/utils/http.ts +6 -0
  376. package/gnoman2.0/backend/utils/secretsResolver.ts +150 -0
  377. package/gnoman2.0/backend/utils/signer.ts +11 -0
  378. package/gnoman2.0/backend/workers/vanityWorker.ts +76 -0
  379. package/gnoman2.0/capacitor.config.ts +13 -0
  380. package/gnoman2.0/cli/gnoman.ts +424 -0
  381. package/gnoman2.0/contracts/OracleConsumer.sol +20 -0
  382. package/gnoman2.0/contracts/PriceFeedConsumer.sol +22 -0
  383. package/gnoman2.0/docs/development-guide.md +203 -0
  384. package/gnoman2.0/docs/etherscan-chainlink-integration.md +44 -0
  385. package/gnoman2.0/docs/gnoman-20-user-manual-STANDARD-PRINT-READY.pdf +0 -0
  386. package/gnoman2.0/docs/gnoman-20-user-manual-STANDARD.pdf +0 -0
  387. package/gnoman2.0/docs/license-dev-guide.md +106 -0
  388. package/gnoman2.0/docs/robinhood-integration.md +30 -0
  389. package/gnoman2.0/docs/system-audit-gpt-guide.md +208 -0
  390. package/gnoman2.0/docs/system-robustness-audit.md +50 -0
  391. package/gnoman2.0/docs/user-guide.md +73 -0
  392. package/gnoman2.0/docs/wiki/development-guide.md +203 -0
  393. package/gnoman2.0/docs/wiki/license-dev-guide.md +106 -0
  394. package/gnoman2.0/docs/wiki/user-guide.md +73 -0
  395. package/gnoman2.0/eslint.config.js +85 -0
  396. package/gnoman2.0/gnomon/__init__.py +0 -0
  397. package/gnoman2.0/gnomon/api/__init__.py +0 -0
  398. package/gnoman2.0/gnomon/api/etherscan_tracker.py +72 -0
  399. package/gnoman2.0/gnomon/core/__init__.py +0 -0
  400. package/gnoman2.0/gnomon/core/safe_manager.py +111 -0
  401. package/gnoman2.0/gnomon/tests/test_abi_resolver.py +181 -0
  402. package/gnoman2.0/gnomon/tests/test_safe_persistence_and_etherscan.py +97 -0
  403. package/gnoman2.0/gnomon/utils/__init__.py +5 -0
  404. package/gnoman2.0/gnomon/utils/abi_resolver.py +255 -0
  405. package/gnoman2.0/ios/ExportOptions.plist +16 -0
  406. package/gnoman2.0/ios/README.md +33 -0
  407. package/gnoman2.0/jest.config.ts +18 -0
  408. package/gnoman2.0/keyring/__init__.py +17 -0
  409. package/gnoman2.0/licensingServer/package.json +23 -0
  410. package/gnoman2.0/licensingServer/src/config/keys.ts +84 -0
  411. package/gnoman2.0/licensingServer/src/index.ts +30 -0
  412. package/gnoman2.0/licensingServer/src/lib/canonicalize.ts +5 -0
  413. package/gnoman2.0/licensingServer/src/lib/crypto.ts +25 -0
  414. package/gnoman2.0/licensingServer/src/lib/validate.ts +62 -0
  415. package/gnoman2.0/licensingServer/src/middleware/auth.ts +20 -0
  416. package/gnoman2.0/licensingServer/src/routes/licenses.ts +110 -0
  417. package/gnoman2.0/licensingServer/tsconfig.json +12 -0
  418. package/gnoman2.0/main/ipcHandlers/index.ts +23 -0
  419. package/gnoman2.0/main/keyring/keyringmanager.ts +154 -0
  420. package/gnoman2.0/main/main.ts +234 -0
  421. package/gnoman2.0/main/preload/index.ts +31 -0
  422. package/gnoman2.0/main/preload/licenseBridge.ts +73 -0
  423. package/gnoman2.0/modules/sandbox/abiLoader.ts +78 -0
  424. package/gnoman2.0/modules/sandbox/contractSimulator.ts +241 -0
  425. package/gnoman2.0/modules/sandbox/formBuilder.ts +16 -0
  426. package/gnoman2.0/modules/sandbox/index.ts +6 -0
  427. package/gnoman2.0/modules/sandbox/localFork.ts +129 -0
  428. package/gnoman2.0/modules/sandbox/safe.abi.json +82 -0
  429. package/gnoman2.0/modules/sandbox/sandboxManager.ts +154 -0
  430. package/gnoman2.0/modules/sandbox/types.ts +84 -0
  431. package/gnoman2.0/modules/sandbox/ui/LogViewer.tsx +30 -0
  432. package/gnoman2.0/modules/sandbox/ui/ParameterForm.tsx +49 -0
  433. package/gnoman2.0/modules/sandbox/ui/SandboxPanel.tsx +568 -0
  434. package/gnoman2.0/package-lock.json +10904 -0
  435. package/gnoman2.0/package.json +82 -0
  436. package/gnoman2.0/renderer/components/LicenseScreen.tsx +134 -0
  437. package/gnoman2.0/renderer/index.html +12 -0
  438. package/gnoman2.0/renderer/package-lock.json +4104 -0
  439. package/gnoman2.0/renderer/package.json +35 -0
  440. package/gnoman2.0/renderer/postcss.config.cjs +6 -0
  441. package/gnoman2.0/renderer/src/App.tsx +229 -0
  442. package/gnoman2.0/renderer/src/context/KeyringContext.tsx +217 -0
  443. package/gnoman2.0/renderer/src/context/SafeContext.tsx +49 -0
  444. package/gnoman2.0/renderer/src/context/ThemeContext.tsx +60 -0
  445. package/gnoman2.0/renderer/src/context/WalletContext.tsx +50 -0
  446. package/gnoman2.0/renderer/src/context/main.tsx +18 -0
  447. package/gnoman2.0/renderer/src/main.tsx +18 -0
  448. package/gnoman2.0/renderer/src/pages/Contracts.tsx +482 -0
  449. package/gnoman2.0/renderer/src/pages/Dashboard.tsx +653 -0
  450. package/gnoman2.0/renderer/src/pages/DeveloperTools.tsx +270 -0
  451. package/gnoman2.0/renderer/src/pages/History.tsx +149 -0
  452. package/gnoman2.0/renderer/src/pages/Keyring.tsx +449 -0
  453. package/gnoman2.0/renderer/src/pages/Safes.tsx +1089 -0
  454. package/gnoman2.0/renderer/src/pages/Sandbox.tsx +146 -0
  455. package/gnoman2.0/renderer/src/pages/Settings.tsx +871 -0
  456. package/gnoman2.0/renderer/src/pages/Wallets.tsx +752 -0
  457. package/gnoman2.0/renderer/src/pages/WikiGuide.tsx +75 -0
  458. package/gnoman2.0/renderer/src/styles.css +32 -0
  459. package/gnoman2.0/renderer/src/types/gnoman.d.ts +9 -0
  460. package/gnoman2.0/renderer/src/types/license.ts +8 -0
  461. package/gnoman2.0/renderer/src/types/safevault.d.ts +17 -0
  462. package/gnoman2.0/renderer/src/utils/backend.ts +88 -0
  463. package/gnoman2.0/renderer/tailwind.config.cjs +8 -0
  464. package/gnoman2.0/renderer/tsconfig.json +13 -0
  465. package/gnoman2.0/renderer/tsconfig.node.json +9 -0
  466. package/gnoman2.0/renderer/vite.config.ts +19 -0
  467. package/gnoman2.0/requests/__init__.py +35 -0
  468. package/gnoman2.0/scripts/build-ios.sh +30 -0
  469. package/gnoman2.0/scripts/copyBackendAssets.js +24 -0
  470. package/gnoman2.0/scripts/copyRenderer.js +87 -0
  471. package/gnoman2.0/scripts/launchElectron.js +51 -0
  472. package/gnoman2.0/src/core/backends/fileBackend.ts +154 -0
  473. package/gnoman2.0/src/core/backends/memoryBackend.ts +27 -0
  474. package/gnoman2.0/src/core/backends/systemBackend.ts +66 -0
  475. package/gnoman2.0/src/core/backends/types.ts +17 -0
  476. package/gnoman2.0/src/core/keyringManager.ts +208 -0
  477. package/gnoman2.0/src/utils/abiCache/.gitkeep +0 -0
  478. package/gnoman2.0/src/utils/abiResolver.ts +200 -0
  479. package/gnoman2.0/src/utils/runtimeObservability.ts +110 -0
  480. package/gnoman2.0/src/utils/secretsResolver.ts +144 -0
  481. package/gnoman2.0/tests/chainlinkService.test.ts +32 -0
  482. package/gnoman2.0/tests/diagnosticsService.test.ts +68 -0
  483. package/gnoman2.0/tests/etherscanController.test.ts +99 -0
  484. package/gnoman2.0/tests/etherscanService.test.ts +116 -0
  485. package/gnoman2.0/tests/keyringManager.test.ts +135 -0
  486. package/gnoman2.0/tests/onchainToolkit.test.ts +71 -0
  487. package/gnoman2.0/tests/robinhoodClient.test.ts +54 -0
  488. package/gnoman2.0/tests/robinhoodController.test.ts +81 -0
  489. package/gnoman2.0/tests/robinhoodIntegrationService.test.ts +50 -0
  490. package/gnoman2.0/tests/safeServicePersistence.test.ts +81 -0
  491. package/gnoman2.0/tests/test_contract_sandbox/sandbox.test.js +407 -0
  492. package/gnoman2.0/tests/walletController.test.ts +57 -0
  493. package/gnoman2.0/tsconfig.backend.json +7 -0
  494. package/gnoman2.0/tsconfig.cli.json +7 -0
  495. package/gnoman2.0/tsconfig.json +18 -0
  496. package/gnoman2.0/tsconfig.main.json +7 -0
  497. package/gnomon/__init__.py +0 -0
  498. package/gnomon/__pycache__/__init__.cpython-310.pyc +0 -0
  499. package/gnomon/api/__init__.py +0 -0
  500. package/gnomon/api/__pycache__/__init__.cpython-310.pyc +0 -0
  501. package/gnomon/api/__pycache__/etherscan_tracker.cpython-310.pyc +0 -0
  502. package/gnomon/api/etherscan_tracker.py +72 -0
  503. package/gnomon/core/__init__.py +0 -0
  504. package/gnomon/core/safe_manager.py +111 -0
  505. package/gnomon/tests/__pycache__/test_safe_persistence_and_etherscan.cpython-310-pytest-8.3.3.pyc +0 -0
  506. package/gnomon/tests/test_abi_resolver.py +181 -0
  507. package/gnomon/tests/test_safe_persistence_and_etherscan.py +97 -0
  508. package/gnomon/utils/__init__.py +5 -0
  509. package/gnomon/utils/abi_resolver.py +255 -0
  510. package/ios/ExportOptions.plist +16 -0
  511. package/ios/README.md +33 -0
  512. package/jest.config.ts +18 -0
  513. package/keyring/__init__.py +17 -0
  514. package/launcher.sh +57 -0
  515. package/license.env +2 -0
  516. package/licensingServer/package.json +23 -0
  517. package/licensingServer/src/config/keys.ts +84 -0
  518. package/licensingServer/src/index.ts +30 -0
  519. package/licensingServer/src/lib/canonicalize.ts +5 -0
  520. package/licensingServer/src/lib/crypto.ts +25 -0
  521. package/licensingServer/src/lib/validate.ts +62 -0
  522. package/licensingServer/src/middleware/auth.ts +20 -0
  523. package/licensingServer/src/routes/licenses.ts +110 -0
  524. package/licensingServer/tsconfig.json +12 -0
  525. package/main/ipcHandlers/index.ts +23 -0
  526. package/main/keyring/keyringmanager.ts +154 -0
  527. package/main/main.ts +234 -0
  528. package/main/preload/index.ts +31 -0
  529. package/main/preload/licenseBridge.ts +73 -0
  530. package/modules/sandbox/abiLoader.ts +78 -0
  531. package/modules/sandbox/contractSimulator.ts +241 -0
  532. package/modules/sandbox/formBuilder.ts +16 -0
  533. package/modules/sandbox/index.ts +6 -0
  534. package/modules/sandbox/localFork.ts +129 -0
  535. package/modules/sandbox/safe.abi.json +82 -0
  536. package/modules/sandbox/sandboxManager.ts +154 -0
  537. package/modules/sandbox/types.ts +84 -0
  538. package/modules/sandbox/ui/LogViewer.tsx +30 -0
  539. package/modules/sandbox/ui/ParameterForm.tsx +49 -0
  540. package/modules/sandbox/ui/SandboxPanel.tsx +568 -0
  541. package/package.json +82 -0
  542. package/renderer/components/LicenseScreen.tsx +134 -0
  543. package/renderer/index.html +12 -0
  544. package/renderer/package-lock.json +4104 -0
  545. package/renderer/package.json +35 -0
  546. package/renderer/postcss.config.cjs +6 -0
  547. package/renderer/src/App.tsx +229 -0
  548. package/renderer/src/context/KeyringContext.tsx +217 -0
  549. package/renderer/src/context/SafeContext.tsx +49 -0
  550. package/renderer/src/context/ThemeContext.tsx +60 -0
  551. package/renderer/src/context/WalletContext.tsx +50 -0
  552. package/renderer/src/context/main.tsx +18 -0
  553. package/renderer/src/main.tsx +18 -0
  554. package/renderer/src/pages/Contracts.tsx +482 -0
  555. package/renderer/src/pages/Dashboard.tsx +653 -0
  556. package/renderer/src/pages/DeveloperTools.tsx +270 -0
  557. package/renderer/src/pages/History.tsx +149 -0
  558. package/renderer/src/pages/Keyring.tsx +449 -0
  559. package/renderer/src/pages/Safes.tsx +1089 -0
  560. package/renderer/src/pages/Sandbox.tsx +146 -0
  561. package/renderer/src/pages/Settings.tsx +871 -0
  562. package/renderer/src/pages/Wallets.tsx +752 -0
  563. package/renderer/src/pages/WikiGuide.tsx +75 -0
  564. package/renderer/src/styles.css +32 -0
  565. package/renderer/src/types/gnoman.d.ts +9 -0
  566. package/renderer/src/types/license.ts +8 -0
  567. package/renderer/src/types/safevault.d.ts +17 -0
  568. package/renderer/src/utils/backend.ts +88 -0
  569. package/renderer/tailwind.config.cjs +8 -0
  570. package/renderer/tsconfig.json +13 -0
  571. package/renderer/tsconfig.node.json +9 -0
  572. package/renderer/vite.config.ts +19 -0
  573. package/requests/__init__.py +35 -0
  574. package/requests/__pycache__/__init__.cpython-310.pyc +0 -0
  575. package/scripts/build-ios.sh +30 -0
  576. package/scripts/copyBackendAssets.js +24 -0
  577. package/scripts/copyRenderer.js +87 -0
  578. package/scripts/deployBackend.sh +24 -0
  579. package/scripts/launchElectron.js +51 -0
  580. package/src/core/backends/fileBackend.ts +154 -0
  581. package/src/core/backends/memoryBackend.ts +27 -0
  582. package/src/core/backends/systemBackend.ts +66 -0
  583. package/src/core/backends/types.ts +17 -0
  584. package/src/core/keyringManager.ts +208 -0
  585. package/src/utils/abiCache/.gitkeep +0 -0
  586. package/src/utils/abiResolver.ts +200 -0
  587. package/src/utils/runtimeObservability.ts +110 -0
  588. package/src/utils/secretsResolver.ts +144 -0
  589. package/tests/chainlinkService.test.ts +32 -0
  590. package/tests/diagnosticsService.test.ts +68 -0
  591. package/tests/etherscanController.test.ts +99 -0
  592. package/tests/etherscanService.test.ts +116 -0
  593. package/tests/keyringManager.test.ts +135 -0
  594. package/tests/onchainToolkit.test.ts +71 -0
  595. package/tests/robinhoodClient.test.ts +54 -0
  596. package/tests/robinhoodController.test.ts +81 -0
  597. package/tests/robinhoodIntegrationService.test.ts +50 -0
  598. package/tests/safeServicePersistence.test.ts +81 -0
  599. package/tests/test_contract_sandbox/sandbox.test.js +407 -0
  600. package/tests/walletController.test.ts +57 -0
  601. package/touch +14 -0
  602. package/tsconfig.backend.json +7 -0
  603. package/tsconfig.cli.json +7 -0
  604. package/tsconfig.json +18 -0
  605. package/tsconfig.main.json +7 -0
  606. 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;