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,203 @@
1
+ # GNOMAN 2.0 Development Guide
2
+
3
+ This guide documents the authoritative workflow for standing up a GNOMAN 2.0
4
+ workstation, exercising the offline licensing stack, and producing builds that
5
+ match what ships to customers. Every path is written relative to the repository
6
+ root (the directory that contains `package.json`).
7
+
8
+ > ℹ️ A byte-for-byte copy of this guide lives at
9
+ > `docs/wiki/development-guide.md` for the in-app wiki. Whenever you update this
10
+ > file, mirror the edits in the wiki directory so desktop users and GitHub
11
+ > readers see the same information.
12
+
13
+ ## 1. Tooling prerequisites
14
+
15
+ | Tool | Required version | Notes |
16
+ | ---- | ---------------- | ----- |
17
+ | Node.js | 18 LTS | Bundles npm 9, which is required by the build scripts. |
18
+ | npm | 9.x | Installed with Node.js. |
19
+ | Python | 3.10 or newer | Powers the Ed25519 licensing utilities. |
20
+ | pip package | `cryptography` | Install with `pip install cryptography`. |
21
+ | Native build chain | OS specific | Xcode Command Line Tools on macOS, `build-essential` on Linux, or Windows Build Tools to compile `better-sqlite3`. The AES keyring runs entirely in user space (no native bindings). |
22
+
23
+ Clone the repository and install dependencies:
24
+
25
+ ```bash
26
+ npm install
27
+ (cd renderer && npm install)
28
+ ```
29
+
30
+ The root install triggers the renderer install via the `postinstall` hook, but
31
+ running both commands explicitly surfaces dependency errors sooner.
32
+
33
+ ## 2. Environment configuration
34
+
35
+ 1. Copy the template to create a working `.env`:
36
+ ```bash
37
+ cp .env.example .env
38
+ ```
39
+ 2. Adjust variables as needed:
40
+ - `PORT` controls the Express API port (defaults to `4399`).
41
+ - `VITE_DEV_SERVER_URL` points the Electron shell at the renderer dev server
42
+ during development.
43
+ - `LICENSE_PRIVATE_KEY` points to the Ed25519 signing key used by
44
+ `backend/licenses/gen_license.py`. The default
45
+ `backend/licenses/license_private.pem` is resolved relative to the
46
+ repository root. Keep the actual private key outside of source control.
47
+
48
+ ### 2.1 AES keyring management
49
+
50
+ The backend, main process, and renderer now rely on a unified keyring manager
51
+ that can hot-swap between the system keychain, an AES-GCM encrypted file store,
52
+ or an in-memory fallback. Use the REST endpoints to administer secrets without
53
+ restarting the app:
54
+
55
+ ```bash
56
+ # List masked secrets for the active backend
57
+ curl http://127.0.0.1:${PORT:-4399}/api/keyring | jq
58
+
59
+ # Store a secret
60
+ curl -X POST http://127.0.0.1:${PORT:-4399}/api/keyring/RPC_URL \
61
+ -H 'Content-Type: application/json' \
62
+ -d '{"value":"https://sepolia.infura.io/v3/..."}'
63
+
64
+ # Reveal a secret (returns the decrypted payload)
65
+ curl http://127.0.0.1:${PORT:-4399}/api/keyring/RPC_URL | jq
66
+
67
+ # Remove a secret
68
+ curl -X DELETE http://127.0.0.1:${PORT:-4399}/api/keyring/RPC_URL
69
+
70
+ # Inspect the active backend and available backends
71
+ curl http://127.0.0.1:${PORT:-4399}/api/keyring/backend | jq
72
+
73
+ # Switch to another backend and reload configuration in place
74
+ curl -X POST http://127.0.0.1:${PORT:-4399}/api/keyring/backend/file
75
+ ```
76
+
77
+ When the system keychain is unavailable (for example, inside a sandboxed CI
78
+ runner), the manager automatically falls back to the encrypted file store and,
79
+ if needed, to the in-memory backend while logging warnings so you know secrets
80
+ may not persist between restarts.
81
+
82
+ ## 3. Running the stack locally
83
+
84
+ Use separate terminals so logs stay readable.
85
+
86
+ ```bash
87
+ npm run dev:backend # Express API at http://localhost:4399
88
+ npm run dev:renderer # Vite dev server at http://localhost:5173
89
+ ```
90
+
91
+ If you prefer to start both web stacks together, run `npm run dev`, which wraps
92
+ the two commands above with `concurrently`.
93
+
94
+ Launch the Electron shell after the TypeScript projects finish compiling:
95
+
96
+ ```bash
97
+ npm run dev:electron # Builds backend/main/renderer and opens the desktop window
98
+ ```
99
+
100
+ The Electron shell loads the renderer URL in development and the packaged
101
+ `dist/renderer/index.html` file after a production build.
102
+
103
+ ## 4. Offline licensing workflows
104
+
105
+ GNOMAN 2.0 keeps the private key offline and validates tokens locally. The
106
+ preload bridge (`main/preload/licenseBridge.ts`) invokes the existing Python
107
+ verifier and persists successful validations under `.safevault/license.env`.
108
+
109
+ ### 4.1 Generate an Ed25519 keypair (one-time)
110
+
111
+ ```bash
112
+ python backend/licenses/make_keys.py
113
+ ```
114
+
115
+ The command writes two files:
116
+
117
+ - `backend/licenses/license_private.pem` – keep this file offline and untracked.
118
+ - `backend/licenses/license_public.pem` – commit this file; it ships with the
119
+ application and is used by the verifier.
120
+
121
+ ### 4.2 Issue a license token
122
+
123
+ Run the issuer from the repository root so relative paths resolve correctly:
124
+
125
+ ```bash
126
+ python backend/licenses/gen_license.py \
127
+ --priv backend/licenses/license_private.pem \
128
+ --id workstation-001 \
129
+ --product GNOMAN \
130
+ --version 2.0.0 \
131
+ --days 365
132
+ ```
133
+
134
+ The script prints two representations:
135
+
136
+ - **RAW TOKEN** – base64url payload and signature separated by a dot.
137
+ - **HUMAN-FRIENDLY** – dashed Base32 string that is easier to transcribe.
138
+
139
+ Either format can be supplied to the desktop client. Store the value somewhere
140
+ secure so you do not need to reissue it later.
141
+
142
+ ### 4.3 Validate a token without the UI
143
+
144
+ Use the Python helper to verify a token directly from the command line. The
145
+ verifier returns `True` for a valid token and `False` otherwise.
146
+
147
+ ```bash
148
+ python -c "import sys; from backend.licenses.verify_license import verify_token; print(verify_token(sys.argv[1], sys.argv[2], 'GNOMAN', '2.0.0'))" backend/licenses/license_public.pem <token>
149
+ ```
150
+
151
+ Replace `<token>` with either the raw token or a Base32 string that decodes to
152
+ one. The helper resolves relative paths with respect to the repository root, so
153
+ invoking it from other directories works as long as you supply the correct
154
+ inputs.
155
+
156
+ ### 4.4 Desktop activation flow
157
+
158
+ 1. Launch the Electron shell (`npm run dev:electron`) and navigate to the
159
+ license screen if it does not appear automatically.
160
+ 2. Enter either token representation. The preload bridge runs
161
+ `verify_license.py` with the checked-in public key.
162
+ 3. When verification succeeds, the preload writes `.safevault/license.env` with:
163
+ ```
164
+ LICENSE_KEY=<raw token>
165
+ VALIDATED_AT=<unix timestamp>
166
+ ```
167
+ 4. On subsequent launches the preload re-verifies the stored token. If it has
168
+ expired or the verification fails, the renderer prompts for a new license.
169
+
170
+ For headless automation or regression tests, the REST endpoint
171
+ `POST /api/license` remains available. It performs the same Ed25519 checks using
172
+ Node.js and persists JSON metadata under `.gnoman/license.json` for backwards
173
+ compatibility.
174
+
175
+ ## 5. Build, lint, and packaging commands
176
+
177
+ | Command | Description |
178
+ | ------- | ----------- |
179
+ | `npm run lint` | Run ESLint across the backend, main process, renderer, and shared modules. |
180
+ | `npm run build:backend` | Compile the Express API to `dist/backend`. |
181
+ | `npm run build:main` | Compile the Electron main process to `dist/main`. |
182
+ | `npm run build:renderer` | Build the renderer UI into `renderer/dist`. |
183
+ | `npm run build` | Clean and produce all distributable artifacts (backend, main, renderer). |
184
+ | `npm start` | Rebuild and launch the packaged Electron shell. |
185
+ | `npm run start:backend` | Run the compiled backend directly from `dist/backend/index.js`. |
186
+
187
+ Distribution builds live under the `dist/` directory. The `scripts/copyRenderer.js`
188
+ helper copies the renderer bundle into `dist/main/` so the packaged Electron app
189
+ can load it from disk.
190
+
191
+ ## 6. Troubleshooting checklist
192
+
193
+ | Symptom | Suggested fix |
194
+ | ------- | -------------- |
195
+ | `ModuleNotFoundError: No module named 'cryptography'` | Install the Python dependency with `pip install cryptography`. |
196
+ | `python3` not found when validating a license | Ensure Python 3.10+ is installed and available on your `PATH`. Update the preload bridge to point at the correct executable if you use pyenv. |
197
+ | `better-sqlite3` fails to compile | Install the platform build tools (Xcode CLI tools, `build-essential`, or Windows Build Tools) before running `npm install` again. |
198
+ | Renderer cannot reach the backend | Confirm `npm run dev:backend` is running and the port matches `renderer/src/config/api.ts`. |
199
+ | License verification unexpectedly fails | Delete `.safevault/license.env` and re-run activation to ensure the stored token has not been corrupted. |
200
+ | Electron window opens without UI in production mode | Run `npm run build:renderer` before launching `npm start` so the packaged assets exist. |
201
+
202
+ Following these conventions keeps every workstation aligned with the offline
203
+ licensing flow and build system that GNOMAN 2.0 expects in production.
@@ -0,0 +1,106 @@
1
+ # GNOMAN 2.0 License Development Guide
2
+
3
+ This reference walks through generating, issuing, and validating offline license
4
+ tokens for GNOMAN 2.0. All examples assume you run commands from the repository
5
+ root (the directory containing `package.json`).
6
+
7
+ > ℹ️ A mirrored copy of this document lives at
8
+ > `docs/wiki/license-dev-guide.md` so the in-app wiki surfaces the same
9
+ > instructions. Update both files whenever you make changes.
10
+
11
+ ## 1. Prerequisites
12
+
13
+ - Python 3.10 or newer
14
+ - `pip install cryptography`
15
+ - Access to the environment-specific Ed25519 private key (keep it offline)
16
+
17
+ ## 2. Generate a keypair
18
+
19
+ Run the helper once per environment to mint a fresh Ed25519 keypair:
20
+
21
+ ```bash
22
+ python backend/licenses/make_keys.py
23
+ ```
24
+
25
+ Outputs:
26
+
27
+ - `backend/licenses/license_private.pem` – keep offline, never commit.
28
+ - `backend/licenses/license_public.pem` – check into source control and ship
29
+ with the application.
30
+
31
+ ## 3. Configure the CLI environment
32
+
33
+ Copy `.env.example` to `.env` and set `LICENSE_PRIVATE_KEY` to the path of the
34
+ private key relative to the repository root. The default value
35
+ `backend/licenses/license_private.pem` is resolved automatically.
36
+
37
+ ## 4. Issue a license token
38
+
39
+ Run the issuer with explicit arguments so the command is copy/paste friendly:
40
+
41
+ ```bash
42
+ python backend/licenses/gen_license.py \
43
+ --priv backend/licenses/license_private.pem \
44
+ --id customer-or-workstation \
45
+ --product GNOMAN \
46
+ --version 2.0.0 \
47
+ --days 365
48
+ ```
49
+
50
+ - `--priv` overrides the default private key path.
51
+ - `--id` can be any identifier useful for auditing (customer, workstation, etc.).
52
+ - `--product` and `--version` must match what the application expects.
53
+ - `--days` controls the validity window.
54
+
55
+ The script prints:
56
+
57
+ - **RAW TOKEN** – base64url payload + signature separated by a dot.
58
+ - **HUMAN-FRIENDLY** – Base32 groups separated by dashes for manual entry.
59
+
60
+ Store the raw token securely. If you need the Base32 form later, you can derive
61
+ it by running the same command again or by base32-encoding the raw value with a
62
+ short Python snippet.
63
+
64
+ ## 5. Validate a token locally
65
+
66
+ Confirm a token is still valid before distributing it:
67
+
68
+ ```bash
69
+ python -c "import sys; from backend.licenses.verify_license import verify_token; print(verify_token(sys.argv[1], sys.argv[2], 'GNOMAN', '2.0.0'))" backend/licenses/license_public.pem <token>
70
+ ```
71
+
72
+ Substitute `<token>` with either representation. A valid token prints `True`;
73
+ any failure (bad signature, wrong product/version, expired timestamp) prints
74
+ `False`.
75
+
76
+ ## 6. Desktop activation flow
77
+
78
+ 1. Launch the Electron app (`npm run dev:electron`).
79
+ 2. Enter the raw or Base32 token on the activation screen.
80
+ 3. The preload bridge executes `verify_license.py` with the checked-in public
81
+ key. Successful validation creates `.safevault/license.env` containing:
82
+ ```
83
+ LICENSE_KEY=<raw token>
84
+ VALIDATED_AT=<unix timestamp>
85
+ ```
86
+ 4. On subsequent launches the preload re-verifies the stored token. Expired or
87
+ tampered tokens force the user back to the activation screen.
88
+
89
+ ## 7. Backend compatibility endpoint
90
+
91
+ Automation can continue to call the REST endpoint `POST /api/license`. It
92
+ performs the same Ed25519 verification in Node.js and persists metadata to
93
+ `.gnoman/license.json`. The renderer no longer depends on this file, but legacy
94
+ integrations may still read it.
95
+
96
+ ## 8. Troubleshooting
97
+
98
+ | Symptom | Resolution |
99
+ | --- | --- |
100
+ | `FileNotFoundError` for the private key | Confirm `LICENSE_PRIVATE_KEY` points at the correct path and that the key lives outside version control. |
101
+ | `ModuleNotFoundError: No module named 'cryptography'` | Install the dependency with `pip install cryptography`. |
102
+ | Token prints `False` unexpectedly | Decode the payload with `python -c "import base64,sys; payload=sys.argv[1].split('.')[0]; pad='='*((4-len(payload)%4)%4); print(base64.urlsafe_b64decode(payload+pad).decode())" <token>` to confirm the product, version, and expiry are correct. |
103
+ | Desktop app refuses a known-good token | Delete `.safevault/license.env` and re-run activation to ensure the cached token has not been modified. |
104
+
105
+ Following this checklist ensures every issued license aligns with the offline
106
+ verification logic that ships with GNOMAN 2.0.
@@ -0,0 +1,73 @@
1
+ @@ -109,57 +109,59 @@ The renderer surfaces the core workflows through a set of tabs defined in
2
+ `GET /api/safes/:address/owners` and `GET /api/safes/:address/transactions/held`
3
+ to populate data and to surface aggregated hold counters plus the effective
4
+ policy (global defaults + Safe override).
5
+ - Tune Safe-specific hold duration and enable/disable flags directly from the
6
+ page. Changes are persisted to SQLite (`holds.sqlite`) and mirrored back via
7
+ `POST /api/safes/:address/hold`.
8
+ - Held transactions reflect entries tracked by the SQLite-backed hold service in
9
+ `backend/services/transactionHoldService.ts`, complete with live countdowns
10
+ and manual release controls.
11
+
12
+ ### 4.4 Sandbox
13
+ - Toggle between the legacy Safe callStatic form and the advanced sandbox panel
14
+ in `modules/sandbox/ui/SandboxPanel.tsx`.
15
+ - Upload or paste ABIs, select contract functions, provide parameters, and run
16
+ simulations via `POST /api/sandbox/contract/simulate`.
17
+ - Replay previous simulations pulled from `GET /api/sandbox/contract/history`
18
+ and optionally run them against a local fork started with
19
+ `POST /api/sandbox/fork/start` (defaults to the `anvil` command).
20
+ - Provide a `forkRpcUrl` to execute simulations against a remote Hardhat/Anvil
21
+ fork when no managed local fork is available—the backend automatically falls
22
+ back to standard RPC calls if neither option is configured.
23
+ - Use the Safe-focused tab to call `POST /api/sandbox/call-static` for quick
24
+ guard checks.
25
+
26
+ ### 4.5 Keyring
27
+ - Lists secrets registered through the Electron IPC bridge (`window.gnoman.invoke('keyring:list')`).
28
+ - Proxies every request to the backend AES keyring service (`/api/keyring/*`),
29
+ which stores encrypted payloads under `.gnoman/keyrings/<service>.json`.
30
+ - Reveals a selected secret via `keyring:get`, which maps to `POST /api/keyring/get`.
31
+ If the `keyring` module cannot load (for example, inside a sandbox), the backend
32
+ switches to an in-memory store and logs a warning so you know the data is
33
+ ephemeral.
34
+ - Encrypt, reveal, and delete secrets entirely inside the renderer. Each UI action
35
+ forwards to `/api/keyring/*`, guaranteeing parity with the legacy CLI while
36
+ capturing an auditable activity feed for operators.
37
+ - Switch between keyring services (for example `production`, `staging`, or
38
+ `aes`) without leaving the UI. The currently active service is displayed in the
39
+ global header and sidebar so you never lose track of your namespace.
40
+ - The backend still falls back to an in-memory store if the native `keyring`
41
+ module is unavailable. The UI highlights this state and keeps secrets scoped to
42
+ the session, while the CLI bridge remains for legacy automation only.
43
+
44
+ ### 4.6 License & Settings
45
+ - The activation screen uses the preload bridge (`window.safevault`) to run the
46
+ Python verifier (`backend/licenses/verify_license.py`) entirely offline.
47
+ - Successful validation writes `.safevault/license.env` with the raw token and a
48
+ `VALIDATED_AT` timestamp. The preload re-verifies this token on every launch.
49
+ - Settings exposes the stored license metadata, the global transaction hold
50
+ toggle/duration (persisted in the AES keyring via `SAFE_TX_HOLD_ENABLED`), and a
51
+ vanity wallet generator surface with live job dashboards.
52
+ - Vanity jobs are executed in worker threads, persisted to `.gnoman/vanity-jobs.json`
53
+ for auditability, and only expose mnemonic aliases so secrets stay in the
54
+ secure store.
55
+ - For automation, the backend still accepts `POST /api/license`, which stores a
56
+ JSON record in `.gnoman/license.json`. This endpoint exists for legacy flows
57
+ that expect the previous storage format.
58
+
59
+ ### 4.7 Wiki Guide
60
+ - Renders Markdown content from `docs/wiki/`, including the mirrored developer
61
+ and licensing guides.
62
+
63
+ ---
64
+
65
+ ## 5. Offline licensing quick reference
66
+
67
+ | Task | Command |
68
+
69
+ ### 4.8 Integrations & Runtime Features (Settings)
70
+ - Settings now includes a dedicated **Integrations & Runtime Features** section that surfaces one-glance enablement + reason status for `safe`, `etherscan`, and `robinhood`.
71
+ - Status values come from `GET /api/runtime/capabilities`, which reflects backend runtime decisions instead of UI guesses.
72
+ - Robinhood credential management is grouped under **Integration Configuration: Robinhood Crypto Trading API** to keep integration setup separate from license/hold/vanity controls.
73
+ - Runtime diagnostics remain available under **Runtime Diagnostics** for detailed ABI cache activity, secrets source status, Safe runtime state, and Robinhood request telemetry.
@@ -0,0 +1,85 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+ import tsParser from '@typescript-eslint/parser';
4
+ import tsPlugin from '@typescript-eslint/eslint-plugin';
5
+ import reactPlugin from 'eslint-plugin-react';
6
+ import eslintConfigPrettier from 'eslint-config-prettier';
7
+
8
+ export default [
9
+ {
10
+ ignores: ['dist/**', 'renderer/dist/**', 'node_modules/**']
11
+ },
12
+ {
13
+ files: ['**/*.{ts,tsx,js,jsx}'],
14
+ languageOptions: {
15
+ parser: tsParser,
16
+ parserOptions: {
17
+ ecmaVersion: 2020,
18
+ sourceType: 'module',
19
+ ecmaFeatures: {
20
+ jsx: true
21
+ }
22
+ },
23
+ globals: {
24
+ ...globals.es2021,
25
+ ...globals.node
26
+ }
27
+ },
28
+ plugins: {
29
+ '@typescript-eslint': tsPlugin,
30
+ react: reactPlugin
31
+ },
32
+ rules: {
33
+ ...js.configs.recommended.rules,
34
+ ...tsPlugin.configs.recommended.rules,
35
+ ...reactPlugin.configs.recommended.rules,
36
+ '@typescript-eslint/no-unused-vars': [
37
+ 'error',
38
+ { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }
39
+ ],
40
+ 'react/react-in-jsx-scope': 'off'
41
+ },
42
+ settings: {
43
+ react: {
44
+ version: 'detect'
45
+ }
46
+ }
47
+ },
48
+ {
49
+ files: ['**/*.{ts,tsx}'],
50
+ rules: {
51
+ 'no-undef': 'off'
52
+ }
53
+ },
54
+ {
55
+ files: ['renderer/**/*.{ts,tsx,js,jsx}'],
56
+ languageOptions: {
57
+ globals: {
58
+ ...globals.es2021,
59
+ ...globals.browser
60
+ }
61
+ }
62
+ },
63
+ {
64
+ files: ['modules/**/*.{ts,tsx,js,jsx}'],
65
+ languageOptions: {
66
+ globals: {
67
+ ...globals.es2021,
68
+ ...globals.browser
69
+ }
70
+ }
71
+ },
72
+ {
73
+ files: ['**/*.d.ts'],
74
+ rules: {
75
+ '@typescript-eslint/no-explicit-any': 'off'
76
+ }
77
+ },
78
+ {
79
+ files: ['**/*.js'],
80
+ rules: {
81
+ '@typescript-eslint/no-var-requires': 'off'
82
+ }
83
+ },
84
+ eslintConfigPrettier
85
+ ];
File without changes
File without changes
@@ -0,0 +1,72 @@
1
+ """
2
+ Etherscan Tracker Integration for GNOMAN
3
+ Tracks Safe transactions and performs lookup queries.
4
+ """
5
+
6
+ import json
7
+ import os
8
+ import time
9
+ from pathlib import Path
10
+
11
+ import requests
12
+ from keyring import get_password
13
+
14
+ SAFE_STATE_PATH = Path("state/gnosis_safe_state.json")
15
+ LOG_PATH = Path("logs/safe_tx_log.json")
16
+ ETHERSCAN_BASE_URL = "https://api.etherscan.io/api"
17
+ POLL_INTERVAL = 30 # seconds
18
+
19
+
20
+ def get_etherscan_api_key() -> str:
21
+ service = os.getenv("GNOMAN_KEYRING_SERVICE", "gnoman")
22
+ api_key = get_password(service, "ETHERSCAN_API_KEY")
23
+ if not api_key:
24
+ raise RuntimeError("ETHERSCAN_API_KEY is not configured in the keyring.")
25
+ return api_key
26
+
27
+
28
+ def get_safe_address() -> str:
29
+ with open(SAFE_STATE_PATH, encoding="utf-8") as handle:
30
+ data = json.load(handle)
31
+ return data["address"]
32
+
33
+
34
+ def load_safe_state() -> dict:
35
+ if not SAFE_STATE_PATH.exists():
36
+ raise RuntimeError("Safe state missing — persistence failure detected.")
37
+ with open(SAFE_STATE_PATH, encoding="utf-8") as handle:
38
+ state = json.load(handle)
39
+ if not state.get("owners") or len(state["owners"]) < 3:
40
+ raise ValueError("Safe loaded without correct owner list (3 required).")
41
+ return state
42
+
43
+
44
+ def fetch_transactions(address: str, api_key: str | None = None):
45
+ api_key = api_key or get_etherscan_api_key()
46
+ url = (
47
+ f"{ETHERSCAN_BASE_URL}?module=account&action=txlist&address={address}"
48
+ f"&apikey={api_key}"
49
+ )
50
+ response = requests.get(url, timeout=20)
51
+ response.raise_for_status()
52
+ data = response.json()
53
+ if data["status"] != "1":
54
+ raise ValueError(f"Etherscan error: {data['message']}")
55
+ return data["result"]
56
+
57
+
58
+ def track_safe_transactions():
59
+ safe = load_safe_state()
60
+ api_key = get_etherscan_api_key()
61
+ LOG_PATH.parent.mkdir(parents=True, exist_ok=True)
62
+ print(f"[EtherscanTracker] Tracking transactions for Safe: {safe['address']}")
63
+ while True:
64
+ txs = fetch_transactions(safe["address"], api_key)
65
+ with open(LOG_PATH, "w", encoding="utf-8") as handle:
66
+ json.dump(txs, handle, indent=2)
67
+ print(f"[EtherscanTracker] {len(txs)} transactions logged.")
68
+ time.sleep(POLL_INTERVAL)
69
+
70
+
71
+ if __name__ == "__main__":
72
+ track_safe_transactions()
File without changes
@@ -0,0 +1,111 @@
1
+ """Safe manager utilities for persisting and reloading Safe state."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any, Callable, Dict, Iterable, Optional
8
+
9
+ SAFE_STATE_PATH = Path("state/gnosis_safe_state.json")
10
+
11
+
12
+ def _normalize_owners(raw_owners: Any) -> list[str]:
13
+ if raw_owners is None:
14
+ return []
15
+ if callable(raw_owners):
16
+ raw_owners = raw_owners()
17
+ if isinstance(raw_owners, dict):
18
+ raw_owners = list(raw_owners.values())
19
+ if isinstance(raw_owners, str):
20
+ return [raw_owners]
21
+ if isinstance(raw_owners, Iterable):
22
+ return [str(owner) for owner in raw_owners]
23
+ return []
24
+
25
+
26
+ def _extract_threshold(safe_instance: Any) -> int:
27
+ threshold = None
28
+ if hasattr(safe_instance, "getThreshold"):
29
+ threshold = safe_instance.getThreshold()
30
+ elif hasattr(safe_instance, "threshold"):
31
+ attr = safe_instance.threshold
32
+ threshold = attr() if callable(attr) else attr
33
+ if threshold is None:
34
+ raise ValueError("Safe instance does not expose a threshold value")
35
+ return int(threshold)
36
+
37
+
38
+ def persist_safe_state(safe_instance: Any) -> Dict[str, Any]:
39
+ """Persist the current Safe metadata to disk.
40
+
41
+ Parameters
42
+ ----------
43
+ safe_instance: Any
44
+ Object exposing ``address``, ``owners`` (method or iterable) and
45
+ ``getThreshold`` or ``threshold``.
46
+ """
47
+
48
+ if safe_instance is None:
49
+ raise ValueError("Safe instance is required to persist state")
50
+
51
+ address = getattr(safe_instance, "address", None)
52
+ if callable(address): # defensive: handle SDKs exposing callables
53
+ address = address()
54
+ if not address:
55
+ raise ValueError("Safe instance is missing an address")
56
+
57
+ owners = _normalize_owners(getattr(safe_instance, "owners", None))
58
+ if len(owners) < 3:
59
+ raise ValueError("Safe must have at least three owners before persisting")
60
+
61
+ threshold = _extract_threshold(safe_instance)
62
+
63
+ SAFE_STATE_PATH.parent.mkdir(parents=True, exist_ok=True)
64
+ data = {"address": str(address), "owners": owners, "threshold": threshold}
65
+ with open(SAFE_STATE_PATH, "w", encoding="utf-8") as handle:
66
+ json.dump(data, handle, indent=2)
67
+ print("[SafeManager] Safe state persisted successfully.")
68
+ return data
69
+
70
+
71
+ def load_persisted_safe() -> Dict[str, Any]:
72
+ if not SAFE_STATE_PATH.exists():
73
+ raise RuntimeError("Safe state file missing.")
74
+ with open(SAFE_STATE_PATH, "r", encoding="utf-8") as handle:
75
+ data = json.load(handle)
76
+ owners = data.get("owners") or []
77
+ if len(owners) < 3:
78
+ raise ValueError("Invalid Safe state — missing or incomplete owners.")
79
+ print(f"[SafeManager] Loaded Safe with owners: {owners}")
80
+ return data
81
+
82
+
83
+ class SafeManager:
84
+ """Utility orchestrating Safe persistence and retrieval."""
85
+
86
+ def __init__(self, safe_factory: Callable[..., Any]):
87
+ self._safe_factory = safe_factory
88
+ self._safe_instance: Optional[Any] = None
89
+
90
+ @property
91
+ def safe(self) -> Any:
92
+ if self._safe_instance is None:
93
+ raise RuntimeError("Safe has not been initialised. Call `load_safe`." )
94
+ return self._safe_instance
95
+
96
+ def load_safe(self, *factory_args: Any, **factory_kwargs: Any) -> Any:
97
+ """Instantiate a Safe instance and persist its state immediately."""
98
+ safe_instance = self._safe_factory(*factory_args, **factory_kwargs)
99
+ self._safe_instance = safe_instance
100
+ persist_safe_state(safe_instance)
101
+ return safe_instance
102
+
103
+ def refresh_state(self) -> Dict[str, Any]:
104
+ """Persist the currently tracked Safe instance again and return the cache."""
105
+ if self._safe_instance is None:
106
+ raise RuntimeError("Safe has not been initialised.")
107
+ return persist_safe_state(self._safe_instance)
108
+
109
+ def get_cached_state(self) -> Dict[str, Any]:
110
+ """Load Safe metadata from the persisted cache on disk."""
111
+ return load_persisted_safe()