@needmoretruth/nmts-cli 0.17.2 → 0.34.2

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 (419) hide show
  1. package/AGENTS.md +125 -517
  2. package/CHANGELOG.md +104 -0
  3. package/README.ko.md +377 -469
  4. package/README.md +394 -474
  5. package/dist/account-proof.d.ts +29 -0
  6. package/dist/account-proof.js +6 -6
  7. package/dist/account.d.ts +18 -0
  8. package/dist/account.js +5 -5
  9. package/dist/agent-host.d.ts +71 -0
  10. package/dist/agent-host.js +169 -0
  11. package/dist/api-advice.d.ts +2 -0
  12. package/dist/api-advice.js +210 -0
  13. package/dist/api-key.d.ts +79 -0
  14. package/dist/api-key.js +7 -7
  15. package/dist/api-refusal.d.ts +14 -0
  16. package/dist/api-refusal.js +8 -0
  17. package/dist/api.d.ts +114 -0
  18. package/dist/api.js +59 -162
  19. package/dist/args.d.ts +160 -0
  20. package/dist/args.js +118 -30
  21. package/dist/artifact-about.d.ts +49 -0
  22. package/dist/autonomy.d.ts +39 -0
  23. package/dist/autonomy.js +110 -32
  24. package/dist/code-access.d.ts +29 -0
  25. package/dist/code-access.js +3 -3
  26. package/dist/code-vault.d.ts +38 -0
  27. package/dist/code-vault.js +8 -8
  28. package/dist/collision.d.ts +67 -0
  29. package/dist/collision.js +1 -1
  30. package/dist/commands/accept-terms.d.ts +11 -0
  31. package/dist/commands/accept-terms.js +106 -0
  32. package/dist/commands/balance.d.ts +7 -0
  33. package/dist/commands/balance.js +54 -1
  34. package/dist/commands/create-code-file.d.ts +24 -0
  35. package/dist/commands/create-code-file.js +93 -0
  36. package/dist/commands/create-link.d.ts +10 -0
  37. package/dist/commands/create-link.js +232 -0
  38. package/dist/commands/create.d.ts +20 -0
  39. package/dist/commands/create.js +43 -102
  40. package/dist/commands/credits.d.ts +9 -0
  41. package/dist/commands/credits.js +110 -0
  42. package/dist/commands/delete-account.d.ts +11 -0
  43. package/dist/commands/delete-account.js +63 -0
  44. package/dist/commands/deposit.d.ts +7 -0
  45. package/dist/commands/deposit.js +85 -0
  46. package/dist/commands/devices.d.ts +12 -0
  47. package/dist/commands/devices.js +144 -0
  48. package/dist/commands/documents.d.ts +35 -0
  49. package/dist/commands/documents.js +212 -0
  50. package/dist/commands/env.d.ts +5 -0
  51. package/dist/commands/env.js +10 -2
  52. package/dist/commands/erase.d.ts +13 -0
  53. package/dist/commands/erase.js +193 -0
  54. package/dist/commands/expiring.d.ts +19 -0
  55. package/dist/commands/extend.d.ts +33 -0
  56. package/dist/commands/extend.js +54 -15
  57. package/dist/commands/get.d.ts +18 -0
  58. package/dist/commands/key-manage.d.ts +11 -0
  59. package/dist/commands/key-manage.js +162 -0
  60. package/dist/commands/key.d.ts +28 -0
  61. package/dist/commands/key.js +249 -0
  62. package/dist/commands/kit.d.ts +11 -0
  63. package/dist/commands/kit.js +7 -7
  64. package/dist/commands/listfile.d.ts +13 -0
  65. package/dist/commands/listfile.js +12 -5
  66. package/dist/commands/login.d.ts +18 -0
  67. package/dist/commands/login.js +19 -19
  68. package/dist/commands/logout.d.ts +1 -0
  69. package/dist/commands/logout.js +1 -1
  70. package/dist/commands/losses.d.ts +12 -0
  71. package/dist/commands/losses.js +180 -0
  72. package/dist/commands/ls.d.ts +23 -0
  73. package/dist/commands/marks-dispatch.d.ts +2 -0
  74. package/dist/commands/marks-dispatch.js +51 -0
  75. package/dist/commands/marks.d.ts +46 -0
  76. package/dist/commands/marks.js +80 -0
  77. package/dist/commands/mcp.d.ts +24 -0
  78. package/dist/commands/mcp.js +70 -5
  79. package/dist/commands/mode.d.ts +8 -0
  80. package/dist/commands/mode.js +60 -24
  81. package/dist/commands/on-collision.d.ts +6 -0
  82. package/dist/commands/organise.d.ts +46 -0
  83. package/dist/commands/padding.d.ts +7 -0
  84. package/dist/commands/padding.js +114 -0
  85. package/dist/commands/public-code.d.ts +9 -0
  86. package/dist/commands/public-code.js +8 -8
  87. package/dist/commands/pull.d.ts +27 -0
  88. package/dist/commands/push-wallet.d.ts +19 -0
  89. package/dist/commands/push-wallet.js +69 -0
  90. package/dist/commands/push.d.ts +47 -0
  91. package/dist/commands/push.js +37 -7
  92. package/dist/commands/put-wallet.d.ts +77 -0
  93. package/dist/commands/put-wallet.js +316 -0
  94. package/dist/commands/put.d.ts +56 -0
  95. package/dist/commands/put.js +53 -6
  96. package/dist/commands/rebuild.d.ts +18 -0
  97. package/dist/commands/rebuild.js +108 -10
  98. package/dist/commands/receive.d.ts +24 -0
  99. package/dist/commands/recovery-dispatch.d.ts +2 -0
  100. package/dist/commands/recovery-dispatch.js +34 -0
  101. package/dist/commands/recovery-list.d.ts +11 -0
  102. package/dist/commands/recovery-list.js +6 -6
  103. package/dist/commands/recovery.d.ts +25 -0
  104. package/dist/commands/recovery.js +2 -2
  105. package/dist/commands/rollback.d.ts +9 -0
  106. package/dist/commands/rollback.js +118 -0
  107. package/dist/commands/s3.d.ts +23 -0
  108. package/dist/commands/s3.js +6 -6
  109. package/dist/commands/settings.d.ts +5 -0
  110. package/dist/commands/settings.js +21 -6
  111. package/dist/commands/share-dispatch.d.ts +2 -0
  112. package/dist/commands/share-dispatch.js +46 -0
  113. package/dist/commands/share.d.ts +14 -0
  114. package/dist/commands/share.js +13 -3
  115. package/dist/commands/shares-sent.d.ts +18 -0
  116. package/dist/commands/shares-sent.js +95 -0
  117. package/dist/commands/support.d.ts +24 -0
  118. package/dist/commands/support.js +321 -0
  119. package/dist/commands/sweep.d.ts +11 -0
  120. package/dist/commands/tip.d.ts +11 -0
  121. package/dist/commands/tip.js +86 -0
  122. package/dist/commands/trash.d.ts +17 -0
  123. package/dist/commands/trash.js +1 -1
  124. package/dist/commands/trial.d.ts +7 -0
  125. package/dist/commands/trial.js +16 -18
  126. package/dist/commands/unlock.d.ts +16 -0
  127. package/dist/commands/unlock.js +159 -0
  128. package/dist/commands/update.d.ts +42 -0
  129. package/dist/commands/update.js +1 -1
  130. package/dist/commands/usage.d.ts +8 -0
  131. package/dist/commands/verify.d.ts +18 -0
  132. package/dist/commands/verify.js +10 -6
  133. package/dist/commands/wallet-activity.d.ts +26 -0
  134. package/dist/commands/wallet-activity.js +117 -0
  135. package/dist/commands/wallet-donate.d.ts +26 -0
  136. package/dist/commands/wallet-donate.js +163 -0
  137. package/dist/commands/wallet-hall.d.ts +35 -0
  138. package/dist/commands/wallet-hall.js +214 -0
  139. package/dist/commands/wallet-send.d.ts +22 -0
  140. package/dist/commands/wallet-send.js +153 -0
  141. package/dist/commands/wallet-storage-ops.d.ts +24 -0
  142. package/dist/commands/wallet-storage-ops.js +215 -0
  143. package/dist/commands/wallet-storage.d.ts +18 -0
  144. package/dist/commands/wallet-storage.js +95 -0
  145. package/dist/commands/wallet-swap.d.ts +32 -0
  146. package/dist/commands/wallet-swap.js +287 -0
  147. package/dist/commands/wallet.d.ts +36 -0
  148. package/dist/commands/wallet.js +57 -15
  149. package/dist/commands/whoami.d.ts +10 -0
  150. package/dist/commands/whoami.js +24 -6
  151. package/dist/consent.d.ts +140 -0
  152. package/dist/consent.js +89 -30
  153. package/dist/credentials.d.ts +146 -0
  154. package/dist/credentials.js +10 -10
  155. package/dist/crypto-surface.d.ts +197 -0
  156. package/dist/crypto.d.ts +81 -0
  157. package/dist/crypto.js +13 -0
  158. package/dist/deposit.d.ts +25 -0
  159. package/dist/deposit.js +78 -0
  160. package/dist/download-part.d.ts +40 -0
  161. package/dist/download-sink.d.ts +76 -0
  162. package/dist/download.d.ts +79 -0
  163. package/dist/download.js +3 -3
  164. package/dist/drive-paths.d.ts +73 -0
  165. package/dist/environment.d.ts +62 -0
  166. package/dist/environment.js +29 -9
  167. package/dist/errors.d.ts +22 -0
  168. package/dist/errors.js +3 -3
  169. package/dist/exit.d.ts +44 -0
  170. package/dist/expiry.d.ts +58 -0
  171. package/dist/extend-budget.d.ts +35 -0
  172. package/dist/extend-budget.js +81 -0
  173. package/dist/extend-chain.d.ts +43 -0
  174. package/dist/extend-chain.js +40 -3
  175. package/dist/extend-plan.d.ts +148 -0
  176. package/dist/extend-plan.js +1 -1
  177. package/dist/gate.d.ts +18 -0
  178. package/dist/gate.js +100 -0
  179. package/dist/guards.d.ts +2 -0
  180. package/dist/help.d.ts +20 -0
  181. package/dist/help.js +199 -33
  182. package/dist/human-check.d.ts +23 -0
  183. package/dist/index.d.ts +42 -0
  184. package/dist/index.js +49 -0
  185. package/dist/item-trash.d.ts +1 -0
  186. package/dist/kit-file.d.ts +56 -0
  187. package/dist/kit-file.js +10 -10
  188. package/dist/list-file.d.ts +88 -0
  189. package/dist/list-file.js +90 -7
  190. package/dist/list-view-find.d.ts +15 -0
  191. package/dist/list-view-order.d.ts +32 -0
  192. package/dist/main.d.ts +12 -0
  193. package/dist/main.js +112 -113
  194. package/dist/manifest-chunk-cache.d.ts +14 -0
  195. package/dist/manifest-chunk-cache.js +103 -0
  196. package/dist/manifest-chunk-flow.d.ts +81 -0
  197. package/dist/manifest-chunk-flow.js +307 -0
  198. package/dist/manifest-create.d.ts +23 -0
  199. package/dist/manifest-create.js +26 -30
  200. package/dist/manifest-write.d.ts +161 -0
  201. package/dist/manifest-write.js +42 -33
  202. package/dist/manifest.d.ts +82 -0
  203. package/dist/manifest.js +69 -21
  204. package/dist/mark-render.d.ts +26 -0
  205. package/dist/mcp-args.d.ts +17 -0
  206. package/dist/mcp-ask.d.ts +43 -0
  207. package/dist/mcp-ask.js +100 -0
  208. package/dist/mcp-tools/context.d.ts +46 -0
  209. package/dist/mcp-tools/credits.d.ts +3 -0
  210. package/dist/mcp-tools/credits.js +61 -0
  211. package/dist/mcp-tools/files.d.ts +3 -0
  212. package/dist/mcp-tools/files.js +34 -0
  213. package/dist/mcp-tools/organise.d.ts +3 -0
  214. package/dist/mcp-tools/organise.js +82 -2
  215. package/dist/mcp-tools/reads.d.ts +3 -0
  216. package/dist/mcp-tools/reads.js +132 -4
  217. package/dist/mcp-tools/share.d.ts +3 -0
  218. package/dist/mcp-tools/share.js +26 -7
  219. package/dist/mcp-tools/support.d.ts +3 -0
  220. package/dist/mcp-tools/support.js +140 -0
  221. package/dist/mcp-tools/tiers.d.ts +31 -0
  222. package/dist/mcp-tools/tiers.js +147 -0
  223. package/dist/mcp.d.ts +80 -0
  224. package/dist/mcp.js +110 -9
  225. package/dist/net-retry.d.ts +38 -0
  226. package/dist/network.d.ts +10 -0
  227. package/dist/notice.d.ts +7 -0
  228. package/dist/notice.js +7 -7
  229. package/dist/product.d.ts +29 -0
  230. package/dist/product.js +1 -1
  231. package/dist/progress.d.ts +37 -0
  232. package/dist/prompt.d.ts +31 -0
  233. package/dist/prompt.js +1 -1
  234. package/dist/rebuild-key-check.d.ts +26 -0
  235. package/dist/rebuild-key-check.js +90 -0
  236. package/dist/rebuild.d.ts +87 -0
  237. package/dist/rebuild.js +26 -4
  238. package/dist/recovery-assemble.d.ts +40 -0
  239. package/dist/recovery-assemble.js +1 -1
  240. package/dist/recovery-build.d.ts +40 -0
  241. package/dist/recovery-map-file.d.ts +53 -0
  242. package/dist/recovery-map-file.js +4 -4
  243. package/dist/recovery-map.d.ts +197 -0
  244. package/dist/recovery-release.d.ts +104 -0
  245. package/dist/recovery-seq.d.ts +10 -0
  246. package/dist/recovery-source.d.ts +50 -0
  247. package/dist/redact.d.ts +70 -0
  248. package/dist/redact.js +212 -0
  249. package/dist/registration.d.ts +30 -0
  250. package/dist/registration.js +5 -5
  251. package/dist/risk.d.ts +380 -0
  252. package/dist/risk.js +206 -0
  253. package/dist/run-log.d.ts +78 -0
  254. package/dist/run-log.js +301 -0
  255. package/dist/s3/listing.d.ts +47 -0
  256. package/dist/s3/multipart.d.ts +21 -0
  257. package/dist/s3/response-sink.d.ts +8 -0
  258. package/dist/s3/same-file.d.ts +54 -0
  259. package/dist/s3/server.d.ts +58 -0
  260. package/dist/s3/server.js +2 -2
  261. package/dist/s3/sigv4.d.ts +46 -0
  262. package/dist/s3/sigv4.js +1 -1
  263. package/dist/s3/staging.d.ts +10 -0
  264. package/dist/s3/xml.d.ts +28 -0
  265. package/dist/safe-path.d.ts +41 -0
  266. package/dist/seal.d.ts +120 -0
  267. package/dist/secret-reader.d.ts +28 -0
  268. package/dist/server.d.ts +9 -0
  269. package/dist/session.d.ts +32 -0
  270. package/dist/session.js +1 -1
  271. package/dist/setup-questions.d.ts +7 -0
  272. package/dist/share.d.ts +108 -0
  273. package/dist/share.js +1 -1
  274. package/dist/shared/lib/crypto/size-padding.d.ts +55 -0
  275. package/dist/shared/lib/crypto/size-padding.js +5 -0
  276. package/dist/shared/lib/drive/manifest-chunks.d.ts +95 -0
  277. package/dist/shared/lib/drive/manifest-chunks.js +252 -0
  278. package/dist/shared/lib/drive/manifest-codec.d.ts +214 -0
  279. package/dist/shared/lib/drive/manifest-codec.js +7 -7
  280. package/dist/shared/lib/drive/manifest-index.d.ts +98 -0
  281. package/dist/shared/lib/drive/manifest-ops.d.ts +167 -0
  282. package/dist/shared/lib/drive/manifest-ops.js +9 -4
  283. package/dist/shared/lib/drive/manifest-pack.d.ts +65 -0
  284. package/dist/shared/lib/drive/manifest-pack.js +287 -0
  285. package/dist/shared/lib/drive/manifest-settings.d.ts +113 -0
  286. package/dist/shared/lib/drive/manifest-settings.js +87 -6
  287. package/dist/shared/lib/drive/name-conflict.d.ts +76 -0
  288. package/dist/shared/lib/drive/rebuild-verify.d.ts +73 -0
  289. package/dist/shared/lib/drive/rebuild-verify.js +112 -0
  290. package/dist/shared/lib/drive/unique-name.d.ts +9 -0
  291. package/dist/shared/lib/drive/zstd.d.ts +27 -0
  292. package/dist/shared/lib/drive/zstd.js +74 -0
  293. package/dist/shared/lib/extend/epochs.d.ts +205 -0
  294. package/dist/shared/lib/net/retry-budget.d.ts +79 -0
  295. package/dist/shared/lib/share/shared-file-info.d.ts +21 -0
  296. package/dist/shared/lib/storage-control/chain.d.ts +57 -0
  297. package/dist/shared/lib/storage-control/chain.js +82 -0
  298. package/dist/shared/lib/storage-control/plan.d.ts +40 -0
  299. package/dist/shared/lib/storage-control/plan.js +72 -0
  300. package/dist/shared/lib/storage-control/reuse.d.ts +72 -0
  301. package/dist/shared/lib/storage-control/reuse.js +95 -0
  302. package/dist/shared/lib/storage-network.d.ts +25 -0
  303. package/dist/shared/lib/upload/part-plan.d.ts +24 -0
  304. package/dist/shared/lib/wallet/activity.d.ts +138 -0
  305. package/dist/shared/lib/wallet/activity.js +208 -0
  306. package/dist/shared/lib/wallet/send-rules.d.ts +68 -0
  307. package/dist/shared/lib/wallet/send-rules.js +116 -0
  308. package/dist/shared/lib/wallet/swap-rules.d.ts +115 -0
  309. package/dist/shared/lib/wallet/swap-rules.js +199 -0
  310. package/dist/shared/lib/wallet/tip.d.ts +14 -0
  311. package/dist/shared/lib/wallet/tip.js +34 -0
  312. package/dist/shared/lib/wallet/venue-ids.d.ts +23 -0
  313. package/dist/shared/lib/wallet/venue-ids.js +53 -0
  314. package/dist/standing-tip.d.ts +24 -0
  315. package/dist/standing-tip.js +52 -0
  316. package/dist/stdout.d.ts +38 -0
  317. package/dist/storage-control-chain.d.ts +38 -0
  318. package/dist/storage-control-chain.js +78 -0
  319. package/dist/sui-rpc.d.ts +15 -0
  320. package/dist/sui-rpc.js +59 -0
  321. package/dist/support-attach.d.ts +24 -0
  322. package/dist/support-attach.js +72 -0
  323. package/dist/support-copy.d.ts +42 -0
  324. package/dist/support-copy.js +109 -0
  325. package/dist/support-wire.d.ts +49 -0
  326. package/dist/support-wire.js +194 -0
  327. package/dist/trash-sweep.d.ts +55 -0
  328. package/dist/units.d.ts +2 -0
  329. package/dist/update-check.d.ts +50 -0
  330. package/dist/update-source.d.ts +63 -0
  331. package/dist/upload-api.d.ts +3 -0
  332. package/dist/upload-file.d.ts +97 -0
  333. package/dist/upload-file.js +3 -2
  334. package/dist/upload-price.d.ts +50 -0
  335. package/dist/upload-steps.d.ts +26 -0
  336. package/dist/upload-steps.js +29 -9
  337. package/dist/upload-store.d.ts +182 -0
  338. package/dist/upload-wallet-chain.d.ts +54 -0
  339. package/dist/upload-wallet-chain.js +203 -0
  340. package/dist/upload-wallet-plan.d.ts +128 -0
  341. package/dist/upload-wallet-plan.js +184 -0
  342. package/dist/upload-wallet.d.ts +24 -0
  343. package/dist/upload-wallet.js +208 -0
  344. package/dist/upload-wire.d.ts +244 -0
  345. package/dist/upload.d.ts +18 -0
  346. package/dist/upload.js +10 -0
  347. package/dist/usage-report.d.ts +35 -0
  348. package/dist/wallet-activity-chain.d.ts +5 -0
  349. package/dist/wallet-activity-chain.js +31 -0
  350. package/dist/wallet-chain.d.ts +19 -0
  351. package/dist/wallet-chain.js +2 -2
  352. package/dist/wallet-grant.d.ts +50 -0
  353. package/dist/wallet-grant.js +218 -0
  354. package/dist/wallet-send-chain.d.ts +24 -0
  355. package/dist/wallet-send-chain.js +49 -0
  356. package/dist/wallet-sign.d.ts +133 -0
  357. package/dist/wallet-sign.js +317 -0
  358. package/dist/wallet-storage-chain.d.ts +3 -0
  359. package/dist/wallet-storage-chain.js +20 -0
  360. package/dist/wallet-swap-chain.d.ts +52 -0
  361. package/dist/wallet-swap-chain.js +186 -0
  362. package/dist/wallet-swap-quote.d.ts +22 -0
  363. package/dist/wallet-swap-quote.js +126 -0
  364. package/dist/wallet.d.ts +135 -0
  365. package/dist/wallet.js +5 -5
  366. package/dist/walrus-write.d.ts +56 -0
  367. package/dist/walrus-write.js +5 -4
  368. package/dist/walrus.d.ts +86 -0
  369. package/dist/walrus.js +48 -10
  370. package/dist/zstd-node.d.ts +11 -0
  371. package/dist/zstd-node.js +71 -0
  372. package/docs/commands/accept-terms.md +15 -0
  373. package/docs/commands/create.md +17 -0
  374. package/docs/commands/credits.md +34 -0
  375. package/docs/commands/delete-account.md +14 -0
  376. package/docs/commands/deposit.md +27 -0
  377. package/docs/commands/devices.md +9 -0
  378. package/docs/commands/documents.md +10 -0
  379. package/docs/commands/env.md +21 -0
  380. package/docs/commands/extend.md +27 -0
  381. package/docs/commands/folders.md +10 -0
  382. package/docs/commands/get.md +14 -0
  383. package/docs/commands/key.md +14 -0
  384. package/docs/commands/login.md +23 -0
  385. package/docs/commands/logout.md +11 -0
  386. package/docs/commands/losses.md +13 -0
  387. package/docs/commands/ls.md +16 -0
  388. package/docs/commands/marks.md +9 -0
  389. package/docs/commands/mcp.md +33 -0
  390. package/docs/commands/mode.md +29 -0
  391. package/docs/commands/on-collision.md +13 -0
  392. package/docs/commands/padding.md +13 -0
  393. package/docs/commands/public-code.md +9 -0
  394. package/docs/commands/pull.md +9 -0
  395. package/docs/commands/push.md +12 -0
  396. package/docs/commands/put.md +36 -0
  397. package/docs/commands/rebuild.md +13 -0
  398. package/docs/commands/recovery.md +18 -0
  399. package/docs/commands/s3.md +17 -0
  400. package/docs/commands/share.md +15 -0
  401. package/docs/commands/support.md +16 -0
  402. package/docs/commands/tip.md +21 -0
  403. package/docs/commands/trash.md +25 -0
  404. package/docs/commands/trial.md +12 -0
  405. package/docs/commands/unlock.md +25 -0
  406. package/docs/commands/update.md +14 -0
  407. package/docs/commands/usage.md +14 -0
  408. package/docs/commands/verify.md +18 -0
  409. package/docs/commands/wallet.md +67 -0
  410. package/docs/commands/whoami.md +12 -0
  411. package/package.json +67 -8
  412. package/server.json +28 -0
  413. package/vendor/nmts-crypto/nmts_crypto_wasm.d.ts +23 -2
  414. package/vendor/nmts-crypto/nmts_crypto_wasm.js +44 -2
  415. package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm +0 -0
  416. package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm.d.ts +1 -0
  417. package/vendor/nmts-crypto/package.json +1 -1
  418. package/dist/commands/consent.js +0 -77
  419. package/dist/extend-sign.js +0 -130
@@ -0,0 +1,11 @@
1
+ export interface SweepOptions {
2
+ server?: string | undefined;
3
+ network?: string | undefined;
4
+ json?: boolean;
5
+ /** Go ahead and drop them. Without this the run reports and changes nothing. */
6
+ yes?: boolean;
7
+ write?: (line: string) => void;
8
+ /** The instant to measure the thirty days against. Passed in so one run means one moment. */
9
+ now?: number;
10
+ }
11
+ export declare function sweep(options?: SweepOptions): Promise<number>;
@@ -0,0 +1,11 @@
1
+ export interface TipOptions {
2
+ server?: string | undefined;
3
+ network?: string | undefined;
4
+ json?: boolean;
5
+ yes?: boolean;
6
+ write?: (line: string) => void;
7
+ /** Injected in tests: answers the one confirmation above the dial's end. */
8
+ readLine?: ((question: string) => Promise<string>) | undefined;
9
+ now?: number;
10
+ }
11
+ export declare function tip(wanted: string | undefined, options?: TipOptions): Promise<number>;
@@ -0,0 +1,86 @@
1
+ // `nmts tip [percent | off]` — the standing share of every storage payment sent to the developer
2
+ // as a gift (owner 2026-09-06). Read with no argument; set with a percent; `off` is 0.
3
+ //
4
+ // ⛔ IT LIVES IN THE SEALED FILE LIST, like `padding`: the server must not learn it, and it follows
5
+ // the account, so the browser and every machine send the same share. 0 is spelled as absence.
6
+ //
7
+ // ⛔ THE AGREEMENT IS ASKED ONCE, AND ONLY WHEN RAISING FROM 0. Setting any share above 0 needs the
8
+ // `donate` unlock — that unlock's text IS the gift terms (voluntary · nothing in return · not
9
+ // refundable · the published address · visible on the chain) — and the first such setting
10
+ // writes the agreement's instant into the list, which the browser reads as the same agreement.
11
+ // After that, changing the share asks nothing. Above 10 % the run confirms once more, in words,
12
+ // that this share of EVERY payment is meant, permanently: at a terminal, or with `--yes`.
13
+ //
14
+ // ⛔ NOTHING IS SENT HERE. The sending happens after each payment (`standing-tip.ts`), without a
15
+ // question, because this is the person's standing choice.
16
+ import { requireConsent } from "../consent.js";
17
+ import { NmtsError } from "../errors.js";
18
+ import { readFileList } from "../manifest.js";
19
+ import { applyManyToList } from "../manifest-write.js";
20
+ import { BINARY_NAME } from "../product.js";
21
+ import { promptLine, stdinIsATerminal } from "../prompt.js";
22
+ import { openSession } from "../session.js";
23
+ import { TIP_DIAL_MAX_TENTHS, needsExtraConfirm, percentText, tenthsFromPercent } from "../shared/lib/wallet/tip.js";
24
+ export async function tip(wanted, options = {}) {
25
+ const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
26
+ const session = await openSession({ server: options.server, network: options.network });
27
+ const list = await readFileList(session.server, session.apiKey, session.code, session.accountId);
28
+ const current = list.manifest?.settings?.tipTenths ?? 0;
29
+ const consentAt = list.manifest?.settings?.tipConsentAt;
30
+ if (wanted === undefined || wanted === "") {
31
+ if (options.json === true) {
32
+ say(JSON.stringify({ tipPercent: Number(percentText(current)), tipTenths: current, agreedAt: consentAt === undefined ? null : new Date(consentAt).toISOString() }));
33
+ return 0;
34
+ }
35
+ say(current > 0
36
+ ? `Every storage payment sends ${percentText(current)} % of what it paid to the developer, as a gift, in WAL — without asking.`
37
+ : `No standing gift: 0 % of each storage payment goes to the developer.`);
38
+ say(` Set one: \`${BINARY_NAME} tip 2.5\` (in steps of 0.1 %, the dial ends at 10 %). Stop it: \`${BINARY_NAME} tip off\`.`);
39
+ if (consentAt !== undefined)
40
+ say(` The gift terms were agreed to on ${new Date(consentAt).toISOString().slice(0, 10)}.`);
41
+ return 0;
42
+ }
43
+ const tenths = wanted === "off" || wanted === "0" ? 0 : tenthsFromPercent(Number(wanted));
44
+ if (wanted !== "off" && !/^\d+(\.\d+)?$/.test(wanted)) {
45
+ throw new NmtsError(`\`${BINARY_NAME} tip\` takes a percent (2.5) or off.`, { exitCode: 2 });
46
+ }
47
+ if (list.manifest === null) {
48
+ throw new NmtsError(`This account has no file list yet; the setting lives in the list, and there is nothing to write it into.`, {
49
+ exitCode: 4,
50
+ nextStep: `Upload once (\`${BINARY_NAME} put\`) and set it after.`,
51
+ });
52
+ }
53
+ // ⛔ THE AGREEMENT — the `donate` unlock — stands between 0 and anything above it, once per machine.
54
+ if (tenths > 0)
55
+ requireConsent("donate");
56
+ if (needsExtraConfirm(tenths) && options.yes !== true) {
57
+ const ask = options.readLine ?? promptLine;
58
+ if (options.readLine === undefined && !stdinIsATerminal()) {
59
+ throw new NmtsError(`A share above ${percentText(TIP_DIAL_MAX_TENTHS)} % is confirmed by a person.`, {
60
+ exitCode: 5,
61
+ nextStep: `Ask them, then run the same command with --yes.`,
62
+ });
63
+ }
64
+ const answer = (await ask(`Send ${percentText(tenths)} % of EVERY storage payment to the developer, permanently, until you change it? [y/N] `)).trim();
65
+ if (answer !== "y" && answer !== "Y") {
66
+ say(`Nothing changed.`);
67
+ return 1;
68
+ }
69
+ }
70
+ const patch = { tipTenths: tenths };
71
+ if (tenths > 0 && consentAt === undefined)
72
+ patch.tipConsentAt = options.now ?? Date.now();
73
+ const result = await applyManyToList(session, () => [], patch);
74
+ if (options.json === true) {
75
+ say(JSON.stringify({ tipPercent: Number(percentText(tenths)), tipTenths: tenths, changed: result.changed }));
76
+ return 0;
77
+ }
78
+ if (!result.changed)
79
+ say(`Already ${tenths === 0 ? "off" : `${percentText(tenths)} %`}. Nothing changed.`);
80
+ else if (tenths === 0)
81
+ say(`Standing gift set to 0 %: nothing more is sent after a payment.`);
82
+ else
83
+ say(`Standing gift set: every storage payment now sends ${percentText(tenths)} % of what it paid to the developer, in WAL, without asking.`);
84
+ say(` Thank you.`);
85
+ return 0;
86
+ }
@@ -0,0 +1,17 @@
1
+ import type { ManifestEntry } from "../shared/lib/drive/manifest-codec.ts";
2
+ export interface TrashOptions {
3
+ server?: string | undefined;
4
+ network?: string | undefined;
5
+ json?: boolean;
6
+ write?: (line: string) => void;
7
+ }
8
+ export declare function rm(paths: readonly string[], options?: TrashOptions): Promise<number>;
9
+ export declare function restore(paths: readonly string[], options?: TrashOptions): Promise<number>;
10
+ /**
11
+ * Every file at or under one entry.
12
+ *
13
+ * ⚠ Trashed descendants are INCLUDED HERE, and the CALLER filters. Somebody who trashed one file
14
+ * last week and then trashes its folder expects the folder to be gone from the server too — so
15
+ * `rm` takes this set whole. `restore` cannot: see the note at the call site.
16
+ */
17
+ export declare function filesUnder(entries: readonly ManifestEntry[], rootId: string): ManifestEntry[];
@@ -249,7 +249,7 @@ function uniqueById(files) {
249
249
  * last week and then trashes its folder expects the folder to be gone from the server too — so
250
250
  * `rm` takes this set whole. `restore` cannot: see the note at the call site.
251
251
  */
252
- function filesUnder(entries, rootId) {
252
+ export function filesUnder(entries, rootId) {
253
253
  const root = entries.find((e) => e.id === rootId);
254
254
  if (root === undefined)
255
255
  return [];
@@ -0,0 +1,7 @@
1
+ export interface TrialOptions {
2
+ server?: string | undefined;
3
+ network?: string | undefined;
4
+ json?: boolean;
5
+ write?: (line: string) => void;
6
+ }
7
+ export declare function trial(action: string | undefined, options?: TrialOptions): Promise<number>;
@@ -17,13 +17,13 @@
17
17
  // person — which sends an agent to make another key, the one thing that cannot help. So the
18
18
  // standing check is asked about first, and the answer names `nmts verify`.
19
19
  //
20
- // ⛔ AND APPLYING ASKS FOR SOMETHING THIS TOOL CANNOT PRODUCE. `POST /v1/trial/apply` runs a
21
- // fresh browser check of its own on every application it is the one request in this API that
22
- // hands out credits, so the check is made per application rather than once per session. A
23
- // command line has no browser and no token, so on any deployment configured with that check
24
- // the application is refused however good the credentials are. That is reported as what it is,
25
- // with the place a person can apply from, rather than as a credential problem. `nmts verify`
26
- // is a DIFFERENT check and does not stand in for this one.
20
+ // ⛔ AND APPLYING ASKS FOR NO BROWSER TOKEN OF ITS OWN (2026-09-06). `POST
21
+ // /v1/trial/apply` used to run a fresh browser check on every application, which closed the
22
+ // route to this tool completely: a command line has no browser, so the application was refused
23
+ // however good the credentials were. The server now reads the account's four-week check as the
24
+ // human evidence a key carries, so applying works exactly while that check is live the same
25
+ // condition the pre-check above already asks about, and the one `nmts verify` renews. Nothing
26
+ // here produces a token, and nothing here needs to.
27
27
  import { request, ServerError } from "../api.js";
28
28
  import { readCredentialsFile } from "../credentials.js";
29
29
  import { NmtsError } from "../errors.js";
@@ -134,18 +134,16 @@ function explain(error, week) {
134
134
  // screen that is refusing for the same reason.
135
135
  case "TURNSTILE_FAILED":
136
136
  // ⛔ THE ADVICE `api.ts` CARRIES FOR THIS CODE IS THE WRONG ONE HERE, and that is why this
137
- // case exists. It says an API key is what waives the check true for signing in, and
138
- // false for this route, which runs its own check on every application no matter what
139
- // credential arrived. A caller told to go and make a key would make one and be refused
140
- // again.
141
- return new NmtsError("This server asks every application for a browser check, and a command line has none.", {
137
+ // case exists. It says a machine credential is what waives the check; on this route what
138
+ // waives it is the account's four-week check, and a caller sent to make another
139
+ // credential would make one and be refused again.
140
+ return new NmtsError("This server asked this application for a browser check of its own.", {
142
141
  exitCode: 4,
143
- nextStep: `Nothing was taken and this account's place for week ${week.round} is untouched. The ` +
144
- `check is a puzzle solved in a browser, and it is asked for on every application ` +
145
- `rather than once, because this is the one request that hands out credits. Apply on ` +
146
- `the account screen at ` +
147
- `${HOME_URL} instead. \`${BINARY_NAME} verify\` is a different check and does not stand ` +
148
- `in for this one.`,
142
+ nextStep: `Nothing was taken and this account's place for week ${week.round} is untouched. ` +
143
+ `Applying needs the account's four-week check to be live, and \`${BINARY_NAME} verify\` ` +
144
+ `is what renews it: it prints a short code for a person to type at a browser. A server ` +
145
+ `that asks for a check on every application is an older build than this expects — ` +
146
+ `there, a person applies on the account screen at ${HOME_URL}.`,
149
147
  });
150
148
  case "TRIAL_FULL":
151
149
  return new NmtsError("Every place in this week is taken.", {
@@ -0,0 +1,16 @@
1
+ export interface UnlockOptions {
2
+ json?: boolean;
3
+ write?: (line: string) => void;
4
+ /** The clock. Injected so a test asserts a real timestamp rather than tolerating any string. */
5
+ now?: () => Date;
6
+ /** Injected in tests: answers the one question. Its presence also stands in for a terminal. */
7
+ readLine?: ((question: string) => Promise<string>) | undefined;
8
+ /** `unlock wallet` only — see `wallet-grant.ts`. */
9
+ days?: string | undefined;
10
+ until?: string | undefined;
11
+ scope?: string | undefined;
12
+ capWal?: string | undefined;
13
+ capSui?: string | undefined;
14
+ }
15
+ /** `unlock` · `lock` · the list. `action` is already normalised by the caller (`grant` → `unlock`). */
16
+ export declare function unlock(action: string | undefined, target: string | undefined, options?: UnlockOptions): Promise<number>;
@@ -0,0 +1,159 @@
1
+ // `nmts unlock` — what this machine's owner has opened, and the one way to open more.
2
+ //
3
+ // ⛔ IT IS A COMMAND AND NOT A PROMPT. A yes/no question in the middle of another command cannot be
4
+ // answered by anything that is not a terminal, which is most of the places this tool runs: a
5
+ // container, a build step, an agent's subprocess. Making the unlock its own command means the
6
+ // same answer works everywhere, is recorded with a date, and can be looked at afterwards.
7
+ //
8
+ // ⛔ A PERSON UNLOCKS, AT A TERMINAL. Opening a lock refuses when stdin is not a terminal — the way
9
+ // an agent's subprocess usually arrives — and prints what the lock guards before it asks. The one
10
+ // mode that may unlock without a terminal is skip-permissions: the person who turned it on said
11
+ // nothing is to ask them. Locking again is one line from anywhere: the safe direction is never
12
+ // harder than the risky one.
13
+ //
14
+ // `nmts consent` is the older name for the same thing and still works: `grant` is `unlock`, `revoke`
15
+ // is `lock`.
16
+ import { currentMode } from "../autonomy.js";
17
+ import { CONSENTS, CONSENT_KEYS, grant, grantedAt, revoke } from "../consent.js";
18
+ import { NmtsError } from "../errors.js";
19
+ import { BINARY_NAME, SUPPORT_EMAIL, VERSION } from "../product.js";
20
+ import { promptLine, stdinIsATerminal } from "../prompt.js";
21
+ import { coinAmount } from "../wallet.js";
22
+ import { parseWalletGrant, readWalletGrant, walletGrantState, writeWalletGrant } from "../wallet-grant.js";
23
+ function isKey(value) {
24
+ return CONSENT_KEYS.includes(value);
25
+ }
26
+ function keyOrFail(raw) {
27
+ if (raw === undefined || raw === "") {
28
+ throw new NmtsError("Say which one.", { exitCode: 2, nextStep: `One of: ${CONSENT_KEYS.join(" · ")}` });
29
+ }
30
+ if (!isKey(raw)) {
31
+ throw new NmtsError(`There is nothing called "${raw}" to unlock.`, {
32
+ exitCode: 2,
33
+ nextStep: `One of: ${CONSENT_KEYS.join(" · ")}`,
34
+ });
35
+ }
36
+ return raw;
37
+ }
38
+ /** `unlock` · `lock` · the list. `action` is already normalised by the caller (`grant` → `unlock`). */
39
+ export async function unlock(action, target, options = {}) {
40
+ const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
41
+ const now = options.now ?? (() => new Date());
42
+ if (action === undefined || action === "" || action === "list") {
43
+ if (options.json) {
44
+ say(JSON.stringify(CONSENT_KEYS.map((key) => row(key, now()))));
45
+ return 0;
46
+ }
47
+ for (const key of CONSENT_KEYS) {
48
+ if (key === "wallet") {
49
+ for (const line of walletLines(now()))
50
+ say(line);
51
+ continue;
52
+ }
53
+ const at = grantedAt(key);
54
+ say(`${at === null ? " locked " : " unlocked "} ${key}`);
55
+ say(` ${CONSENTS[key].what}`);
56
+ if (at !== null)
57
+ say(` unlocked on this machine ${at}`);
58
+ say(``);
59
+ }
60
+ say(` ${BINARY_NAME} unlock <name> open one, at a terminal, once`);
61
+ say(` ${BINARY_NAME} lock <name> close it again`);
62
+ say(``);
63
+ say(` Unlocking here does not change what the published Terms say. NMTS is not responsible`);
64
+ say(` for what any program on this machine does with this account, an AI agent included.`);
65
+ say(` Something wrong or confusing? ${SUPPORT_EMAIL}`);
66
+ return 0;
67
+ }
68
+ if (action === "unlock") {
69
+ const key = keyOrFail(target);
70
+ if (options.readLine === undefined && !stdinIsATerminal() && currentMode() !== "skip-permissions") {
71
+ throw new NmtsError(`A person unlocks, at a terminal — stdin here is not one.`, {
72
+ exitCode: 5,
73
+ nextStep: `If you are an agent: do not unlock things. Show the person what \`${BINARY_NAME} unlock\` ` +
74
+ `prints for "${key}" and let them decide.`,
75
+ });
76
+ }
77
+ const c = CONSENTS[key];
78
+ // ⚠ A wrong command line is refused BEFORE the question, so nobody answers y to nothing.
79
+ const wallet = key === "wallet" ? parseWalletGrant(options, now(), VERSION) : null;
80
+ say(c.what);
81
+ say(` ${c.risk}`);
82
+ say(` ${c.limit}`);
83
+ if (currentMode() !== "skip-permissions") {
84
+ const ask = options.readLine ?? promptLine;
85
+ const answer = (await ask(`Unlock ${key} on this machine? [y/N] `)).trim();
86
+ if (answer !== "y" && answer !== "Y") {
87
+ say(`Nothing was unlocked.`);
88
+ return 1;
89
+ }
90
+ }
91
+ if (wallet !== null) {
92
+ // ⛔ Not a bare date: scope, expiry and ceilings.
93
+ writeWalletGrant(wallet);
94
+ say(`unlocked: wallet — scope ${wallet.scope}, until ${wallet.expiresAt}`);
95
+ say(` ${ceilingWords(wallet.capWalFrost, wallet.capSuiMist)}`);
96
+ return 0;
97
+ }
98
+ grant(key, VERSION, now());
99
+ say(`unlocked: ${key}`);
100
+ return 0;
101
+ }
102
+ if (action === "lock") {
103
+ const key = keyOrFail(target);
104
+ revoke(key);
105
+ say(`locked: ${key}`);
106
+ return 0;
107
+ }
108
+ throw new NmtsError(`Unknown: ${BINARY_NAME} unlock ${action}`, {
109
+ exitCode: 2,
110
+ nextStep: `Try \`${BINARY_NAME} unlock\`, \`${BINARY_NAME} unlock <name>\`, or \`${BINARY_NAME} lock <name>\`.`,
111
+ });
112
+ }
113
+ function row(key, now) {
114
+ if (key === "wallet") {
115
+ const g = readWalletGrant();
116
+ const state = walletGrantState(g, now);
117
+ return {
118
+ key,
119
+ unlocked: state === "active",
120
+ state,
121
+ unlockedAt: g?.grantedAt ?? null,
122
+ expiresAt: g?.expiresAt ?? null,
123
+ scope: g?.scope ?? null,
124
+ capWalFrost: g?.capWalFrost ?? null,
125
+ capSuiMist: g?.capSuiMist ?? null,
126
+ spentWalFrost: g?.spentWalFrost ?? null,
127
+ spentSuiMist: g?.spentSuiMist ?? null,
128
+ what: CONSENTS[key].what,
129
+ risk: CONSENTS[key].risk,
130
+ };
131
+ }
132
+ return { key, unlocked: grantedAt(key) !== null, unlockedAt: grantedAt(key), what: CONSENTS[key].what, risk: CONSENTS[key].risk };
133
+ }
134
+ /** The wallet row of the list: state, scope, expiry, ceilings and what was signed under it. */
135
+ function walletLines(now) {
136
+ const g = readWalletGrant();
137
+ const state = walletGrantState(g, now);
138
+ const head = state === "active" ? " unlocked " : state === "expired" ? " ran out " : " locked ";
139
+ const out = [`${head} wallet`, ` ${CONSENTS.wallet.what}`];
140
+ if (g !== null) {
141
+ out.push(` scope ${g.scope} · unlocked ${g.grantedAt} · ${state === "expired" ? "ran out" : "until"} ${g.expiresAt}`);
142
+ out.push(` ${ceilingWords(g.capWalFrost, g.capSuiMist)} · signed away so far ${coinAmount(BigInt(g.spentWalFrost))} WAL, ${coinAmount(BigInt(g.spentSuiMist))} SUI in fees`);
143
+ }
144
+ else {
145
+ out.push(` ${BINARY_NAME} unlock wallet --days <1..30> [--scope storage|all] [--cap-wal <coins> --cap-sui <coins>]`);
146
+ }
147
+ out.push(``);
148
+ return out;
149
+ }
150
+ function ceilingWords(capWal, capSui) {
151
+ if (capWal === null && capSui === null)
152
+ return "no ceiling on what this tool may sign away";
153
+ const parts = [];
154
+ if (capWal !== null)
155
+ parts.push(`${coinAmount(BigInt(capWal))} WAL`);
156
+ if (capSui !== null)
157
+ parts.push(`${coinAmount(BigInt(capSui))} SUI`);
158
+ return `ceiling ${parts.join(" and ")}`;
159
+ }
@@ -0,0 +1,42 @@
1
+ import { lookupLatest } from "../update-check.ts";
2
+ export interface UpdateOptions {
3
+ json?: boolean;
4
+ /** Say what it would install, and stop. */
5
+ dryRun?: boolean;
6
+ write?: (line: string) => void;
7
+ /** Injected in tests, so the whole command can run without a host. */
8
+ lookup?: typeof lookupLatest;
9
+ /** Injected in tests. What is running now. */
10
+ running?: string;
11
+ /**
12
+ * The file this module was loaded from — the basis for "was this copy installed".
13
+ *
14
+ * ⚠ Injected rather than read straight from `import.meta` so both answers can be tested on one
15
+ * machine. Nothing on a command line reaches it.
16
+ */
17
+ moduleFile?: string;
18
+ /** Injected in tests. Runs the installer and reports how it went. */
19
+ install?: (command: readonly string[], json: boolean) => InstallOutcome;
20
+ }
21
+ /** What running the installer produced. */
22
+ export interface InstallOutcome {
23
+ code: number;
24
+ /** What it said, when its output was captured rather than passed through. */
25
+ output?: string;
26
+ /** Why it could not be started at all. */
27
+ unstartable?: string;
28
+ }
29
+ /**
30
+ * Was this copy put here by the installer that would replace it?
31
+ *
32
+ * The test is the one thing that is actually true of every such copy and of nothing else: it
33
+ * lives in a directory named for the package, inside a `node_modules`.
34
+ *
35
+ * ⛔ BOTH SEPARATORS, AND THAT IS NOT DEFENSIVENESS. Windows accepts either, and Node hands out
36
+ * either: a path that came through a file URL arrives as `D:/a/…` while `import.meta.filename`
37
+ * gives `D:\a\…`. Splitting on the platform's own separator found nothing in the first shape,
38
+ * so an installed copy on Windows was told it was not installed and `update` refused to run —
39
+ * green on Linux and macOS, red only on the platform this repository tests last.
40
+ */
41
+ export declare function installedAsPackage(moduleFile: string): boolean;
42
+ export declare function update(options?: UpdateOptions): Promise<number>;
@@ -18,7 +18,7 @@
18
18
  // directories in an environment variable. That is the kind of confusion somebody debugs for an
19
19
  // hour, so it is a refusal that says what to run instead.
20
20
  //
21
- // ⛔ IT ASKS THE SOURCE-HOSTING SITE, NOT NMTS. No account code, no API key, no session; the
21
+ // ⛔ IT ASKS THE SOURCE-HOSTING SITE, NOT NMTS. No NMTS key, no API key, no session; the
22
22
  // command works signed out, and it is one of the two places in this tool that talk to a host
23
23
  // other than the NMTS server and the storage network. The other is `nmts recovery`.
24
24
  import { spawnSync } from "node:child_process";
@@ -0,0 +1,8 @@
1
+ export interface UsageOptions {
2
+ server?: string | undefined;
3
+ network?: string | undefined;
4
+ /** Machine-readable output. For an agent this is the shape to parse; the table is for a person. */
5
+ json?: boolean;
6
+ write?: (line: string) => void;
7
+ }
8
+ export declare function usage(options?: UsageOptions): Promise<number>;
@@ -0,0 +1,18 @@
1
+ export interface VerifyOptions {
2
+ server?: string | undefined;
3
+ json?: boolean;
4
+ /** Ask whether the check is live, print the answer, and mint nothing. */
5
+ status?: boolean;
6
+ write?: (line: string) => void;
7
+ /**
8
+ * The wait between asks. Injected by tests so they do not spend the real interval.
9
+ *
10
+ * ⚠ It resolves rather than rejects when the wait is cut short. What cancelling MEANS is decided
11
+ * in one place below, after the wait, so that an abort during a request and an abort during a
12
+ * wait end the same way.
13
+ */
14
+ sleep?: (ms: number, signal: AbortSignal) => Promise<void>;
15
+ /** A caller's own reason to stop waiting. Joined with the interrupt key. */
16
+ signal?: AbortSignal | undefined;
17
+ }
18
+ export declare function verify(options?: VerifyOptions): Promise<number>;
@@ -9,10 +9,10 @@
9
9
  // the doing is theirs, the waiting is ours, and saying it any other way would be a lie about
10
10
  // what a program can do.
11
11
  //
12
- // ⛔ THE CODE IS PRINTED ON PURPOSE, AND IT IS NOT THE ACCOUNT CODE. Everything else in this tool
12
+ // ⛔ THE CODE IS PRINTED ON PURPOSE, AND IT IS NOT THE NMTS KEY. Everything else in this tool
13
13
  // refuses to put a credential on the screen. This one is minted to be read out: it is single
14
14
  // use, it stops working within minutes, the server keeps only a hash of it, and by itself it
15
- // opens nothing — a person still has to pass the check on the page. The account code is a
15
+ // opens nothing — a person still has to pass the check on the page. The NMTS key is a
16
16
  // different thing entirely and still never appears here, which the text says out loud so that
17
17
  // nobody reads "type this code" and reaches for the wrong one.
18
18
  //
@@ -23,8 +23,11 @@
23
23
  // two answers to one question start. The honest thing is the absolute moment, and then whoever
24
24
  // is reading decides.
25
25
  //
26
- // ⚠ IT NEEDS THE API KEY AND NOT THE ACCOUNT CODE. Nothing here opens a file, so demanding the
27
- // code would refuse a run over a credential the command never uses.
26
+ // ⚠ IT NEEDS THE API KEY AND NOT THE NMTS KEY. Nothing here opens a file, so demanding the
27
+ // code would refuse a run over a credential the command never uses. The PAGE, since 2026-09-05,
28
+ // does want the account's holder — signed in there, or typing the NMTS key there — because
29
+ // a check anybody could pass for anybody was a check that could be bought; that is said to the
30
+ // person in the printed text, and it changes nothing about what this command holds.
28
31
  import { request } from "../api.js";
29
32
  import { readCredentialsFile } from "../credentials.js";
30
33
  import { NmtsError } from "../errors.js";
@@ -92,8 +95,9 @@ export async function verify(options = {}) {
92
95
  human(` Ask the person to open ${minted.verifyUrl}`);
93
96
  human(` and to type this code ${minted.code}`);
94
97
  human(``);
95
- human(`This is not the account code. It works once, and it stops working at`);
96
- human(`${minted.expiresAt.iso} (${inWords(minted.expiresAt.ms - Date.now())}).`);
98
+ human(`Only this account's holder can confirm: signed in to it in that browser, or`);
99
+ human(`typing its NMTS key there. The code above is not the NMTS key. It works`);
100
+ human(`once, and it stops working at ${minted.expiresAt.iso} (${inWords(minted.expiresAt.ms - Date.now())}).`);
97
101
  human(``);
98
102
  human(`Waiting here until it is used. Ctrl-C stops the waiting, not the code.`);
99
103
  const wait = options.sleep ?? waitFor;
@@ -0,0 +1,26 @@
1
+ import { type Network } from "../network.ts";
2
+ import { type ActivityContext, type RpcTransaction } from "../shared/lib/wallet/activity.ts";
3
+ /** How many to ask for in each direction, and how many to print after the merge. */
4
+ export declare const FETCH_PER_DIRECTION = 25;
5
+ export declare const SHOW = 20;
6
+ /** The two lists the chain answers with. */
7
+ export interface ActivityFetch {
8
+ sent: readonly RpcTransaction[];
9
+ received: readonly RpcTransaction[];
10
+ }
11
+ export interface WalletActivityOptions {
12
+ server?: string | undefined;
13
+ network?: string | undefined;
14
+ json?: boolean;
15
+ write?: (line: string) => void;
16
+ /**
17
+ * Where the transactions come from.
18
+ *
19
+ * ⚠ A SEAM, NOT AN OPTION: no flag reaches it. A test that talked to a live chain could not run
20
+ * offline and could never be asked to fail on purpose.
21
+ */
22
+ queryChain?: (network: Network, address: string) => Promise<ActivityFetch>;
23
+ }
24
+ /** What the judgement compares against on this network. Donation and pool addresses: unknown here. */
25
+ export declare function activityContext(network: Network, address: string): ActivityContext;
26
+ export declare function walletActivity(options?: WalletActivityOptions): Promise<number>;
@@ -0,0 +1,117 @@
1
+ // `nmts wallet activity` — the recent transactions of the wallet this NMTS key derives.
2
+ //
3
+ // ⛔ IT READS. The chain is asked twice (sent, received — the RPC filter has no OR), the rows are
4
+ // named by the SAME judgement the browser uses (`shared/lib/wallet/activity.ts`, copied
5
+ // byte-for-byte), and nothing here signs or spends.
6
+ //
7
+ // ⛔ A NAME IS PUT ONLY WHERE A CONSTANT PROVES IT. What this tool cannot prove it prints as
8
+ // "other" — with the time, the balance changes and the chain link still there. Two things the
9
+ // browser knows and this tool does not: the developer's donation address and the free-trial
10
+ // pool's, which the server keeps to itself. So here a gift shows as a plain send, and a fee the
11
+ // pool paid shows as paid by "another address". Both are said below the list, once.
12
+ //
13
+ // ⛔ AN UNANSWERED CHAIN IS NOT AN EMPTY LIST. A read that fails exits non-zero and says so; the
14
+ // empty list is printed only when the chain answered and had nothing.
15
+ import { MAINNET_WALRUS_PACKAGE_CONFIG, TESTNET_WALRUS_PACKAGE_CONFIG } from "@mysten/walrus";
16
+ import { requireAccountCode } from "../code-access.js";
17
+ import { readCredentialsFile } from "../credentials.js";
18
+ import { NmtsError } from "../errors.js";
19
+ import { resolveNetwork } from "../network.js";
20
+ import { BINARY_NAME } from "../product.js";
21
+ import { resolveServer } from "../server.js";
22
+ import { mergeActivity, toActivityRow, } from "../shared/lib/wallet/activity.js";
23
+ import { BLUEFIN_PACKAGE_IDS, DEEPBOOK_PACKAGE_IDS } from "../shared/lib/wallet/venue-ids.js";
24
+ import { coinAmount, walCoinType, walletAddress } from "../wallet.js";
25
+ /** How many to ask for in each direction, and how many to print after the merge. */
26
+ export const FETCH_PER_DIRECTION = 25;
27
+ export const SHOW = 20;
28
+ /** What the judgement compares against on this network. Donation and pool addresses: unknown here. */
29
+ export function activityContext(network, address) {
30
+ const walrus = network === "mainnet" ? MAINNET_WALRUS_PACKAGE_CONFIG : TESTNET_WALRUS_PACKAGE_CONFIG;
31
+ return {
32
+ address,
33
+ donationAddresses: [],
34
+ poolAddress: "",
35
+ walCoinType: walCoinType(network),
36
+ walrusSystemObjectId: walrus.systemObjectId,
37
+ deepbookPackageId: DEEPBOOK_PACKAGE_IDS[network],
38
+ bluefinPackageId: BLUEFIN_PACKAGE_IDS[network],
39
+ exchangeObjectId: network === "testnet" ? (TESTNET_WALRUS_PACKAGE_CONFIG.exchangeIds[0] ?? null) : null,
40
+ network,
41
+ };
42
+ }
43
+ export async function walletActivity(options = {}) {
44
+ const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
45
+ const resolved = await requireAccountCode();
46
+ const address = await walletAddress(resolved.code);
47
+ const stored = resolved.source === "file" || resolved.source === "file-locked" ? readCredentialsFile() : null;
48
+ const server = resolveServer(options.server ?? stored?.server);
49
+ const network = resolveNetwork(server, options.network ?? stored?.network);
50
+ const query = options.queryChain ?? (async (net, addr) => (await import("../wallet-activity-chain.js")).queryActivity(net, addr));
51
+ let fetched;
52
+ try {
53
+ fetched = await query(network, address);
54
+ }
55
+ catch (error) {
56
+ throw new NmtsError("The wallet's transactions could not be read from the chain.", {
57
+ exitCode: 1,
58
+ nextStep: `Nothing is known about this wallet's activity from here — that is not the same as there ` +
59
+ `being none. \`${BINARY_NAME} env\` says which network was asked. ` +
60
+ `Cause: ${error instanceof Error ? error.message : String(error)}`,
61
+ });
62
+ }
63
+ const ctx = activityContext(network, address);
64
+ const rows = mergeActivity([fetched.sent.map((tx) => toActivityRow(tx, ctx)), fetched.received.map((tx) => toActivityRow(tx, ctx))], SHOW);
65
+ if (options.json) {
66
+ say(JSON.stringify({ address, network, shown: rows.length, rows: rows.map(asJson) }));
67
+ return 0;
68
+ }
69
+ say(`Address ${address}`);
70
+ say(`Network ${network}`);
71
+ say(``);
72
+ if (rows.length === 0) {
73
+ say(` The chain answered and lists no transaction for this wallet.`);
74
+ }
75
+ else {
76
+ for (const row of rows)
77
+ say(` ${inWords(row)}`);
78
+ }
79
+ say(``);
80
+ say(` The newest ${SHOW} at most; the chain link on each line shows the rest. A name is put only`);
81
+ say(` where the transaction proves it — the storage network's own calls, the two exchanges, a`);
82
+ say(` plain transfer. Anything else is "other". Gifts to the developer show here as sends, and a`);
83
+ say(` fee the free-trial pool paid shows as paid by another address: this tool does not know`);
84
+ say(` those two addresses.`);
85
+ return 0;
86
+ }
87
+ /** An amount with its sign — `coinAmount` formats magnitudes, and a balance change has a direction. */
88
+ function signed(amount) {
89
+ return amount < 0n ? `-${coinAmount(-amount)}` : `+${coinAmount(amount)}`;
90
+ }
91
+ /** One row, for a person: when · what · how much of which coin · who paid the fee · the link. */
92
+ function inWords(row) {
93
+ const when = row.atMs === null ? "time unknown " : new Date(row.atMs).toISOString().replace(/\.\d{3}Z$/, "Z");
94
+ const changes = row.changes.length === 0
95
+ ? "no balance change"
96
+ : row.changes.map((c) => `${signed(c.amount)} ${c.coin ?? c.coinType}`).join(", ");
97
+ const fee = row.gasPayer === "self" ? "" : " fee paid by another address";
98
+ const failed = row.failed ? " ⛔ FAILED on chain" : "";
99
+ return `${when} ${row.kind.padEnd(8)} ${changes}${fee}${failed}\n ${row.explorerUrl}`;
100
+ }
101
+ /** One row, for a program. ⚠ Amounts are strings: base units run past what a JSON number keeps. */
102
+ function asJson(row) {
103
+ return {
104
+ digest: row.digest,
105
+ at: row.atMs === null ? null : new Date(row.atMs).toISOString(),
106
+ kind: row.kind,
107
+ failed: row.failed,
108
+ gasPayer: row.gasPayer,
109
+ changes: row.changes.map((c) => ({
110
+ coin: c.coin,
111
+ coinType: c.coinType,
112
+ baseUnits: c.amount.toString(),
113
+ amount: signed(c.amount),
114
+ })),
115
+ explorerUrl: row.explorerUrl,
116
+ };
117
+ }