@echoclaw/echo-0g 1.0.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 (371) hide show
  1. package/README.md +1175 -0
  2. package/dist/0g-compute/account.d.ts +36 -0
  3. package/dist/0g-compute/account.d.ts.map +1 -0
  4. package/dist/0g-compute/account.js +85 -0
  5. package/dist/0g-compute/account.js.map +1 -0
  6. package/dist/0g-compute/bridge.d.ts +16 -0
  7. package/dist/0g-compute/bridge.d.ts.map +1 -0
  8. package/dist/0g-compute/bridge.js +40 -0
  9. package/dist/0g-compute/bridge.js.map +1 -0
  10. package/dist/0g-compute/broker-factory.d.ts +19 -0
  11. package/dist/0g-compute/broker-factory.d.ts.map +1 -0
  12. package/dist/0g-compute/broker-factory.js +65 -0
  13. package/dist/0g-compute/broker-factory.js.map +1 -0
  14. package/dist/0g-compute/constants.d.ts +10 -0
  15. package/dist/0g-compute/constants.d.ts.map +1 -0
  16. package/dist/0g-compute/constants.js +12 -0
  17. package/dist/0g-compute/constants.js.map +1 -0
  18. package/dist/0g-compute/monitor.d.ts +43 -0
  19. package/dist/0g-compute/monitor.d.ts.map +1 -0
  20. package/dist/0g-compute/monitor.js +302 -0
  21. package/dist/0g-compute/monitor.js.map +1 -0
  22. package/dist/0g-compute/pricing.d.ts +43 -0
  23. package/dist/0g-compute/pricing.d.ts.map +1 -0
  24. package/dist/0g-compute/pricing.js +53 -0
  25. package/dist/0g-compute/pricing.js.map +1 -0
  26. package/dist/0g-compute/sdk-bridge.cjs +17 -0
  27. package/dist/0g-compute/sdk-bridge.cjs.map +1 -0
  28. package/dist/0g-compute/sdk-bridge.d.cts +9 -0
  29. package/dist/0g-compute/sdk-bridge.d.cts.map +1 -0
  30. package/dist/0g-compute/smoke-test.d.ts +11 -0
  31. package/dist/0g-compute/smoke-test.d.ts.map +1 -0
  32. package/dist/0g-compute/smoke-test.js +172 -0
  33. package/dist/0g-compute/smoke-test.js.map +1 -0
  34. package/dist/bot/daemon.d.ts +34 -0
  35. package/dist/bot/daemon.d.ts.map +1 -0
  36. package/dist/bot/daemon.js +386 -0
  37. package/dist/bot/daemon.js.map +1 -0
  38. package/dist/bot/executor.d.ts +14238 -0
  39. package/dist/bot/executor.d.ts.map +1 -0
  40. package/dist/bot/executor.js +183 -0
  41. package/dist/bot/executor.js.map +1 -0
  42. package/dist/bot/nonce-queue.d.ts +20 -0
  43. package/dist/bot/nonce-queue.d.ts.map +1 -0
  44. package/dist/bot/nonce-queue.js +41 -0
  45. package/dist/bot/nonce-queue.js.map +1 -0
  46. package/dist/bot/notify.d.ts +15 -0
  47. package/dist/bot/notify.d.ts.map +1 -0
  48. package/dist/bot/notify.js +98 -0
  49. package/dist/bot/notify.js.map +1 -0
  50. package/dist/bot/orders.d.ts +30 -0
  51. package/dist/bot/orders.d.ts.map +1 -0
  52. package/dist/bot/orders.js +172 -0
  53. package/dist/bot/orders.js.map +1 -0
  54. package/dist/bot/state.d.ts +14 -0
  55. package/dist/bot/state.d.ts.map +1 -0
  56. package/dist/bot/state.js +109 -0
  57. package/dist/bot/state.js.map +1 -0
  58. package/dist/bot/stream.d.ts +28 -0
  59. package/dist/bot/stream.d.ts.map +1 -0
  60. package/dist/bot/stream.js +96 -0
  61. package/dist/bot/stream.js.map +1 -0
  62. package/dist/bot/triggers.d.ts +17 -0
  63. package/dist/bot/triggers.d.ts.map +1 -0
  64. package/dist/bot/triggers.js +95 -0
  65. package/dist/bot/triggers.js.map +1 -0
  66. package/dist/bot/types.d.ts +199 -0
  67. package/dist/bot/types.d.ts.map +1 -0
  68. package/dist/bot/types.js +12 -0
  69. package/dist/bot/types.js.map +1 -0
  70. package/dist/chainscan/client.d.ts +28 -0
  71. package/dist/chainscan/client.d.ts.map +1 -0
  72. package/dist/chainscan/client.js +361 -0
  73. package/dist/chainscan/client.js.map +1 -0
  74. package/dist/chainscan/constants.d.ts +15 -0
  75. package/dist/chainscan/constants.d.ts.map +1 -0
  76. package/dist/chainscan/constants.js +15 -0
  77. package/dist/chainscan/constants.js.map +1 -0
  78. package/dist/chainscan/types.d.ts +148 -0
  79. package/dist/chainscan/types.d.ts.map +1 -0
  80. package/dist/chainscan/types.js +2 -0
  81. package/dist/chainscan/types.js.map +1 -0
  82. package/dist/chainscan/validation.d.ts +35 -0
  83. package/dist/chainscan/validation.d.ts.map +1 -0
  84. package/dist/chainscan/validation.js +97 -0
  85. package/dist/chainscan/validation.js.map +1 -0
  86. package/dist/cli.d.ts +7 -0
  87. package/dist/cli.d.ts.map +1 -0
  88. package/dist/cli.js +328 -0
  89. package/dist/cli.js.map +1 -0
  90. package/dist/commands/0g-compute.d.ts +21 -0
  91. package/dist/commands/0g-compute.d.ts.map +1 -0
  92. package/dist/commands/0g-compute.js +850 -0
  93. package/dist/commands/0g-compute.js.map +1 -0
  94. package/dist/commands/chainscan.d.ts +17 -0
  95. package/dist/commands/chainscan.d.ts.map +1 -0
  96. package/dist/commands/chainscan.js +605 -0
  97. package/dist/commands/chainscan.js.map +1 -0
  98. package/dist/commands/config.d.ts +3 -0
  99. package/dist/commands/config.d.ts.map +1 -0
  100. package/dist/commands/config.js +251 -0
  101. package/dist/commands/config.js.map +1 -0
  102. package/dist/commands/echobook.d.ts +17 -0
  103. package/dist/commands/echobook.d.ts.map +1 -0
  104. package/dist/commands/echobook.js +905 -0
  105. package/dist/commands/echobook.js.map +1 -0
  106. package/dist/commands/jaine-subgraph.d.ts +3 -0
  107. package/dist/commands/jaine-subgraph.d.ts.map +1 -0
  108. package/dist/commands/jaine-subgraph.js +565 -0
  109. package/dist/commands/jaine-subgraph.js.map +1 -0
  110. package/dist/commands/jaine.d.ts +3 -0
  111. package/dist/commands/jaine.d.ts.map +1 -0
  112. package/dist/commands/jaine.js +1415 -0
  113. package/dist/commands/jaine.js.map +1 -0
  114. package/dist/commands/marketmaker.d.ts +6 -0
  115. package/dist/commands/marketmaker.d.ts.map +1 -0
  116. package/dist/commands/marketmaker.js +451 -0
  117. package/dist/commands/marketmaker.js.map +1 -0
  118. package/dist/commands/send.d.ts +3 -0
  119. package/dist/commands/send.d.ts.map +1 -0
  120. package/dist/commands/send.js +229 -0
  121. package/dist/commands/send.js.map +1 -0
  122. package/dist/commands/setup.d.ts +3 -0
  123. package/dist/commands/setup.d.ts.map +1 -0
  124. package/dist/commands/setup.js +263 -0
  125. package/dist/commands/setup.js.map +1 -0
  126. package/dist/commands/slop-app.d.ts +9 -0
  127. package/dist/commands/slop-app.d.ts.map +1 -0
  128. package/dist/commands/slop-app.js +708 -0
  129. package/dist/commands/slop-app.js.map +1 -0
  130. package/dist/commands/slop-stream.d.ts +9 -0
  131. package/dist/commands/slop-stream.d.ts.map +1 -0
  132. package/dist/commands/slop-stream.js +99 -0
  133. package/dist/commands/slop-stream.js.map +1 -0
  134. package/dist/commands/slop.d.ts +3 -0
  135. package/dist/commands/slop.d.ts.map +1 -0
  136. package/dist/commands/slop.js +1053 -0
  137. package/dist/commands/slop.js.map +1 -0
  138. package/dist/commands/wallet.d.ts +13 -0
  139. package/dist/commands/wallet.d.ts.map +1 -0
  140. package/dist/commands/wallet.js +748 -0
  141. package/dist/commands/wallet.js.map +1 -0
  142. package/dist/config/paths.d.ts +13 -0
  143. package/dist/config/paths.d.ts.map +1 -0
  144. package/dist/config/paths.js +33 -0
  145. package/dist/config/paths.js.map +1 -0
  146. package/dist/config/store.d.ts +48 -0
  147. package/dist/config/store.d.ts.map +1 -0
  148. package/dist/config/store.js +113 -0
  149. package/dist/config/store.js.map +1 -0
  150. package/dist/constants/chain.d.ts +57 -0
  151. package/dist/constants/chain.d.ts.map +1 -0
  152. package/dist/constants/chain.js +51 -0
  153. package/dist/constants/chain.js.map +1 -0
  154. package/dist/echobook/api.d.ts +38 -0
  155. package/dist/echobook/api.d.ts.map +1 -0
  156. package/dist/echobook/api.js +86 -0
  157. package/dist/echobook/api.js.map +1 -0
  158. package/dist/echobook/auth.d.ts +31 -0
  159. package/dist/echobook/auth.d.ts.map +1 -0
  160. package/dist/echobook/auth.js +93 -0
  161. package/dist/echobook/auth.js.map +1 -0
  162. package/dist/echobook/comments.d.ts +26 -0
  163. package/dist/echobook/comments.d.ts.map +1 -0
  164. package/dist/echobook/comments.js +20 -0
  165. package/dist/echobook/comments.js.map +1 -0
  166. package/dist/echobook/follows.d.ts +19 -0
  167. package/dist/echobook/follows.d.ts.map +1 -0
  168. package/dist/echobook/follows.js +21 -0
  169. package/dist/echobook/follows.js.map +1 -0
  170. package/dist/echobook/jwtCache.d.ts +15 -0
  171. package/dist/echobook/jwtCache.d.ts.map +1 -0
  172. package/dist/echobook/jwtCache.js +63 -0
  173. package/dist/echobook/jwtCache.js.map +1 -0
  174. package/dist/echobook/notifications.d.ts +30 -0
  175. package/dist/echobook/notifications.d.ts.map +1 -0
  176. package/dist/echobook/notifications.js +26 -0
  177. package/dist/echobook/notifications.js.map +1 -0
  178. package/dist/echobook/points.d.ts +35 -0
  179. package/dist/echobook/points.d.ts.map +1 -0
  180. package/dist/echobook/points.js +20 -0
  181. package/dist/echobook/points.js.map +1 -0
  182. package/dist/echobook/posts.d.ts +46 -0
  183. package/dist/echobook/posts.d.ts.map +1 -0
  184. package/dist/echobook/posts.js +43 -0
  185. package/dist/echobook/posts.js.map +1 -0
  186. package/dist/echobook/profile.d.ts +29 -0
  187. package/dist/echobook/profile.d.ts.map +1 -0
  188. package/dist/echobook/profile.js +14 -0
  189. package/dist/echobook/profile.js.map +1 -0
  190. package/dist/echobook/submolts.d.ts +22 -0
  191. package/dist/echobook/submolts.d.ts.map +1 -0
  192. package/dist/echobook/submolts.js +24 -0
  193. package/dist/echobook/submolts.js.map +1 -0
  194. package/dist/echobook/tradeProof.d.ts +21 -0
  195. package/dist/echobook/tradeProof.d.ts.map +1 -0
  196. package/dist/echobook/tradeProof.js +14 -0
  197. package/dist/echobook/tradeProof.js.map +1 -0
  198. package/dist/echobook/votes.d.ts +17 -0
  199. package/dist/echobook/votes.d.ts.map +1 -0
  200. package/dist/echobook/votes.js +20 -0
  201. package/dist/echobook/votes.js.map +1 -0
  202. package/dist/errors.d.ts +125 -0
  203. package/dist/errors.d.ts.map +1 -0
  204. package/dist/errors.js +147 -0
  205. package/dist/errors.js.map +1 -0
  206. package/dist/intents/store.d.ts +22 -0
  207. package/dist/intents/store.d.ts.map +1 -0
  208. package/dist/intents/store.js +76 -0
  209. package/dist/intents/store.js.map +1 -0
  210. package/dist/intents/types.d.ts +21 -0
  211. package/dist/intents/types.d.ts.map +1 -0
  212. package/dist/intents/types.js +2 -0
  213. package/dist/intents/types.js.map +1 -0
  214. package/dist/jaine/abi/erc20.d.ts +90 -0
  215. package/dist/jaine/abi/erc20.d.ts.map +1 -0
  216. package/dist/jaine/abi/erc20.js +65 -0
  217. package/dist/jaine/abi/erc20.js.map +1 -0
  218. package/dist/jaine/abi/factory.d.ts +38 -0
  219. package/dist/jaine/abi/factory.d.ts.map +1 -0
  220. package/dist/jaine/abi/factory.js +26 -0
  221. package/dist/jaine/abi/factory.js.map +1 -0
  222. package/dist/jaine/abi/index.d.ts +11 -0
  223. package/dist/jaine/abi/index.d.ts.map +1 -0
  224. package/dist/jaine/abi/index.js +11 -0
  225. package/dist/jaine/abi/index.js.map +1 -0
  226. package/dist/jaine/abi/nftManager.d.ts +282 -0
  227. package/dist/jaine/abi/nftManager.d.ts.map +1 -0
  228. package/dist/jaine/abi/nftManager.js +182 -0
  229. package/dist/jaine/abi/nftManager.js.map +1 -0
  230. package/dist/jaine/abi/pool.d.ts +77 -0
  231. package/dist/jaine/abi/pool.d.ts.map +1 -0
  232. package/dist/jaine/abi/pool.js +56 -0
  233. package/dist/jaine/abi/pool.js.map +1 -0
  234. package/dist/jaine/abi/quoter.d.ts +84 -0
  235. package/dist/jaine/abi/quoter.d.ts.map +1 -0
  236. package/dist/jaine/abi/quoter.js +53 -0
  237. package/dist/jaine/abi/quoter.js.map +1 -0
  238. package/dist/jaine/abi/router.d.ts +135 -0
  239. package/dist/jaine/abi/router.d.ts.map +1 -0
  240. package/dist/jaine/abi/router.js +88 -0
  241. package/dist/jaine/abi/router.js.map +1 -0
  242. package/dist/jaine/abi/w0g.d.ts +41 -0
  243. package/dist/jaine/abi/w0g.d.ts.map +1 -0
  244. package/dist/jaine/abi/w0g.js +34 -0
  245. package/dist/jaine/abi/w0g.js.map +1 -0
  246. package/dist/jaine/allowance.d.ts +48 -0
  247. package/dist/jaine/allowance.d.ts.map +1 -0
  248. package/dist/jaine/allowance.js +192 -0
  249. package/dist/jaine/allowance.js.map +1 -0
  250. package/dist/jaine/coreTokens.d.ts +32 -0
  251. package/dist/jaine/coreTokens.d.ts.map +1 -0
  252. package/dist/jaine/coreTokens.js +91 -0
  253. package/dist/jaine/coreTokens.js.map +1 -0
  254. package/dist/jaine/pathEncoding.d.ts +39 -0
  255. package/dist/jaine/pathEncoding.d.ts.map +1 -0
  256. package/dist/jaine/pathEncoding.js +98 -0
  257. package/dist/jaine/pathEncoding.js.map +1 -0
  258. package/dist/jaine/paths.d.ts +11 -0
  259. package/dist/jaine/paths.d.ts.map +1 -0
  260. package/dist/jaine/paths.js +20 -0
  261. package/dist/jaine/paths.js.map +1 -0
  262. package/dist/jaine/poolCache.d.ts +47 -0
  263. package/dist/jaine/poolCache.d.ts.map +1 -0
  264. package/dist/jaine/poolCache.js +195 -0
  265. package/dist/jaine/poolCache.js.map +1 -0
  266. package/dist/jaine/routing.d.ts +41 -0
  267. package/dist/jaine/routing.d.ts.map +1 -0
  268. package/dist/jaine/routing.js +247 -0
  269. package/dist/jaine/routing.js.map +1 -0
  270. package/dist/jaine/subgraph/client.d.ts +26 -0
  271. package/dist/jaine/subgraph/client.d.ts.map +1 -0
  272. package/dist/jaine/subgraph/client.js +201 -0
  273. package/dist/jaine/subgraph/client.js.map +1 -0
  274. package/dist/jaine/subgraph/constants.d.ts +9 -0
  275. package/dist/jaine/subgraph/constants.d.ts.map +1 -0
  276. package/dist/jaine/subgraph/constants.js +9 -0
  277. package/dist/jaine/subgraph/constants.js.map +1 -0
  278. package/dist/jaine/subgraph/queries.d.ts +21 -0
  279. package/dist/jaine/subgraph/queries.d.ts.map +1 -0
  280. package/dist/jaine/subgraph/queries.js +304 -0
  281. package/dist/jaine/subgraph/queries.js.map +1 -0
  282. package/dist/jaine/subgraph/types.d.ts +209 -0
  283. package/dist/jaine/subgraph/types.d.ts.map +1 -0
  284. package/dist/jaine/subgraph/types.js +7 -0
  285. package/dist/jaine/subgraph/types.js.map +1 -0
  286. package/dist/jaine/userTokens.d.ts +27 -0
  287. package/dist/jaine/userTokens.d.ts.map +1 -0
  288. package/dist/jaine/userTokens.js +89 -0
  289. package/dist/jaine/userTokens.js.map +1 -0
  290. package/dist/openclaw/config.d.ts +43 -0
  291. package/dist/openclaw/config.d.ts.map +1 -0
  292. package/dist/openclaw/config.js +231 -0
  293. package/dist/openclaw/config.js.map +1 -0
  294. package/dist/openclaw/hooks-client.d.ts +24 -0
  295. package/dist/openclaw/hooks-client.d.ts.map +1 -0
  296. package/dist/openclaw/hooks-client.js +119 -0
  297. package/dist/openclaw/hooks-client.js.map +1 -0
  298. package/dist/slop/abi/factory.d.ts +128 -0
  299. package/dist/slop/abi/factory.d.ts.map +1 -0
  300. package/dist/slop/abi/factory.js +70 -0
  301. package/dist/slop/abi/factory.js.map +1 -0
  302. package/dist/slop/abi/feeCollector.d.ts +95 -0
  303. package/dist/slop/abi/feeCollector.d.ts.map +1 -0
  304. package/dist/slop/abi/feeCollector.js +71 -0
  305. package/dist/slop/abi/feeCollector.js.map +1 -0
  306. package/dist/slop/abi/index.d.ts +5 -0
  307. package/dist/slop/abi/index.d.ts.map +1 -0
  308. package/dist/slop/abi/index.js +5 -0
  309. package/dist/slop/abi/index.js.map +1 -0
  310. package/dist/slop/abi/registry.d.ts +135 -0
  311. package/dist/slop/abi/registry.d.ts.map +1 -0
  312. package/dist/slop/abi/registry.js +90 -0
  313. package/dist/slop/abi/registry.js.map +1 -0
  314. package/dist/slop/abi/token.d.ts +320 -0
  315. package/dist/slop/abi/token.d.ts.map +1 -0
  316. package/dist/slop/abi/token.js +251 -0
  317. package/dist/slop/abi/token.js.map +1 -0
  318. package/dist/slop/auth.d.ts +19 -0
  319. package/dist/slop/auth.d.ts.map +1 -0
  320. package/dist/slop/auth.js +92 -0
  321. package/dist/slop/auth.js.map +1 -0
  322. package/dist/slop/jwtCache.d.ts +27 -0
  323. package/dist/slop/jwtCache.d.ts.map +1 -0
  324. package/dist/slop/jwtCache.js +91 -0
  325. package/dist/slop/jwtCache.js.map +1 -0
  326. package/dist/slop/quote.d.ts +80 -0
  327. package/dist/slop/quote.d.ts.map +1 -0
  328. package/dist/slop/quote.js +174 -0
  329. package/dist/slop/quote.js.map +1 -0
  330. package/dist/utils/canonicalJson.d.ts +8 -0
  331. package/dist/utils/canonicalJson.d.ts.map +1 -0
  332. package/dist/utils/canonicalJson.js +20 -0
  333. package/dist/utils/canonicalJson.js.map +1 -0
  334. package/dist/utils/env.d.ts +11 -0
  335. package/dist/utils/env.d.ts.map +1 -0
  336. package/dist/utils/env.js +20 -0
  337. package/dist/utils/env.js.map +1 -0
  338. package/dist/utils/http.d.ts +19 -0
  339. package/dist/utils/http.d.ts.map +1 -0
  340. package/dist/utils/http.js +61 -0
  341. package/dist/utils/http.js.map +1 -0
  342. package/dist/utils/logger.d.ts +4 -0
  343. package/dist/utils/logger.d.ts.map +1 -0
  344. package/dist/utils/logger.js +21 -0
  345. package/dist/utils/logger.js.map +1 -0
  346. package/dist/utils/output.d.ts +29 -0
  347. package/dist/utils/output.d.ts.map +1 -0
  348. package/dist/utils/output.js +51 -0
  349. package/dist/utils/output.js.map +1 -0
  350. package/dist/utils/rateLimit.d.ts +22 -0
  351. package/dist/utils/rateLimit.d.ts.map +1 -0
  352. package/dist/utils/rateLimit.js +58 -0
  353. package/dist/utils/rateLimit.js.map +1 -0
  354. package/dist/utils/respond.d.ts +19 -0
  355. package/dist/utils/respond.d.ts.map +1 -0
  356. package/dist/utils/respond.js +25 -0
  357. package/dist/utils/respond.js.map +1 -0
  358. package/dist/utils/ui.d.ts +38 -0
  359. package/dist/utils/ui.d.ts.map +1 -0
  360. package/dist/utils/ui.js +126 -0
  361. package/dist/utils/ui.js.map +1 -0
  362. package/dist/wallet/client.d.ts +4 -0
  363. package/dist/wallet/client.d.ts.map +1 -0
  364. package/dist/wallet/client.js +53 -0
  365. package/dist/wallet/client.js.map +1 -0
  366. package/dist/wallet/keystore.d.ts +22 -0
  367. package/dist/wallet/keystore.d.ts.map +1 -0
  368. package/dist/wallet/keystore.js +111 -0
  369. package/dist/wallet/keystore.js.map +1 -0
  370. package/package.json +63 -0
  371. package/skills/echo/SKILL.md +1121 -0
@@ -0,0 +1,302 @@
1
+ /**
2
+ * BalanceMonitor — daemon that polls 0G Compute sub-account balances
3
+ * and sends webhook alerts when they drop below a threshold.
4
+ *
5
+ * Supports two modes:
6
+ * - `fixed`: user-supplied static threshold
7
+ * - `recommended`: dynamic threshold derived from provider pricing
8
+ *
9
+ * Follows the same lifecycle pattern as BotDaemon (pidfile, shutdown file, signals).
10
+ */
11
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, } from "node:fs";
12
+ import { getAuthenticatedBroker } from "./broker-factory.js";
13
+ import { withSuppressedConsole } from "./bridge.js";
14
+ import { normalizeSubAccount } from "./account.js";
15
+ import { calculateProviderPricing } from "./pricing.js";
16
+ import { loadHooksConfig } from "../openclaw/hooks-client.js";
17
+ import { ZG_COMPUTE_DIR, ZG_MONITOR_PID_FILE, ZG_MONITOR_SHUTDOWN_FILE, ZG_MONITOR_STATE_FILE, } from "./constants.js";
18
+ import { EchoError, ErrorCodes } from "../errors.js";
19
+ import logger from "../utils/logger.js";
20
+ const ALERT_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour
21
+ const ALERT_DROP_THRESHOLD = 0.5; // alert again if balance dropped another 50%
22
+ export class BalanceMonitor {
23
+ providers;
24
+ mode;
25
+ threshold;
26
+ buffer;
27
+ alertRatio;
28
+ intervalSec;
29
+ shuttingDown = false;
30
+ shutdownWatcher = null;
31
+ pollTimer = null;
32
+ state;
33
+ constructor(opts) {
34
+ this.providers = opts.providers;
35
+ this.mode = opts.mode;
36
+ this.threshold = opts.threshold;
37
+ this.buffer = opts.buffer ?? 0;
38
+ this.alertRatio = opts.alertRatio ?? 1.2;
39
+ this.intervalSec = Math.max(60, opts.intervalSec);
40
+ this.state = {
41
+ providers: opts.providers,
42
+ mode: opts.mode,
43
+ threshold: opts.threshold,
44
+ buffer: this.buffer,
45
+ alertRatio: this.alertRatio,
46
+ intervalSec: this.intervalSec,
47
+ lastCheckAt: 0,
48
+ alerts: {},
49
+ };
50
+ }
51
+ async start() {
52
+ this.checkAndWritePid();
53
+ this.cleanupShutdownFile();
54
+ logger.info(`[Monitor] Starting balance monitor`);
55
+ logger.info(`[Monitor] Mode: ${this.mode}`);
56
+ logger.info(`[Monitor] Providers: ${this.providers.join(", ")}`);
57
+ if (this.mode === "fixed") {
58
+ logger.info(`[Monitor] Threshold: ${this.threshold} 0G, interval: ${this.intervalSec}s`);
59
+ }
60
+ else {
61
+ logger.info(`[Monitor] Buffer: ${this.buffer} 0G, alertRatio: ${this.alertRatio}, interval: ${this.intervalSec}s`);
62
+ }
63
+ // Signal handlers
64
+ const onSignal = () => this.stop();
65
+ process.on("SIGINT", onSignal);
66
+ process.on("SIGTERM", onSignal);
67
+ // Shutdown file watcher (Windows fallback)
68
+ this.shutdownWatcher = setInterval(() => {
69
+ if (existsSync(ZG_MONITOR_SHUTDOWN_FILE)) {
70
+ logger.info("[Monitor] Shutdown file detected, stopping...");
71
+ this.stop();
72
+ }
73
+ }, 1000);
74
+ // First check immediately
75
+ await this.poll();
76
+ // Then schedule recurring
77
+ this.schedulePoll();
78
+ logger.info("[Monitor] Running (press Ctrl+C to stop)");
79
+ }
80
+ schedulePoll() {
81
+ if (this.shuttingDown)
82
+ return;
83
+ this.pollTimer = setTimeout(async () => {
84
+ if (this.shuttingDown)
85
+ return;
86
+ await this.poll();
87
+ this.schedulePoll();
88
+ }, this.intervalSec * 1000);
89
+ }
90
+ async poll() {
91
+ try {
92
+ const broker = await getAuthenticatedBroker();
93
+ // In recommended mode, fetch pricing once per poll
94
+ let providerPricingMap;
95
+ if (this.mode === "recommended") {
96
+ providerPricingMap = new Map();
97
+ try {
98
+ const services = await withSuppressedConsole(() => broker.inference.listServiceWithDetail());
99
+ for (const svc of services) {
100
+ const addr = svc.provider.toLowerCase();
101
+ const pricing = calculateProviderPricing(svc.inputPrice, svc.outputPrice, undefined, this.alertRatio);
102
+ providerPricingMap.set(addr, {
103
+ threshold: pricing.recommendedAlertLockedOg + this.buffer,
104
+ recommendedMin: pricing.recommendedMinLockedOg,
105
+ });
106
+ }
107
+ }
108
+ catch (err) {
109
+ logger.warn(`[Monitor] Failed to fetch service pricing: ${err instanceof Error ? err.message : String(err)}`);
110
+ }
111
+ }
112
+ for (const provider of this.providers) {
113
+ try {
114
+ const account = await withSuppressedConsole(() => broker.inference.getAccount(provider));
115
+ const normalized = normalizeSubAccount(account);
116
+ logger.debug(`[Monitor] ${provider.slice(0, 10)}... locked: ${normalized.lockedOg.toFixed(4)} 0G ` +
117
+ `(total: ${normalized.totalOg.toFixed(4)}, pending: ${normalized.pendingRefundOg.toFixed(4)})`);
118
+ // Determine effective threshold
119
+ let effectiveThreshold;
120
+ let recommendedMin;
121
+ if (this.mode === "fixed") {
122
+ effectiveThreshold = this.threshold;
123
+ }
124
+ else {
125
+ const providerKey = provider.toLowerCase();
126
+ const pricing = providerPricingMap?.get(providerKey);
127
+ if (pricing) {
128
+ effectiveThreshold = pricing.threshold;
129
+ recommendedMin = pricing.recommendedMin;
130
+ }
131
+ else {
132
+ // Fallback: provider not found in services list, use 1.0 0G floor
133
+ effectiveThreshold = 1.0 + this.buffer;
134
+ recommendedMin = 1.0;
135
+ logger.debug(`[Monitor] ${provider.slice(0, 10)}... not found in services, using floor threshold`);
136
+ }
137
+ }
138
+ if (normalized.lockedOg < effectiveThreshold) {
139
+ await this.handleLowBalance(provider, normalized.lockedOg, effectiveThreshold, recommendedMin);
140
+ }
141
+ // Save per-provider thresholds in state
142
+ if (this.mode === "recommended") {
143
+ if (!this.state.providerThresholds)
144
+ this.state.providerThresholds = {};
145
+ this.state.providerThresholds[provider] = {
146
+ threshold: effectiveThreshold,
147
+ recommendedMin: recommendedMin ?? effectiveThreshold,
148
+ };
149
+ }
150
+ }
151
+ catch (err) {
152
+ logger.warn(`[Monitor] Failed to check ${provider.slice(0, 10)}...: ${err instanceof Error ? err.message : String(err)}`);
153
+ }
154
+ }
155
+ this.state.lastCheckAt = Date.now();
156
+ this.saveState();
157
+ }
158
+ catch (err) {
159
+ logger.error(`[Monitor] Poll failed: ${err instanceof Error ? err.message : String(err)}`);
160
+ }
161
+ }
162
+ async handleLowBalance(provider, lockedOg, threshold, recommendedMin) {
163
+ const now = Date.now();
164
+ const alertState = this.state.alerts[provider];
165
+ if (alertState) {
166
+ const timeSinceLastAlert = now - alertState.lastAlertAt;
167
+ const lastBalance = parseFloat(alertState.lastAlertBalance);
168
+ // Anti-spam: skip if alerted less than 1h ago AND balance hasn't dropped another 50%
169
+ if (timeSinceLastAlert < ALERT_COOLDOWN_MS &&
170
+ (lastBalance === 0 || lockedOg > lastBalance * ALERT_DROP_THRESHOLD)) {
171
+ logger.debug(`[Monitor] Suppressing alert for ${provider.slice(0, 10)}... (cooldown)`);
172
+ return;
173
+ }
174
+ }
175
+ logger.warn(`[Monitor] Low balance: ${provider.slice(0, 10)}... locked=${lockedOg.toFixed(4)} 0G ` +
176
+ `(threshold: ${threshold.toFixed(4)}${recommendedMin != null ? `, recommendedMin: ${recommendedMin.toFixed(4)}` : ""})`);
177
+ // Update alert state
178
+ this.state.alerts[provider] = {
179
+ lastAlertAt: now,
180
+ lastAlertBalance: lockedOg.toString(),
181
+ };
182
+ this.saveState();
183
+ // Send webhook
184
+ await this.sendWebhook(provider, lockedOg, threshold, recommendedMin);
185
+ }
186
+ async sendWebhook(provider, lockedOg, threshold, recommendedMin) {
187
+ const config = loadHooksConfig();
188
+ if (!config) {
189
+ logger.debug("[Monitor] Webhook disabled (OPENCLAW_HOOKS_* not configured)");
190
+ return;
191
+ }
192
+ const lines = [
193
+ `Low balance for provider ${provider.slice(0, 10)}...`,
194
+ `Locked: ${lockedOg.toFixed(4)} 0G (threshold: ${threshold.toFixed(4)} 0G)`,
195
+ ];
196
+ if (recommendedMin != null) {
197
+ lines.push(`Recommended min: ${recommendedMin.toFixed(4)} 0G`);
198
+ }
199
+ lines.push(`Run: echo 0g-compute ledger fund --provider ${provider} --amount <amount> --yes`);
200
+ const message = lines.join("\n");
201
+ const body = {
202
+ message,
203
+ name: "BalanceMonitor",
204
+ deliver: true,
205
+ wakeMode: "now",
206
+ ...(config.agentId ? { agentId: config.agentId } : {}),
207
+ ...(config.channel ? { channel: config.channel } : {}),
208
+ };
209
+ const url = `${config.baseUrl}/hooks/agent`;
210
+ for (let attempt = 0; attempt < 2; attempt++) {
211
+ try {
212
+ const res = await fetch(url, {
213
+ method: "POST",
214
+ headers: {
215
+ "Content-Type": "application/json",
216
+ Authorization: `Bearer ${config.token}`,
217
+ },
218
+ body: JSON.stringify(body),
219
+ signal: AbortSignal.timeout(10_000),
220
+ });
221
+ if (res.ok) {
222
+ logger.info(`[Monitor] Webhook sent for ${provider.slice(0, 10)}...`);
223
+ }
224
+ else {
225
+ logger.warn(`[Monitor] Webhook failed: ${res.status}`);
226
+ }
227
+ return;
228
+ }
229
+ catch (err) {
230
+ if (attempt === 0)
231
+ continue;
232
+ logger.warn(`[Monitor] Webhook error: ${err instanceof Error ? err.message : String(err)}`);
233
+ }
234
+ }
235
+ }
236
+ checkAndWritePid() {
237
+ if (!existsSync(ZG_COMPUTE_DIR)) {
238
+ mkdirSync(ZG_COMPUTE_DIR, { recursive: true });
239
+ }
240
+ if (existsSync(ZG_MONITOR_PID_FILE)) {
241
+ const existingPid = parseInt(readFileSync(ZG_MONITOR_PID_FILE, "utf-8").trim(), 10);
242
+ try {
243
+ process.kill(existingPid, 0);
244
+ throw new EchoError(ErrorCodes.ZG_MONITOR_ALREADY_RUNNING, `Balance monitor already running (PID ${existingPid})`, "Run: echo 0g-compute monitor stop");
245
+ }
246
+ catch (err) {
247
+ if (err instanceof EchoError)
248
+ throw err;
249
+ logger.debug(`[Monitor] Removing stale pidfile (PID ${existingPid})`);
250
+ unlinkSync(ZG_MONITOR_PID_FILE);
251
+ }
252
+ }
253
+ writeFileSync(ZG_MONITOR_PID_FILE, String(process.pid), "utf-8");
254
+ logger.debug(`[Monitor] PID file written: ${process.pid}`);
255
+ }
256
+ cleanupShutdownFile() {
257
+ try {
258
+ if (existsSync(ZG_MONITOR_SHUTDOWN_FILE)) {
259
+ unlinkSync(ZG_MONITOR_SHUTDOWN_FILE);
260
+ }
261
+ }
262
+ catch { /* ignore */ }
263
+ }
264
+ saveState() {
265
+ try {
266
+ if (!existsSync(ZG_COMPUTE_DIR)) {
267
+ mkdirSync(ZG_COMPUTE_DIR, { recursive: true });
268
+ }
269
+ writeFileSync(ZG_MONITOR_STATE_FILE, JSON.stringify(this.state, null, 2), "utf-8");
270
+ }
271
+ catch (err) {
272
+ logger.warn(`[Monitor] Failed to save state: ${err instanceof Error ? err.message : String(err)}`);
273
+ }
274
+ }
275
+ stop() {
276
+ if (this.shuttingDown)
277
+ return;
278
+ this.shuttingDown = true;
279
+ logger.info("[Monitor] Shutting down...");
280
+ if (this.shutdownWatcher) {
281
+ clearInterval(this.shutdownWatcher);
282
+ this.shutdownWatcher = null;
283
+ }
284
+ if (this.pollTimer) {
285
+ clearTimeout(this.pollTimer);
286
+ this.pollTimer = null;
287
+ }
288
+ try {
289
+ if (existsSync(ZG_MONITOR_PID_FILE))
290
+ unlinkSync(ZG_MONITOR_PID_FILE);
291
+ }
292
+ catch { /* ignore */ }
293
+ try {
294
+ if (existsSync(ZG_MONITOR_SHUTDOWN_FILE))
295
+ unlinkSync(ZG_MONITOR_SHUTDOWN_FILE);
296
+ }
297
+ catch { /* ignore */ }
298
+ logger.info("[Monitor] Stopped");
299
+ process.exit(0);
300
+ }
301
+ }
302
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/0g-compute/monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Pricing heuristics for 0G Compute providers.
3
+ *
4
+ * SDK prices (`inputPrice`, `outputPrice`) are **per-token in neuron**
5
+ * (1 0G = 10^18 neuron). The CLI needs to:
6
+ * 1. Display prices as "per 1M tokens" (human-readable).
7
+ * 2. Compute a recommended minimum locked balance per provider.
8
+ *
9
+ * Upstream SDK constants for reference:
10
+ * topUpTriggerThreshold = 1_000_000 (tokens)
11
+ * topUpTargetThreshold = 2_000_000 (tokens)
12
+ */
13
+ /** Default token budget — matches upstream `topUpTargetThreshold`. */
14
+ export declare const DEFAULT_TOKEN_BUDGET = 2000000n;
15
+ /** Alert when locked balance < recommendedMin * alertRatio. */
16
+ export declare const DEFAULT_ALERT_RATIO = 1.2;
17
+ export interface ProviderPricing {
18
+ /** Recommended minimum locked balance in 0G. */
19
+ recommendedMinLockedOg: number;
20
+ /** Alert threshold: balance below this triggers a warning. */
21
+ recommendedAlertLockedOg: number;
22
+ /** Cost (neuron) for the given token budget. */
23
+ costNeuron: bigint;
24
+ }
25
+ /**
26
+ * Calculate recommended locked balance for a provider.
27
+ *
28
+ * Formula (mirrors upstream SDK top-up logic):
29
+ * ```
30
+ * costNeuron = tokenBudget * (inputPrice + outputPrice)
31
+ * recommendedMinLockedOg = max(1.0, formatUnits(costNeuron, 18))
32
+ * recommendedAlertLockedOg = recommendedMinLockedOg * alertRatio
33
+ * ```
34
+ */
35
+ export declare function calculateProviderPricing(inputPriceNeuron: bigint, outputPriceNeuron: bigint, tokenBudget?: bigint, alertRatio?: number): ProviderPricing;
36
+ /**
37
+ * Format a per-token neuron price as "X.XXXX 0G/M tokens".
38
+ *
39
+ * SDK prices are **per single token**. To get per-1M-tokens:
40
+ * `pricePerM = priceNeuron * 1_000_000`.
41
+ */
42
+ export declare function formatPricePerMTokens(priceNeuron: bigint): string;
43
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/0g-compute/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,WAAa,CAAC;AAE/C,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAOvC,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,8DAA8D;IAC9D,wBAAwB,EAAE,MAAM,CAAC;IACjC,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,WAAW,GAAE,MAA6B,EAC1C,UAAU,GAAE,MAA4B,GACvC,eAAe,CAYjB;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGjE"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Pricing heuristics for 0G Compute providers.
3
+ *
4
+ * SDK prices (`inputPrice`, `outputPrice`) are **per-token in neuron**
5
+ * (1 0G = 10^18 neuron). The CLI needs to:
6
+ * 1. Display prices as "per 1M tokens" (human-readable).
7
+ * 2. Compute a recommended minimum locked balance per provider.
8
+ *
9
+ * Upstream SDK constants for reference:
10
+ * topUpTriggerThreshold = 1_000_000 (tokens)
11
+ * topUpTargetThreshold = 2_000_000 (tokens)
12
+ */
13
+ import { formatUnits } from "ethers";
14
+ // ── Constants ────────────────────────────────────────────────────────
15
+ /** Default token budget — matches upstream `topUpTargetThreshold`. */
16
+ export const DEFAULT_TOKEN_BUDGET = 2000000n;
17
+ /** Alert when locked balance < recommendedMin * alertRatio. */
18
+ export const DEFAULT_ALERT_RATIO = 1.2;
19
+ /** Minimum recommended locked balance in 0G — floor to avoid tiny values. */
20
+ const MIN_RECOMMENDED_OG = 1.0;
21
+ /**
22
+ * Calculate recommended locked balance for a provider.
23
+ *
24
+ * Formula (mirrors upstream SDK top-up logic):
25
+ * ```
26
+ * costNeuron = tokenBudget * (inputPrice + outputPrice)
27
+ * recommendedMinLockedOg = max(1.0, formatUnits(costNeuron, 18))
28
+ * recommendedAlertLockedOg = recommendedMinLockedOg * alertRatio
29
+ * ```
30
+ */
31
+ export function calculateProviderPricing(inputPriceNeuron, outputPriceNeuron, tokenBudget = DEFAULT_TOKEN_BUDGET, alertRatio = DEFAULT_ALERT_RATIO) {
32
+ const costNeuron = tokenBudget * (inputPriceNeuron + outputPriceNeuron);
33
+ const costOg = parseFloat(formatUnits(costNeuron, 18));
34
+ const recommendedMinLockedOg = Math.max(MIN_RECOMMENDED_OG, costOg);
35
+ const recommendedAlertLockedOg = recommendedMinLockedOg * alertRatio;
36
+ return {
37
+ recommendedMinLockedOg,
38
+ recommendedAlertLockedOg,
39
+ costNeuron,
40
+ };
41
+ }
42
+ // ── Display helpers ──────────────────────────────────────────────────
43
+ /**
44
+ * Format a per-token neuron price as "X.XXXX 0G/M tokens".
45
+ *
46
+ * SDK prices are **per single token**. To get per-1M-tokens:
47
+ * `pricePerM = priceNeuron * 1_000_000`.
48
+ */
49
+ export function formatPricePerMTokens(priceNeuron) {
50
+ const perM = priceNeuron * 1000000n;
51
+ return formatUnits(perM, 18);
52
+ }
53
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/0g-compute/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,wEAAwE;AAExE,sEAAsE;AACtE,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAU,CAAC;AAE/C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,6EAA6E;AAC7E,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAa/B;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CACtC,gBAAwB,EACxB,iBAAyB,EACzB,cAAsB,oBAAoB,EAC1C,aAAqB,mBAAmB;IAExC,MAAM,UAAU,GAAG,WAAW,GAAG,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAEvD,MAAM,sBAAsB,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,wBAAwB,GAAG,sBAAsB,GAAG,UAAU,CAAC;IAErE,OAAO;QACL,sBAAsB;QACtB,wBAAwB;QACxB,UAAU;KACX,CAAC;AACJ,CAAC;AAED,wEAAwE;AAExE;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,MAAM,IAAI,GAAG,WAAW,GAAG,QAAU,CAAC;IACtC,OAAO,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /**
3
+ * CJS bridge module — ethers resolves to lib.commonjs here, matching SDK types.
4
+ * This eliminates the #private nominal type mismatch between ESM and CJS Wallet.
5
+ *
6
+ * All parameters are plain strings — no ethers types cross the ESM/CJS boundary.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createBrokerFromKey = createBrokerFromKey;
10
+ const ethers_1 = require("ethers");
11
+ const _0g_serving_broker_1 = require("@0glabs/0g-serving-broker");
12
+ async function createBrokerFromKey(privateKey, rpcUrl) {
13
+ const provider = new ethers_1.JsonRpcProvider(rpcUrl);
14
+ const wallet = new ethers_1.Wallet(privateKey, provider);
15
+ return (0, _0g_serving_broker_1.createZGComputeNetworkBroker)(wallet);
16
+ }
17
+ //# sourceMappingURL=sdk-bridge.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-bridge.cjs","sourceRoot":"","sources":["../../src/0g-compute/sdk-bridge.cts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAMH,kDAOC;AAXD,mCAAiD;AACjD,kEAAyE;AAGlE,KAAK,UAAU,mBAAmB,CACvC,UAAkB,EAClB,MAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,wBAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAChD,OAAO,IAAA,iDAA4B,EAAC,MAAM,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * CJS bridge module — ethers resolves to lib.commonjs here, matching SDK types.
3
+ * This eliminates the #private nominal type mismatch between ESM and CJS Wallet.
4
+ *
5
+ * All parameters are plain strings — no ethers types cross the ESM/CJS boundary.
6
+ */
7
+ import type { ZGComputeNetworkBroker } from "@0glabs/0g-serving-broker";
8
+ export declare function createBrokerFromKey(privateKey: string, rpcUrl: string): Promise<ZGComputeNetworkBroker>;
9
+ //# sourceMappingURL=sdk-bridge.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-bridge.d.cts","sourceRoot":"","sources":["../../src/0g-compute/sdk-bridge.cts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAExE,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,sBAAsB,CAAC,CAIjC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 0G Compute SDK smoke-test — standalone script.
3
+ *
4
+ * Validates end-to-end: npm SDK + Echo wallet → list → ledger → API key → inference.
5
+ * Run after `npm run build`:
6
+ * ECHO_KEYSTORE_PASSWORD=xxx node dist/0g-compute/smoke-test.js [--provider 0x...] [--dry-run]
7
+ *
8
+ * Default provider: 0x1B3AAe... (deepseek-chat-v3-0324, cheapest chatbot).
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=smoke-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke-test.d.ts","sourceRoot":"","sources":["../../src/0g-compute/smoke-test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * 0G Compute SDK smoke-test — standalone script.
3
+ *
4
+ * Validates end-to-end: npm SDK + Echo wallet → list → ledger → API key → inference.
5
+ * Run after `npm run build`:
6
+ * ECHO_KEYSTORE_PASSWORD=xxx node dist/0g-compute/smoke-test.js [--provider 0x...] [--dry-run]
7
+ *
8
+ * Default provider: 0x1B3AAe... (deepseek-chat-v3-0324, cheapest chatbot).
9
+ */
10
+ import { parseArgs } from "node:util";
11
+ import { formatUnits, getAddress } from "ethers";
12
+ import { requireWalletAndKeystore } from "../bot/executor.js";
13
+ import { createBrokerFromKey } from "./sdk-bridge.cjs";
14
+ import { withSuppressedConsole } from "./bridge.js";
15
+ import { loadConfig } from "../config/store.js";
16
+ import logger from "../utils/logger.js";
17
+ function normalizeAddress(raw) {
18
+ const trimmed = raw.trim();
19
+ try {
20
+ return getAddress(trimmed);
21
+ }
22
+ catch {
23
+ if (/^0x[0-9a-fA-F]{40}$/.test(trimmed)) {
24
+ return `0x${trimmed.slice(2).toLowerCase()}`;
25
+ }
26
+ throw new Error(`Invalid address: ${raw}`);
27
+ }
28
+ }
29
+ function redactToken(token) {
30
+ if (token.startsWith("app-sk-"))
31
+ return "app-sk-***";
32
+ return "***";
33
+ }
34
+ async function main() {
35
+ const { values } = parseArgs({
36
+ options: {
37
+ provider: { type: "string" },
38
+ "dry-run": { type: "boolean", default: false },
39
+ },
40
+ strict: false,
41
+ });
42
+ const providerArg = values.provider;
43
+ const dryRun = values["dry-run"];
44
+ logger.info("[smoke-test] Starting 0G Compute SDK smoke test");
45
+ logger.info(`[smoke-test] Provider: ${providerArg ?? "(auto)"}`);
46
+ logger.info(`[smoke-test] Dry run: ${dryRun}`);
47
+ // 1. Get wallet
48
+ const { address, privateKey } = requireWalletAndKeystore();
49
+ logger.info(`[smoke-test] Wallet: ${address}`);
50
+ // 2. Create authenticated broker via CJS bridge (avoids ESM/CJS type mismatch)
51
+ const cfg = loadConfig();
52
+ const broker = await withSuppressedConsole(() => createBrokerFromKey(privateKey, cfg.chain.rpcUrl));
53
+ logger.info("[smoke-test] Broker initialized");
54
+ // 3. List services
55
+ const services = await broker.inference.listService();
56
+ logger.info(`[smoke-test] Found ${services.length} services:`);
57
+ for (const svc of services) {
58
+ const provider = typeof svc.provider === "string" ? svc.provider : (typeof svc[0] === "string" ? svc[0] : String(svc[0]));
59
+ const model = typeof svc.model === "string" ? svc.model : (typeof svc[6] === "string" ? svc[6] : String(svc[6]));
60
+ const url = typeof svc.url === "string" ? svc.url : (typeof svc[2] === "string" ? svc[2] : String(svc[2]));
61
+ logger.info(` - ${model} (provider: ${provider.slice(0, 10)}..., url: ${url})`);
62
+ }
63
+ // Choose provider
64
+ const selectedProviderRaw = providerArg
65
+ ? providerArg
66
+ : (services.find((s) => s.serviceType === "chatbot")?.provider ??
67
+ services[0]?.provider ??
68
+ services[0]?.[0]);
69
+ const providerAddress = normalizeAddress(String(selectedProviderRaw));
70
+ logger.info(`[smoke-test] Using provider: ${providerAddress}`);
71
+ // Metadata (read-only)
72
+ let metadata = null;
73
+ try {
74
+ metadata = await broker.inference.getServiceMetadata(providerAddress);
75
+ logger.info(`[smoke-test] Model: ${metadata.model}`);
76
+ logger.info(`[smoke-test] Endpoint: ${metadata.endpoint}`);
77
+ }
78
+ catch (err) {
79
+ logger.warn(`[smoke-test] Failed to fetch service metadata: ${err instanceof Error ? err.message : String(err)}`);
80
+ }
81
+ // 4. Check ledger
82
+ try {
83
+ const ledger = await broker.ledger.getLedger();
84
+ logger.info(`[smoke-test] Ledger found: ${JSON.stringify(ledger, (_k, v) => typeof v === "bigint" ? formatUnits(v, 18) + " 0G" : v)}`);
85
+ }
86
+ catch (err) {
87
+ logger.warn(`[smoke-test] No ledger found: ${err instanceof Error ? err.message : String(err)}`);
88
+ logger.warn("[smoke-test] Hint: create ledger with `echo 0g-compute ledger deposit <amount> --yes`");
89
+ }
90
+ // 5. Check sub-account balance
91
+ try {
92
+ const account = await broker.inference.getAccount(providerAddress);
93
+ logger.info(`[smoke-test] Sub-account: ${JSON.stringify(account, (_k, v) => typeof v === "bigint" ? formatUnits(v, 18) + " 0G" : v)}`);
94
+ }
95
+ catch (err) {
96
+ logger.warn(`[smoke-test] No sub-account for provider: ${err instanceof Error ? err.message : String(err)}`);
97
+ }
98
+ // 6. Check user-level ack (read-only)
99
+ let userAcked = false;
100
+ try {
101
+ userAcked = await broker.inference.acknowledged(providerAddress);
102
+ logger.info(`[smoke-test] User acknowledged: ${userAcked}`);
103
+ }
104
+ catch (err) {
105
+ logger.warn(`[smoke-test] Failed to check user acknowledgement: ${err instanceof Error ? err.message : String(err)}`);
106
+ }
107
+ if (dryRun) {
108
+ logger.info("[smoke-test] Dry run complete — skipping ack, API key, and inference.");
109
+ const result = {
110
+ step: "dry-run",
111
+ services: services.length,
112
+ provider: providerAddress,
113
+ model: metadata?.model ?? null,
114
+ endpoint: metadata?.endpoint ?? null,
115
+ userAcked,
116
+ };
117
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
118
+ return;
119
+ }
120
+ // 8. Acknowledge provider signer (idempotent)
121
+ logger.info("[smoke-test] Acknowledging provider signer...");
122
+ await withSuppressedConsole(() => broker.inference.acknowledgeProviderSigner(providerAddress));
123
+ logger.info("[smoke-test] Provider signer acknowledged");
124
+ // 9. Create API key
125
+ logger.info("[smoke-test] Creating API key (tokenId=0, never expires)...");
126
+ const apiKeyInfo = await withSuppressedConsole(() => broker.inference.requestProcessor.createApiKey(providerAddress, { tokenId: 0, expiresIn: 0 }));
127
+ logger.info(`[smoke-test] API key created: tokenId=${apiKeyInfo.tokenId}, token=${redactToken(apiKeyInfo.rawToken)}`);
128
+ // 10. Make inference request
129
+ const metadata2 = metadata ?? (await broker.inference.getServiceMetadata(providerAddress));
130
+ const inferenceUrl = `${metadata2.endpoint}/chat/completions`;
131
+ logger.info(`[smoke-test] Inference URL: ${inferenceUrl}`);
132
+ logger.info(`[smoke-test] Model: ${metadata2.model}`);
133
+ const response = await fetch(inferenceUrl, {
134
+ method: "POST",
135
+ headers: {
136
+ "Content-Type": "application/json",
137
+ Authorization: `Bearer ${apiKeyInfo.rawToken}`,
138
+ },
139
+ body: JSON.stringify({
140
+ model: metadata2.model,
141
+ messages: [{ role: "user", content: "Say hello in one sentence." }],
142
+ max_tokens: 50,
143
+ }),
144
+ signal: AbortSignal.timeout(60_000),
145
+ });
146
+ if (!response.ok) {
147
+ const body = await response.text();
148
+ logger.error(`[smoke-test] Inference failed: ${response.status} ${body}`);
149
+ process.exit(1);
150
+ }
151
+ const inferenceResult = await response.json();
152
+ logger.info(`[smoke-test] Inference response: ${JSON.stringify(inferenceResult).slice(0, 500)}`);
153
+ // Summary (rawToken REDACTED)
154
+ const summary = {
155
+ step: "complete",
156
+ wallet: address,
157
+ provider: providerAddress,
158
+ model: metadata2.model,
159
+ endpoint: metadata2.endpoint,
160
+ apiKey: { tokenId: apiKeyInfo.tokenId, token: redactToken(apiKeyInfo.rawToken) },
161
+ inferenceStatus: response.status,
162
+ };
163
+ process.stdout.write(JSON.stringify(summary, null, 2) + "\n");
164
+ }
165
+ main().catch((err) => {
166
+ logger.error(`[smoke-test] Fatal: ${err instanceof Error ? err.message : String(err)}`);
167
+ if (err instanceof Error && err.stack) {
168
+ logger.debug(err.stack);
169
+ }
170
+ process.exit(1);
171
+ });
172
+ //# sourceMappingURL=smoke-test.js.map