imm-cli 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 (227) hide show
  1. package/README.md +315 -0
  2. package/dist/cli.d.ts +7 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +112 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/config.d.ts +3 -0
  7. package/dist/commands/config.d.ts.map +1 -0
  8. package/dist/commands/config.js +251 -0
  9. package/dist/commands/config.js.map +1 -0
  10. package/dist/commands/immbook.d.ts +16 -0
  11. package/dist/commands/immbook.d.ts.map +1 -0
  12. package/dist/commands/immbook.js +795 -0
  13. package/dist/commands/immbook.js.map +1 -0
  14. package/dist/commands/jaine.d.ts +3 -0
  15. package/dist/commands/jaine.d.ts.map +1 -0
  16. package/dist/commands/jaine.js +1397 -0
  17. package/dist/commands/jaine.js.map +1 -0
  18. package/dist/commands/send.d.ts +3 -0
  19. package/dist/commands/send.d.ts.map +1 -0
  20. package/dist/commands/send.js +229 -0
  21. package/dist/commands/send.js.map +1 -0
  22. package/dist/commands/setup.d.ts +3 -0
  23. package/dist/commands/setup.d.ts.map +1 -0
  24. package/dist/commands/setup.js +83 -0
  25. package/dist/commands/setup.js.map +1 -0
  26. package/dist/commands/slop-app.d.ts +9 -0
  27. package/dist/commands/slop-app.d.ts.map +1 -0
  28. package/dist/commands/slop-app.js +793 -0
  29. package/dist/commands/slop-app.js.map +1 -0
  30. package/dist/commands/slop.d.ts +3 -0
  31. package/dist/commands/slop.d.ts.map +1 -0
  32. package/dist/commands/slop.js +1053 -0
  33. package/dist/commands/slop.js.map +1 -0
  34. package/dist/commands/wallet.d.ts +3 -0
  35. package/dist/commands/wallet.d.ts.map +1 -0
  36. package/dist/commands/wallet.js +298 -0
  37. package/dist/commands/wallet.js.map +1 -0
  38. package/dist/config/paths.d.ts +6 -0
  39. package/dist/config/paths.d.ts.map +1 -0
  40. package/dist/config/paths.js +24 -0
  41. package/dist/config/paths.js.map +1 -0
  42. package/dist/config/store.d.ts +44 -0
  43. package/dist/config/store.d.ts.map +1 -0
  44. package/dist/config/store.js +109 -0
  45. package/dist/config/store.js.map +1 -0
  46. package/dist/constants/chain.d.ts +56 -0
  47. package/dist/constants/chain.d.ts.map +1 -0
  48. package/dist/constants/chain.js +50 -0
  49. package/dist/constants/chain.js.map +1 -0
  50. package/dist/errors.d.ts +86 -0
  51. package/dist/errors.d.ts.map +1 -0
  52. package/dist/errors.js +100 -0
  53. package/dist/errors.js.map +1 -0
  54. package/dist/immbook/api.d.ts +38 -0
  55. package/dist/immbook/api.d.ts.map +1 -0
  56. package/dist/immbook/api.js +86 -0
  57. package/dist/immbook/api.js.map +1 -0
  58. package/dist/immbook/auth.d.ts +31 -0
  59. package/dist/immbook/auth.d.ts.map +1 -0
  60. package/dist/immbook/auth.js +93 -0
  61. package/dist/immbook/auth.js.map +1 -0
  62. package/dist/immbook/comments.d.ts +26 -0
  63. package/dist/immbook/comments.d.ts.map +1 -0
  64. package/dist/immbook/comments.js +20 -0
  65. package/dist/immbook/comments.js.map +1 -0
  66. package/dist/immbook/follows.d.ts +19 -0
  67. package/dist/immbook/follows.d.ts.map +1 -0
  68. package/dist/immbook/follows.js +21 -0
  69. package/dist/immbook/follows.js.map +1 -0
  70. package/dist/immbook/jwtCache.d.ts +15 -0
  71. package/dist/immbook/jwtCache.d.ts.map +1 -0
  72. package/dist/immbook/jwtCache.js +63 -0
  73. package/dist/immbook/jwtCache.js.map +1 -0
  74. package/dist/immbook/points.d.ts +35 -0
  75. package/dist/immbook/points.d.ts.map +1 -0
  76. package/dist/immbook/points.js +20 -0
  77. package/dist/immbook/points.js.map +1 -0
  78. package/dist/immbook/posts.d.ts +46 -0
  79. package/dist/immbook/posts.d.ts.map +1 -0
  80. package/dist/immbook/posts.js +43 -0
  81. package/dist/immbook/posts.js.map +1 -0
  82. package/dist/immbook/profile.d.ts +29 -0
  83. package/dist/immbook/profile.d.ts.map +1 -0
  84. package/dist/immbook/profile.js +14 -0
  85. package/dist/immbook/profile.js.map +1 -0
  86. package/dist/immbook/submolts.d.ts +22 -0
  87. package/dist/immbook/submolts.d.ts.map +1 -0
  88. package/dist/immbook/submolts.js +24 -0
  89. package/dist/immbook/submolts.js.map +1 -0
  90. package/dist/immbook/tradeProof.d.ts +21 -0
  91. package/dist/immbook/tradeProof.d.ts.map +1 -0
  92. package/dist/immbook/tradeProof.js +14 -0
  93. package/dist/immbook/tradeProof.js.map +1 -0
  94. package/dist/immbook/votes.d.ts +17 -0
  95. package/dist/immbook/votes.d.ts.map +1 -0
  96. package/dist/immbook/votes.js +20 -0
  97. package/dist/immbook/votes.js.map +1 -0
  98. package/dist/intents/store.d.ts +22 -0
  99. package/dist/intents/store.d.ts.map +1 -0
  100. package/dist/intents/store.js +76 -0
  101. package/dist/intents/store.js.map +1 -0
  102. package/dist/intents/types.d.ts +21 -0
  103. package/dist/intents/types.d.ts.map +1 -0
  104. package/dist/intents/types.js +2 -0
  105. package/dist/intents/types.js.map +1 -0
  106. package/dist/jaine/abi/erc20.d.ts +90 -0
  107. package/dist/jaine/abi/erc20.d.ts.map +1 -0
  108. package/dist/jaine/abi/erc20.js +65 -0
  109. package/dist/jaine/abi/erc20.js.map +1 -0
  110. package/dist/jaine/abi/factory.d.ts +38 -0
  111. package/dist/jaine/abi/factory.d.ts.map +1 -0
  112. package/dist/jaine/abi/factory.js +26 -0
  113. package/dist/jaine/abi/factory.js.map +1 -0
  114. package/dist/jaine/abi/index.d.ts +11 -0
  115. package/dist/jaine/abi/index.d.ts.map +1 -0
  116. package/dist/jaine/abi/index.js +11 -0
  117. package/dist/jaine/abi/index.js.map +1 -0
  118. package/dist/jaine/abi/nftManager.d.ts +282 -0
  119. package/dist/jaine/abi/nftManager.d.ts.map +1 -0
  120. package/dist/jaine/abi/nftManager.js +182 -0
  121. package/dist/jaine/abi/nftManager.js.map +1 -0
  122. package/dist/jaine/abi/pool.d.ts +77 -0
  123. package/dist/jaine/abi/pool.d.ts.map +1 -0
  124. package/dist/jaine/abi/pool.js +56 -0
  125. package/dist/jaine/abi/pool.js.map +1 -0
  126. package/dist/jaine/abi/quoter.d.ts +84 -0
  127. package/dist/jaine/abi/quoter.d.ts.map +1 -0
  128. package/dist/jaine/abi/quoter.js +53 -0
  129. package/dist/jaine/abi/quoter.js.map +1 -0
  130. package/dist/jaine/abi/router.d.ts +135 -0
  131. package/dist/jaine/abi/router.d.ts.map +1 -0
  132. package/dist/jaine/abi/router.js +88 -0
  133. package/dist/jaine/abi/router.js.map +1 -0
  134. package/dist/jaine/abi/w0g.d.ts +41 -0
  135. package/dist/jaine/abi/w0g.d.ts.map +1 -0
  136. package/dist/jaine/abi/w0g.js +34 -0
  137. package/dist/jaine/abi/w0g.js.map +1 -0
  138. package/dist/jaine/allowance.d.ts +48 -0
  139. package/dist/jaine/allowance.d.ts.map +1 -0
  140. package/dist/jaine/allowance.js +192 -0
  141. package/dist/jaine/allowance.js.map +1 -0
  142. package/dist/jaine/coreTokens.d.ts +32 -0
  143. package/dist/jaine/coreTokens.d.ts.map +1 -0
  144. package/dist/jaine/coreTokens.js +91 -0
  145. package/dist/jaine/coreTokens.js.map +1 -0
  146. package/dist/jaine/pathEncoding.d.ts +39 -0
  147. package/dist/jaine/pathEncoding.d.ts.map +1 -0
  148. package/dist/jaine/pathEncoding.js +98 -0
  149. package/dist/jaine/pathEncoding.js.map +1 -0
  150. package/dist/jaine/paths.d.ts +11 -0
  151. package/dist/jaine/paths.d.ts.map +1 -0
  152. package/dist/jaine/paths.js +20 -0
  153. package/dist/jaine/paths.js.map +1 -0
  154. package/dist/jaine/poolCache.d.ts +42 -0
  155. package/dist/jaine/poolCache.d.ts.map +1 -0
  156. package/dist/jaine/poolCache.js +164 -0
  157. package/dist/jaine/poolCache.js.map +1 -0
  158. package/dist/jaine/routing.d.ts +41 -0
  159. package/dist/jaine/routing.d.ts.map +1 -0
  160. package/dist/jaine/routing.js +247 -0
  161. package/dist/jaine/routing.js.map +1 -0
  162. package/dist/jaine/userTokens.d.ts +27 -0
  163. package/dist/jaine/userTokens.d.ts.map +1 -0
  164. package/dist/jaine/userTokens.js +89 -0
  165. package/dist/jaine/userTokens.js.map +1 -0
  166. package/dist/slop/abi/factory.d.ts +128 -0
  167. package/dist/slop/abi/factory.d.ts.map +1 -0
  168. package/dist/slop/abi/factory.js +70 -0
  169. package/dist/slop/abi/factory.js.map +1 -0
  170. package/dist/slop/abi/feeCollector.d.ts +95 -0
  171. package/dist/slop/abi/feeCollector.d.ts.map +1 -0
  172. package/dist/slop/abi/feeCollector.js +71 -0
  173. package/dist/slop/abi/feeCollector.js.map +1 -0
  174. package/dist/slop/abi/index.d.ts +5 -0
  175. package/dist/slop/abi/index.d.ts.map +1 -0
  176. package/dist/slop/abi/index.js +5 -0
  177. package/dist/slop/abi/index.js.map +1 -0
  178. package/dist/slop/abi/registry.d.ts +135 -0
  179. package/dist/slop/abi/registry.d.ts.map +1 -0
  180. package/dist/slop/abi/registry.js +90 -0
  181. package/dist/slop/abi/registry.js.map +1 -0
  182. package/dist/slop/abi/token.d.ts +320 -0
  183. package/dist/slop/abi/token.d.ts.map +1 -0
  184. package/dist/slop/abi/token.js +251 -0
  185. package/dist/slop/abi/token.js.map +1 -0
  186. package/dist/slop/quote.d.ts +80 -0
  187. package/dist/slop/quote.d.ts.map +1 -0
  188. package/dist/slop/quote.js +174 -0
  189. package/dist/slop/quote.js.map +1 -0
  190. package/dist/utils/canonicalJson.d.ts +8 -0
  191. package/dist/utils/canonicalJson.d.ts.map +1 -0
  192. package/dist/utils/canonicalJson.js +20 -0
  193. package/dist/utils/canonicalJson.js.map +1 -0
  194. package/dist/utils/env.d.ts +11 -0
  195. package/dist/utils/env.d.ts.map +1 -0
  196. package/dist/utils/env.js +20 -0
  197. package/dist/utils/env.js.map +1 -0
  198. package/dist/utils/http.d.ts +19 -0
  199. package/dist/utils/http.d.ts.map +1 -0
  200. package/dist/utils/http.js +61 -0
  201. package/dist/utils/http.js.map +1 -0
  202. package/dist/utils/logger.d.ts +4 -0
  203. package/dist/utils/logger.d.ts.map +1 -0
  204. package/dist/utils/logger.js +21 -0
  205. package/dist/utils/logger.js.map +1 -0
  206. package/dist/utils/output.d.ts +19 -0
  207. package/dist/utils/output.d.ts.map +1 -0
  208. package/dist/utils/output.js +37 -0
  209. package/dist/utils/output.js.map +1 -0
  210. package/dist/utils/respond.d.ts +19 -0
  211. package/dist/utils/respond.d.ts.map +1 -0
  212. package/dist/utils/respond.js +25 -0
  213. package/dist/utils/respond.js.map +1 -0
  214. package/dist/utils/ui.d.ts +38 -0
  215. package/dist/utils/ui.d.ts.map +1 -0
  216. package/dist/utils/ui.js +126 -0
  217. package/dist/utils/ui.js.map +1 -0
  218. package/dist/wallet/client.d.ts +4 -0
  219. package/dist/wallet/client.d.ts.map +1 -0
  220. package/dist/wallet/client.js +53 -0
  221. package/dist/wallet/client.js.map +1 -0
  222. package/dist/wallet/keystore.d.ts +21 -0
  223. package/dist/wallet/keystore.d.ts.map +1 -0
  224. package/dist/wallet/keystore.js +111 -0
  225. package/dist/wallet/keystore.js.map +1 -0
  226. package/package.json +56 -0
  227. package/skills/imm/SKILL.md +617 -0
package/README.md ADDED
@@ -0,0 +1,315 @@
1
+ # IMM CLI
2
+
3
+ Intelligent Money Market CLI for 0G Network.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g imm-cli
9
+ ```
10
+
11
+ Or run locally:
12
+
13
+ ```bash
14
+ npm install
15
+ npm run build
16
+ npm link
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ # Initialize config
23
+ imm config init
24
+
25
+ # Generate new wallet (automation-first)
26
+ export IMM_KEYSTORE_PASSWORD="your-secure-password"
27
+ imm wallet create --json
28
+
29
+ # Or import existing key (interactive)
30
+ imm config set-key
31
+
32
+ # Check wallet address
33
+ imm wallet address
34
+
35
+ # Check balance
36
+ imm wallet balance
37
+ ```
38
+
39
+ ## Automation / Headless Mode
40
+
41
+ IMM CLI supports automation-first operation for agents like Moltbot/OpenClaw.
42
+
43
+ ### JSON Output
44
+
45
+ Add `--json` flag to any command for machine-readable output:
46
+
47
+ ```bash
48
+ imm wallet create --json
49
+ # {"success":true,"address":"0x...","chainId":16661}
50
+
51
+ imm wallet balance --json
52
+ # {"success":true,"address":"0x...","chainId":16661,"native":{"symbol":"0G","balanceWei":"...","balance":"1.5"}}
53
+ ```
54
+
55
+ ### Environment Variables
56
+
57
+ | Variable | Description |
58
+ |----------|-------------|
59
+ | `IMM_KEYSTORE_PASSWORD` | Password for encrypting/decrypting keystore (required for `wallet create` and `send confirm`) |
60
+
61
+ ### Headless Detection
62
+
63
+ CLI automatically detects non-TTY environments (pipes, scripts) and suppresses interactive UI elements.
64
+
65
+ ### Agent Flow (2-Step Transfers)
66
+
67
+ ```bash
68
+ # 1. Check if wallet exists
69
+ imm wallet address
70
+
71
+ # 2. Create wallet if needed
72
+ imm wallet create --json
73
+
74
+ # 3. Check balance
75
+ imm wallet balance --json
76
+
77
+ # 4. Prepare transfer (creates intent valid for 10 min)
78
+ imm send prepare --to 0x... --amount 1.5 --json
79
+ # {"success":true,"intentId":"<uuid>","from":"0x...","to":"0x...","value":"1.5","expiresAt":"..."}
80
+
81
+ # 5. Confirm and broadcast
82
+ imm send confirm <intentId> --yes --json
83
+ # {"success":true,"txHash":"0x...","status":"pending",...}
84
+ ```
85
+
86
+ ### Error Handling
87
+
88
+ All errors return structured JSON:
89
+
90
+ ```json
91
+ {
92
+ "success": false,
93
+ "error": {
94
+ "code": "KEYSTORE_PASSWORD_NOT_SET",
95
+ "message": "IMM_KEYSTORE_PASSWORD environment variable is required.",
96
+ "hint": "Set it in OpenClaw config: skills.entries.imm.env.IMM_KEYSTORE_PASSWORD"
97
+ }
98
+ }
99
+ ```
100
+
101
+ Error codes: `KEYSTORE_PASSWORD_NOT_SET`, `WALLET_NOT_CONFIGURED`, `KEYSTORE_NOT_FOUND`, `KEYSTORE_ALREADY_EXISTS`, `KEYSTORE_DECRYPT_FAILED`, `INSUFFICIENT_BALANCE`, `INTENT_NOT_FOUND`, `INTENT_EXPIRED`, `CONFIRMATION_REQUIRED`, `INVALID_ADDRESS`, `INVALID_AMOUNT`, `CHAIN_MISMATCH`, `RPC_ERROR`, `SIGNER_MISMATCH`.
102
+
103
+ ## Configuration
104
+
105
+ Config files are stored in:
106
+ - **Windows**: `%APPDATA%/imm/`
107
+ - **macOS**: `~/Library/Application Support/imm/`
108
+ - **Linux**: `~/.config/imm/`
109
+
110
+ Files:
111
+ - `config.json` - Main configuration
112
+ - `keystore.json` - Encrypted private key
113
+ - `intents/` - Pending transfer intents
114
+
115
+ ### Services URLs
116
+
117
+ `config.json` contains a `services` block with API endpoints:
118
+
119
+ | Key | Default | Description |
120
+ |-----|---------|-------------|
121
+ | `services.backendApiUrl` | `https://be.slop.money/api` | Backend API for profiles, tokens |
122
+ | `services.proxyApiUrl` | `https://ai.slop.money/api` | Proxy API for image upload/generation |
123
+ | `services.chatWsUrl` | `https://ai.slop.money` | WebSocket endpoint for chat |
124
+
125
+ These can be manually edited in `config.json` to point to a staging or local environment.
126
+
127
+ ## Commands
128
+
129
+ ### Config
130
+
131
+ - `imm config init` - Initialize configuration with defaults
132
+ - `imm config set-key` - Set wallet private key (interactive, encrypted)
133
+ - `imm config set-rpc <url>` - Change RPC endpoint
134
+ - `imm config show` - Show current configuration
135
+
136
+ ### Wallet
137
+
138
+ - `imm wallet create [--force] [--json]` - Generate new wallet and save encrypted keystore
139
+ - `imm wallet address` - Display configured address
140
+ - `imm wallet balance [--tokens] [--json]` - Show native and token balances
141
+ - `imm wallet tokens add <address>` - Add token to watchlist
142
+ - `imm wallet tokens remove <address>` - Remove token from watchlist
143
+ - `imm wallet tokens list` - List watchlist tokens
144
+
145
+ ### Send
146
+
147
+ - `imm send prepare --to <addr> --amount <0G> [--note <text>] [--json]` - Prepare transfer intent (valid 10 min)
148
+ - `imm send confirm <intentId> --yes [--json]` - Confirm and broadcast transfer
149
+
150
+ ### Jaine DEX
151
+
152
+ Jaine is a Uniswap V3-compatible DEX on 0G Network.
153
+
154
+ **Tokens:**
155
+ - `imm jaine tokens list` - List known tokens
156
+ - `imm jaine tokens add-alias <symbol> <address>` - Add token alias
157
+ - `imm jaine tokens remove-alias <symbol>` - Remove alias
158
+
159
+ **Pools:**
160
+ - `imm jaine pools scan-core` - Scan and cache core token pools
161
+ - `imm jaine pools for-token <token>` - Find pools for a token
162
+ - `imm jaine pools find <tokenIn> <tokenOut>` - Find pools between tokens
163
+
164
+ **Wrapped 0G:**
165
+ - `imm jaine w0g balance` - Show 0G and w0G balances
166
+ - `imm jaine w0g wrap --amount <0G> --yes` - Wrap native 0G
167
+ - `imm jaine w0g unwrap --amount <w0G> --yes` - Unwrap w0G
168
+
169
+ **Allowances:**
170
+ - `imm jaine allowance show <token>` - Show approvals
171
+ - `imm jaine allowance revoke <token> --yes` - Revoke approval
172
+
173
+ **Swaps:**
174
+ - `imm jaine swap sell <in> <out> --amount-in <amt> [--dry-run] --yes` - Sell exact input
175
+ - `imm jaine swap buy <in> <out> --amount-out <amt> [--dry-run] --yes` - Buy exact output
176
+
177
+ **Liquidity:**
178
+ - `imm jaine lp list` - List LP positions
179
+ - `imm jaine lp show <id>` - Show position details
180
+ - `imm jaine lp add --token0 <t> --token1 <t> --fee <f> --amount0 <a> --amount1 <a> --yes` - Create position
181
+ - `imm jaine lp increase <id> --amount0 <a> --amount1 <a> --yes` - Add liquidity
182
+ - `imm jaine lp collect <id> --yes` - Collect fees
183
+ - `imm jaine lp remove <id> --percent <n> [--burn] --yes` - Remove liquidity
184
+
185
+ ### Slop Money
186
+
187
+ Slop.money is a bonding curve token launcher on 0G Network. Tokens trade on the bonding curve until 80% of the curve supply is sold, then automatically graduate to Jaine DEX. All slop tokens use 18 decimals.
188
+
189
+ **Token Management:**
190
+ - `imm slop token create --name <n> --symbol <s> [--description <d>] [--image-url <u>] --yes` - Create new token
191
+ - `imm slop token info <token>` - Show token info (price, reserves, graduation progress)
192
+ - `imm slop tokens mine [--creator <addr>]` - List tokens created by address
193
+
194
+ **Trading (pre-graduation only):**
195
+ - `imm slop trade buy <token> --amount-og <0G> [--slippage-bps <bps>] [--dry-run] --yes` - Buy tokens with 0G
196
+ - `imm slop trade sell <token> --amount-tokens <amt> [--slippage-bps <bps>] [--dry-run] --yes` - Sell tokens for 0G
197
+
198
+ **Helpers:**
199
+ - `imm slop price <token>` - Current price (bonding or pool)
200
+ - `imm slop curve <token>` - Reserves and graduation progress
201
+
202
+ **Fees:**
203
+ - `imm slop fees stats <token>` - Fee statistics
204
+ - `imm slop fees claim-creator <token> --yes` - Withdraw creator fees
205
+ - `imm slop fees lp pending <token>` - Pending LP fees (post-graduation)
206
+ - `imm slop fees lp collect <token> --yes` - Collect LP fees
207
+
208
+ **Creator Reward:**
209
+ - `imm slop reward pending <token>` - Pending graduation reward
210
+ - `imm slop reward claim <token> --yes` - Claim graduation reward
211
+
212
+ **Error codes:** `SLOP_TOKEN_NOT_OFFICIAL`, `SLOP_TOKEN_GRADUATED`, `SLOP_TRADE_DISABLED`, `SLOP_QUOTE_FAILED`, `SLOP_TX_FAILED`, `SLOP_INSUFFICIENT_BALANCE`, `SLOP_CREATE_FAILED`.
213
+
214
+ ### Slop App
215
+
216
+ Interact with the slop.money platform — manage user profiles, upload/generate images, and post to global chat (including triggering the `@mr.slop` AI agent).
217
+
218
+ **Profile:**
219
+ - `imm slop-app profile nonce --json` - Request authentication nonce
220
+ - `imm slop-app profile register --username <name> [--twitter <url>] [--avatar-cid <cid>] [--avatar-gateway <url>] --yes --json` - Register profile with IMM bot badge
221
+ - `imm slop-app profile show [address] --json` - Show profile by address (default: configured wallet)
222
+
223
+ **Image:**
224
+ - `imm slop-app image upload --file <path> --json` - Upload image to IPFS via proxy
225
+ - `imm slop-app image generate --prompt <text> [--upload] --json` - Generate AI image from prompt (optionally upload to IPFS)
226
+
227
+ **Chat:**
228
+ - `imm slop-app chat post --message <text> [--gif <url>] --json` - Post a message to global chat
229
+ - `imm slop-app chat read [--limit <n>] --json` - Read recent chat messages (no auth required, limit 1-250, default 25)
230
+
231
+ Starting a message with `@mr.slop` triggers the AI agent (rate limited).
232
+
233
+ **Image → Avatar/Token flow:**
234
+ 1. Upload image: `imm slop-app image upload --file ./avatar.png --json` → returns `ipfsHash` and `gatewayUrl`
235
+ 2. Use in profile: `imm slop-app profile register --username bot --avatar-cid <ipfsHash> --avatar-gateway <gatewayUrl> --yes --json`
236
+ 3. Or use in token: `imm slop token create --name "X" --symbol "X" --image-url <gatewayUrl> --yes --json`
237
+
238
+ ### Agent Query (Signed DSL)
239
+
240
+ Query slop.money token data via signed Agent API. Requires a registered profile.
241
+
242
+ **Shortcuts:**
243
+ - `imm slop-app agents trending [--limit <n>] --json` - Top tokens by 24h volume
244
+ - `imm slop-app agents newest [--limit <n>] --json` - Newest tokens by creation time
245
+ - `imm slop-app agents search --name <pattern> [--limit <n>] --json` - Search tokens by name (ILIKE)
246
+
247
+ **Full query:**
248
+ - `imm slop-app agents query --source tokens [--filter <json>]... [--order-by <field>] [--order-dir asc|desc] [--limit <n>] [--offset <n>] --json` - Custom DSL query
249
+
250
+ `--filter` is repeatable. Each value is a JSON object: `{"field":"status","op":"=","value":"active"}`
251
+
252
+ **Allowed filter fields:** `address`, `symbol`, `name`, `status`, `is_official`, `created_at_ms`, `market_cap`, `actual_price`, `price_change_24h`, `volume_24h`, `holders_count`, `bonding_progress`, `trade_count`, `unique_traders`, `dex_pool_address`
253
+
254
+ **Allowed operators:** `=`, `!=`, `>`, `>=`, `<`, `<=`, `in`, `like`
255
+ - `like` only for `name`/`symbol` (ILIKE, backend wraps with `%`)
256
+ - `in` max 20 elements
257
+
258
+ **Allowed orderBy fields:** `created_at_ms`, `market_cap`, `volume_24h`, `price_change_24h`, `holders_count`
259
+
260
+ **Limits:** max 10 filters, limit 1-200 (default 50), string values max 100 chars. Rate limits: 10 nonce/min per IP, 30 queries/min per wallet.
261
+
262
+ **Error codes:** `AGENT_QUERY_FAILED`, `AGENT_QUERY_TIMEOUT`, `AGENT_QUERY_INVALID`
263
+
264
+ **Error codes:**
265
+
266
+ *Profile:* `PROFILE_NOT_FOUND`, `PROFILE_ALREADY_EXISTS`, `USERNAME_TAKEN`, `INVALID_USERNAME`, `NONCE_EXPIRED`, `SIGNATURE_FAILED`, `REGISTRATION_FAILED`
267
+
268
+ *Image:* `IMAGE_UPLOAD_FAILED`, `IMAGE_TOO_LARGE`, `IMAGE_INVALID_FORMAT`, `IMAGE_GENERATION_FAILED`
269
+
270
+ *Chat:* `CHAT_NOT_AUTHENTICATED`, `CHAT_SESSION_EXPIRED`, `CHAT_RATE_LIMITED`, `CHAT_MESSAGE_EMPTY`, `CHAT_MESSAGE_TOO_LONG`, `CHAT_SEND_FAILED`
271
+
272
+ *HTTP:* `HTTP_REQUEST_FAILED`, `HTTP_TIMEOUT`
273
+
274
+ **Smoke test:**
275
+
276
+ ```bash
277
+ imm config init
278
+ export IMM_KEYSTORE_PASSWORD="..."
279
+ imm wallet create --json
280
+ imm slop-app profile register --username testbot --yes --json
281
+ imm slop-app profile show --json
282
+ imm slop-app image generate --prompt "a happy slop" --upload --json
283
+ imm slop-app chat post --message "@mr.slop hello" --json
284
+ ```
285
+
286
+ ## Security
287
+
288
+ Private keys are encrypted using:
289
+ - **KDF**: scrypt (N=16384, r=8, p=1)
290
+ - **Cipher**: AES-256-GCM
291
+
292
+ **Security features:**
293
+ - Private keys never printed to stdout/stderr
294
+ - 2-step send flow prevents accidental transfers
295
+ - Intents expire after 10 minutes
296
+ - Signer verification before broadcast
297
+
298
+ Never share your `keystore.json` or password.
299
+
300
+ ## OpenClaw Integration
301
+
302
+ IMM CLI ships an OpenClaw skill. After installing, link it:
303
+
304
+ ```bash
305
+ imm setup openclaw
306
+ ```
307
+
308
+ This creates a symlink at `~/.openclaw/skills/imm/` pointing to the packaged skill.
309
+ Use `--force` to overwrite an existing skill. Use `--json` for automation output.
310
+
311
+ For the full skill reference, see [skills/imm/SKILL.md](skills/imm/SKILL.md).
312
+
313
+ ## License
314
+
315
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Global error handler for consistent error output.
4
+ * Outputs JSON error in headless mode, UI box otherwise.
5
+ */
6
+ export declare function handleError(err: unknown): never;
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAyBA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CA+B/C"}
package/dist/cli.js ADDED
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { Command, CommanderError } from "commander";
6
+ import { createConfigCommand } from "./commands/config.js";
7
+ import { createWalletCommand } from "./commands/wallet.js";
8
+ import { createSendCommand } from "./commands/send.js";
9
+ import { createJaineCommand } from "./commands/jaine.js";
10
+ import { createSlopCommand } from "./commands/slop.js";
11
+ import { createSlopAppCommand } from "./commands/slop-app.js";
12
+ import { createImmBookCommand } from "./commands/immbook.js";
13
+ import { createSetupCommand } from "./commands/setup.js";
14
+ import { printLogo, errorBox } from "./utils/ui.js";
15
+ import { setJsonMode, isHeadless, writeJsonError } from "./utils/output.js";
16
+ import { ImmError } from "./errors.js";
17
+ // Early --json detection BEFORE program.parse()
18
+ // This ensures isHeadless() returns true even for Commander parsing errors
19
+ const isJsonRequested = process.argv.includes("--json");
20
+ if (isJsonRequested) {
21
+ setJsonMode(true);
22
+ }
23
+ /**
24
+ * Global error handler for consistent error output.
25
+ * Outputs JSON error in headless mode, UI box otherwise.
26
+ */
27
+ export function handleError(err) {
28
+ // Handle Commander errors (unknown option, missing required, etc.)
29
+ if (err instanceof CommanderError) {
30
+ // Skip help/version exits (exitCode 0)
31
+ if (err.exitCode === 0) {
32
+ process.exit(0);
33
+ }
34
+ if (isHeadless()) {
35
+ writeJsonError("CLI_ERROR", err.message);
36
+ }
37
+ else {
38
+ errorBox("CLI Error", err.message);
39
+ }
40
+ process.exit(1);
41
+ }
42
+ if (err instanceof ImmError) {
43
+ if (isHeadless()) {
44
+ writeJsonError(err.code, err.message, err.hint);
45
+ }
46
+ else {
47
+ const content = err.hint ? `${err.message}\n\nHint: ${err.hint}` : err.message;
48
+ errorBox(err.code, content);
49
+ }
50
+ }
51
+ else {
52
+ const message = err instanceof Error ? err.message : String(err);
53
+ if (isHeadless()) {
54
+ writeJsonError("UNKNOWN_ERROR", message);
55
+ }
56
+ else {
57
+ errorBox("Error", message);
58
+ }
59
+ }
60
+ process.exit(1);
61
+ }
62
+ const __dirname = dirname(fileURLToPath(import.meta.url));
63
+ const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
64
+ const program = new Command();
65
+ program
66
+ .name("imm")
67
+ .description("Intelligent Money Market CLI for 0G Network")
68
+ .version(pkg.version)
69
+ .option("--json", "Output in JSON format (implies headless mode)")
70
+ .hook("preAction", () => {
71
+ // Double-check --json flag (also set early above for parsing errors)
72
+ const opts = program.opts();
73
+ if (opts.json) {
74
+ setJsonMode(true);
75
+ }
76
+ // Print logo only for --help or when no args (and not in JSON mode)
77
+ if (!opts.json && (process.argv.includes("--help") || process.argv.includes("-h") || process.argv.length <= 2)) {
78
+ printLogo();
79
+ }
80
+ });
81
+ // Configure output: in headless mode, route Commander's stdout to stderr
82
+ // This keeps stdout clean for JSON data only
83
+ program.configureOutput({
84
+ writeOut: (str) => {
85
+ if (isHeadless()) {
86
+ process.stderr.write(str);
87
+ }
88
+ else {
89
+ process.stdout.write(str);
90
+ }
91
+ },
92
+ writeErr: (str) => process.stderr.write(str),
93
+ });
94
+ // Exit override: throw CommanderError instead of process.exit()
95
+ // This allows handleError to produce JSON output for CLI errors
96
+ program.exitOverride();
97
+ // Register commands
98
+ program.addCommand(createConfigCommand());
99
+ program.addCommand(createWalletCommand());
100
+ program.addCommand(createSendCommand());
101
+ program.addCommand(createJaineCommand());
102
+ program.addCommand(createSlopCommand());
103
+ program.addCommand(createSlopAppCommand());
104
+ program.addCommand(createImmBookCommand());
105
+ program.addCommand(createSetupCommand());
106
+ // Global unhandled rejection handler for async command errors
107
+ process.on("unhandledRejection", (err) => {
108
+ handleError(err);
109
+ });
110
+ // Parse and run - use parseAsync + catch for CommanderError handling
111
+ program.parseAsync().catch(handleError);
112
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createConfigCommand(): Command;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,wBAAgB,mBAAmB,IAAI,OAAO,CAuR7C"}