@needmoretruth/nmts-cli 0.17.2 → 0.34.1
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.
- package/AGENTS.md +124 -516
- package/CHANGELOG.md +98 -0
- package/README.ko.md +374 -467
- package/README.md +384 -465
- package/dist/account-proof.d.ts +29 -0
- package/dist/account-proof.js +6 -6
- package/dist/account.d.ts +18 -0
- package/dist/account.js +5 -5
- package/dist/agent-host.d.ts +71 -0
- package/dist/agent-host.js +169 -0
- package/dist/api-advice.d.ts +2 -0
- package/dist/api-advice.js +210 -0
- package/dist/api-key.d.ts +79 -0
- package/dist/api-key.js +7 -7
- package/dist/api-refusal.d.ts +14 -0
- package/dist/api-refusal.js +8 -0
- package/dist/api.d.ts +114 -0
- package/dist/api.js +59 -162
- package/dist/args.d.ts +160 -0
- package/dist/args.js +118 -30
- package/dist/artifact-about.d.ts +49 -0
- package/dist/autonomy.d.ts +39 -0
- package/dist/autonomy.js +110 -32
- package/dist/code-access.d.ts +29 -0
- package/dist/code-access.js +3 -3
- package/dist/code-vault.d.ts +38 -0
- package/dist/code-vault.js +8 -8
- package/dist/collision.d.ts +67 -0
- package/dist/collision.js +1 -1
- package/dist/commands/accept-terms.d.ts +11 -0
- package/dist/commands/accept-terms.js +106 -0
- package/dist/commands/balance.d.ts +7 -0
- package/dist/commands/balance.js +54 -1
- package/dist/commands/create-code-file.d.ts +24 -0
- package/dist/commands/create-code-file.js +93 -0
- package/dist/commands/create-link.d.ts +10 -0
- package/dist/commands/create-link.js +232 -0
- package/dist/commands/create.d.ts +20 -0
- package/dist/commands/create.js +43 -102
- package/dist/commands/credits.d.ts +9 -0
- package/dist/commands/credits.js +110 -0
- package/dist/commands/delete-account.d.ts +11 -0
- package/dist/commands/delete-account.js +63 -0
- package/dist/commands/deposit.d.ts +7 -0
- package/dist/commands/deposit.js +85 -0
- package/dist/commands/devices.d.ts +12 -0
- package/dist/commands/devices.js +144 -0
- package/dist/commands/documents.d.ts +35 -0
- package/dist/commands/documents.js +212 -0
- package/dist/commands/env.d.ts +5 -0
- package/dist/commands/env.js +10 -2
- package/dist/commands/erase.d.ts +13 -0
- package/dist/commands/erase.js +193 -0
- package/dist/commands/expiring.d.ts +19 -0
- package/dist/commands/extend.d.ts +33 -0
- package/dist/commands/extend.js +54 -15
- package/dist/commands/get.d.ts +18 -0
- package/dist/commands/key-manage.d.ts +11 -0
- package/dist/commands/key-manage.js +162 -0
- package/dist/commands/key.d.ts +28 -0
- package/dist/commands/key.js +249 -0
- package/dist/commands/kit.d.ts +11 -0
- package/dist/commands/kit.js +7 -7
- package/dist/commands/listfile.d.ts +13 -0
- package/dist/commands/listfile.js +12 -5
- package/dist/commands/login.d.ts +18 -0
- package/dist/commands/login.js +19 -19
- package/dist/commands/logout.d.ts +1 -0
- package/dist/commands/logout.js +1 -1
- package/dist/commands/losses.d.ts +12 -0
- package/dist/commands/losses.js +180 -0
- package/dist/commands/ls.d.ts +23 -0
- package/dist/commands/marks-dispatch.d.ts +2 -0
- package/dist/commands/marks-dispatch.js +51 -0
- package/dist/commands/marks.d.ts +46 -0
- package/dist/commands/marks.js +80 -0
- package/dist/commands/mcp.d.ts +24 -0
- package/dist/commands/mcp.js +70 -5
- package/dist/commands/mode.d.ts +8 -0
- package/dist/commands/mode.js +60 -24
- package/dist/commands/on-collision.d.ts +6 -0
- package/dist/commands/organise.d.ts +46 -0
- package/dist/commands/padding.d.ts +7 -0
- package/dist/commands/padding.js +114 -0
- package/dist/commands/public-code.d.ts +9 -0
- package/dist/commands/public-code.js +8 -8
- package/dist/commands/pull.d.ts +27 -0
- package/dist/commands/push-wallet.d.ts +19 -0
- package/dist/commands/push-wallet.js +69 -0
- package/dist/commands/push.d.ts +47 -0
- package/dist/commands/push.js +37 -7
- package/dist/commands/put-wallet.d.ts +77 -0
- package/dist/commands/put-wallet.js +316 -0
- package/dist/commands/put.d.ts +56 -0
- package/dist/commands/put.js +53 -6
- package/dist/commands/rebuild.d.ts +18 -0
- package/dist/commands/rebuild.js +108 -10
- package/dist/commands/receive.d.ts +24 -0
- package/dist/commands/recovery-dispatch.d.ts +2 -0
- package/dist/commands/recovery-dispatch.js +34 -0
- package/dist/commands/recovery-list.d.ts +11 -0
- package/dist/commands/recovery-list.js +6 -6
- package/dist/commands/recovery.d.ts +25 -0
- package/dist/commands/recovery.js +2 -2
- package/dist/commands/rollback.d.ts +9 -0
- package/dist/commands/rollback.js +118 -0
- package/dist/commands/s3.d.ts +23 -0
- package/dist/commands/s3.js +6 -6
- package/dist/commands/settings.d.ts +5 -0
- package/dist/commands/settings.js +21 -6
- package/dist/commands/share-dispatch.d.ts +2 -0
- package/dist/commands/share-dispatch.js +46 -0
- package/dist/commands/share.d.ts +14 -0
- package/dist/commands/share.js +13 -3
- package/dist/commands/shares-sent.d.ts +18 -0
- package/dist/commands/shares-sent.js +95 -0
- package/dist/commands/support.d.ts +24 -0
- package/dist/commands/support.js +321 -0
- package/dist/commands/sweep.d.ts +11 -0
- package/dist/commands/tip.d.ts +11 -0
- package/dist/commands/tip.js +86 -0
- package/dist/commands/trash.d.ts +17 -0
- package/dist/commands/trash.js +1 -1
- package/dist/commands/trial.d.ts +7 -0
- package/dist/commands/trial.js +16 -18
- package/dist/commands/unlock.d.ts +16 -0
- package/dist/commands/unlock.js +159 -0
- package/dist/commands/update.d.ts +42 -0
- package/dist/commands/update.js +1 -1
- package/dist/commands/usage.d.ts +8 -0
- package/dist/commands/verify.d.ts +18 -0
- package/dist/commands/verify.js +10 -6
- package/dist/commands/wallet-activity.d.ts +26 -0
- package/dist/commands/wallet-activity.js +117 -0
- package/dist/commands/wallet-donate.d.ts +26 -0
- package/dist/commands/wallet-donate.js +163 -0
- package/dist/commands/wallet-hall.d.ts +35 -0
- package/dist/commands/wallet-hall.js +214 -0
- package/dist/commands/wallet-send.d.ts +22 -0
- package/dist/commands/wallet-send.js +153 -0
- package/dist/commands/wallet-storage-ops.d.ts +24 -0
- package/dist/commands/wallet-storage-ops.js +215 -0
- package/dist/commands/wallet-storage.d.ts +18 -0
- package/dist/commands/wallet-storage.js +95 -0
- package/dist/commands/wallet-swap.d.ts +32 -0
- package/dist/commands/wallet-swap.js +287 -0
- package/dist/commands/wallet.d.ts +36 -0
- package/dist/commands/wallet.js +57 -15
- package/dist/commands/whoami.d.ts +10 -0
- package/dist/commands/whoami.js +24 -6
- package/dist/consent.d.ts +140 -0
- package/dist/consent.js +89 -30
- package/dist/credentials.d.ts +146 -0
- package/dist/credentials.js +10 -10
- package/dist/crypto-surface.d.ts +197 -0
- package/dist/crypto.d.ts +81 -0
- package/dist/crypto.js +13 -0
- package/dist/deposit.d.ts +25 -0
- package/dist/deposit.js +78 -0
- package/dist/download-part.d.ts +40 -0
- package/dist/download-sink.d.ts +76 -0
- package/dist/download.d.ts +79 -0
- package/dist/download.js +3 -3
- package/dist/drive-paths.d.ts +73 -0
- package/dist/environment.d.ts +62 -0
- package/dist/environment.js +29 -9
- package/dist/errors.d.ts +22 -0
- package/dist/errors.js +3 -3
- package/dist/exit.d.ts +44 -0
- package/dist/expiry.d.ts +58 -0
- package/dist/extend-budget.d.ts +35 -0
- package/dist/extend-budget.js +81 -0
- package/dist/extend-chain.d.ts +43 -0
- package/dist/extend-chain.js +40 -3
- package/dist/extend-plan.d.ts +148 -0
- package/dist/extend-plan.js +1 -1
- package/dist/gate.d.ts +18 -0
- package/dist/gate.js +100 -0
- package/dist/guards.d.ts +2 -0
- package/dist/help.d.ts +20 -0
- package/dist/help.js +199 -33
- package/dist/human-check.d.ts +23 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +49 -0
- package/dist/item-trash.d.ts +1 -0
- package/dist/kit-file.d.ts +56 -0
- package/dist/kit-file.js +10 -10
- package/dist/list-file.d.ts +88 -0
- package/dist/list-file.js +90 -7
- package/dist/list-view-find.d.ts +15 -0
- package/dist/list-view-order.d.ts +32 -0
- package/dist/main.d.ts +12 -0
- package/dist/main.js +112 -113
- package/dist/manifest-chunk-cache.d.ts +14 -0
- package/dist/manifest-chunk-cache.js +103 -0
- package/dist/manifest-chunk-flow.d.ts +81 -0
- package/dist/manifest-chunk-flow.js +307 -0
- package/dist/manifest-create.d.ts +23 -0
- package/dist/manifest-create.js +26 -30
- package/dist/manifest-write.d.ts +161 -0
- package/dist/manifest-write.js +42 -33
- package/dist/manifest.d.ts +82 -0
- package/dist/manifest.js +69 -21
- package/dist/mark-render.d.ts +26 -0
- package/dist/mcp-args.d.ts +17 -0
- package/dist/mcp-ask.d.ts +43 -0
- package/dist/mcp-ask.js +100 -0
- package/dist/mcp-tools/context.d.ts +46 -0
- package/dist/mcp-tools/credits.d.ts +3 -0
- package/dist/mcp-tools/credits.js +61 -0
- package/dist/mcp-tools/files.d.ts +3 -0
- package/dist/mcp-tools/files.js +34 -0
- package/dist/mcp-tools/organise.d.ts +3 -0
- package/dist/mcp-tools/organise.js +82 -2
- package/dist/mcp-tools/reads.d.ts +3 -0
- package/dist/mcp-tools/reads.js +132 -4
- package/dist/mcp-tools/share.d.ts +3 -0
- package/dist/mcp-tools/share.js +26 -7
- package/dist/mcp-tools/support.d.ts +3 -0
- package/dist/mcp-tools/support.js +140 -0
- package/dist/mcp-tools/tiers.d.ts +31 -0
- package/dist/mcp-tools/tiers.js +147 -0
- package/dist/mcp.d.ts +80 -0
- package/dist/mcp.js +110 -9
- package/dist/net-retry.d.ts +38 -0
- package/dist/network.d.ts +10 -0
- package/dist/notice.d.ts +7 -0
- package/dist/notice.js +7 -7
- package/dist/product.d.ts +29 -0
- package/dist/product.js +1 -1
- package/dist/progress.d.ts +37 -0
- package/dist/prompt.d.ts +31 -0
- package/dist/prompt.js +1 -1
- package/dist/rebuild-key-check.d.ts +26 -0
- package/dist/rebuild-key-check.js +90 -0
- package/dist/rebuild.d.ts +87 -0
- package/dist/rebuild.js +26 -4
- package/dist/recovery-assemble.d.ts +40 -0
- package/dist/recovery-assemble.js +1 -1
- package/dist/recovery-build.d.ts +40 -0
- package/dist/recovery-map-file.d.ts +53 -0
- package/dist/recovery-map-file.js +4 -4
- package/dist/recovery-map.d.ts +197 -0
- package/dist/recovery-release.d.ts +104 -0
- package/dist/recovery-seq.d.ts +10 -0
- package/dist/recovery-source.d.ts +50 -0
- package/dist/redact.d.ts +70 -0
- package/dist/redact.js +212 -0
- package/dist/registration.d.ts +30 -0
- package/dist/registration.js +5 -5
- package/dist/risk.d.ts +380 -0
- package/dist/risk.js +206 -0
- package/dist/run-log.d.ts +78 -0
- package/dist/run-log.js +301 -0
- package/dist/s3/listing.d.ts +47 -0
- package/dist/s3/multipart.d.ts +21 -0
- package/dist/s3/response-sink.d.ts +8 -0
- package/dist/s3/same-file.d.ts +54 -0
- package/dist/s3/server.d.ts +58 -0
- package/dist/s3/server.js +2 -2
- package/dist/s3/sigv4.d.ts +46 -0
- package/dist/s3/sigv4.js +1 -1
- package/dist/s3/staging.d.ts +10 -0
- package/dist/s3/xml.d.ts +28 -0
- package/dist/safe-path.d.ts +41 -0
- package/dist/seal.d.ts +120 -0
- package/dist/secret-reader.d.ts +28 -0
- package/dist/server.d.ts +9 -0
- package/dist/session.d.ts +32 -0
- package/dist/session.js +1 -1
- package/dist/setup-questions.d.ts +7 -0
- package/dist/share.d.ts +108 -0
- package/dist/share.js +1 -1
- package/dist/shared/lib/crypto/size-padding.d.ts +55 -0
- package/dist/shared/lib/crypto/size-padding.js +5 -0
- package/dist/shared/lib/drive/manifest-chunks.d.ts +95 -0
- package/dist/shared/lib/drive/manifest-chunks.js +252 -0
- package/dist/shared/lib/drive/manifest-codec.d.ts +214 -0
- package/dist/shared/lib/drive/manifest-codec.js +7 -7
- package/dist/shared/lib/drive/manifest-index.d.ts +98 -0
- package/dist/shared/lib/drive/manifest-ops.d.ts +167 -0
- package/dist/shared/lib/drive/manifest-ops.js +9 -4
- package/dist/shared/lib/drive/manifest-pack.d.ts +65 -0
- package/dist/shared/lib/drive/manifest-pack.js +287 -0
- package/dist/shared/lib/drive/manifest-settings.d.ts +113 -0
- package/dist/shared/lib/drive/manifest-settings.js +87 -6
- package/dist/shared/lib/drive/name-conflict.d.ts +76 -0
- package/dist/shared/lib/drive/rebuild-verify.d.ts +73 -0
- package/dist/shared/lib/drive/rebuild-verify.js +112 -0
- package/dist/shared/lib/drive/unique-name.d.ts +9 -0
- package/dist/shared/lib/drive/zstd.d.ts +27 -0
- package/dist/shared/lib/drive/zstd.js +74 -0
- package/dist/shared/lib/extend/epochs.d.ts +205 -0
- package/dist/shared/lib/net/retry-budget.d.ts +79 -0
- package/dist/shared/lib/share/shared-file-info.d.ts +21 -0
- package/dist/shared/lib/storage-control/chain.d.ts +57 -0
- package/dist/shared/lib/storage-control/chain.js +82 -0
- package/dist/shared/lib/storage-control/plan.d.ts +40 -0
- package/dist/shared/lib/storage-control/plan.js +72 -0
- package/dist/shared/lib/storage-control/reuse.d.ts +72 -0
- package/dist/shared/lib/storage-control/reuse.js +95 -0
- package/dist/shared/lib/storage-network.d.ts +25 -0
- package/dist/shared/lib/upload/part-plan.d.ts +24 -0
- package/dist/shared/lib/wallet/activity.d.ts +138 -0
- package/dist/shared/lib/wallet/activity.js +208 -0
- package/dist/shared/lib/wallet/send-rules.d.ts +68 -0
- package/dist/shared/lib/wallet/send-rules.js +116 -0
- package/dist/shared/lib/wallet/swap-rules.d.ts +115 -0
- package/dist/shared/lib/wallet/swap-rules.js +199 -0
- package/dist/shared/lib/wallet/tip.d.ts +14 -0
- package/dist/shared/lib/wallet/tip.js +34 -0
- package/dist/shared/lib/wallet/venue-ids.d.ts +23 -0
- package/dist/shared/lib/wallet/venue-ids.js +53 -0
- package/dist/standing-tip.d.ts +24 -0
- package/dist/standing-tip.js +52 -0
- package/dist/stdout.d.ts +38 -0
- package/dist/storage-control-chain.d.ts +38 -0
- package/dist/storage-control-chain.js +78 -0
- package/dist/sui-rpc.d.ts +15 -0
- package/dist/sui-rpc.js +59 -0
- package/dist/support-attach.d.ts +24 -0
- package/dist/support-attach.js +72 -0
- package/dist/support-copy.d.ts +42 -0
- package/dist/support-copy.js +109 -0
- package/dist/support-wire.d.ts +49 -0
- package/dist/support-wire.js +194 -0
- package/dist/trash-sweep.d.ts +55 -0
- package/dist/units.d.ts +2 -0
- package/dist/update-check.d.ts +50 -0
- package/dist/update-source.d.ts +63 -0
- package/dist/upload-api.d.ts +3 -0
- package/dist/upload-file.d.ts +97 -0
- package/dist/upload-file.js +3 -2
- package/dist/upload-price.d.ts +50 -0
- package/dist/upload-steps.d.ts +26 -0
- package/dist/upload-steps.js +29 -9
- package/dist/upload-store.d.ts +182 -0
- package/dist/upload-wallet-chain.d.ts +54 -0
- package/dist/upload-wallet-chain.js +203 -0
- package/dist/upload-wallet-plan.d.ts +128 -0
- package/dist/upload-wallet-plan.js +184 -0
- package/dist/upload-wallet.d.ts +24 -0
- package/dist/upload-wallet.js +208 -0
- package/dist/upload-wire.d.ts +244 -0
- package/dist/upload.d.ts +18 -0
- package/dist/upload.js +10 -0
- package/dist/usage-report.d.ts +35 -0
- package/dist/wallet-activity-chain.d.ts +5 -0
- package/dist/wallet-activity-chain.js +31 -0
- package/dist/wallet-chain.d.ts +19 -0
- package/dist/wallet-chain.js +2 -2
- package/dist/wallet-grant.d.ts +50 -0
- package/dist/wallet-grant.js +218 -0
- package/dist/wallet-send-chain.d.ts +24 -0
- package/dist/wallet-send-chain.js +49 -0
- package/dist/wallet-sign.d.ts +133 -0
- package/dist/wallet-sign.js +317 -0
- package/dist/wallet-storage-chain.d.ts +3 -0
- package/dist/wallet-storage-chain.js +20 -0
- package/dist/wallet-swap-chain.d.ts +52 -0
- package/dist/wallet-swap-chain.js +186 -0
- package/dist/wallet-swap-quote.d.ts +22 -0
- package/dist/wallet-swap-quote.js +126 -0
- package/dist/wallet.d.ts +135 -0
- package/dist/wallet.js +5 -5
- package/dist/walrus-write.d.ts +56 -0
- package/dist/walrus-write.js +5 -4
- package/dist/walrus.d.ts +86 -0
- package/dist/walrus.js +48 -10
- package/dist/zstd-node.d.ts +11 -0
- package/dist/zstd-node.js +71 -0
- package/docs/commands/accept-terms.md +15 -0
- package/docs/commands/create.md +17 -0
- package/docs/commands/credits.md +34 -0
- package/docs/commands/delete-account.md +14 -0
- package/docs/commands/deposit.md +27 -0
- package/docs/commands/devices.md +9 -0
- package/docs/commands/documents.md +10 -0
- package/docs/commands/env.md +21 -0
- package/docs/commands/extend.md +27 -0
- package/docs/commands/folders.md +10 -0
- package/docs/commands/get.md +14 -0
- package/docs/commands/key.md +14 -0
- package/docs/commands/login.md +23 -0
- package/docs/commands/logout.md +11 -0
- package/docs/commands/losses.md +13 -0
- package/docs/commands/ls.md +16 -0
- package/docs/commands/marks.md +9 -0
- package/docs/commands/mcp.md +33 -0
- package/docs/commands/mode.md +29 -0
- package/docs/commands/on-collision.md +13 -0
- package/docs/commands/padding.md +13 -0
- package/docs/commands/public-code.md +9 -0
- package/docs/commands/pull.md +9 -0
- package/docs/commands/push.md +12 -0
- package/docs/commands/put.md +36 -0
- package/docs/commands/rebuild.md +13 -0
- package/docs/commands/recovery.md +18 -0
- package/docs/commands/s3.md +17 -0
- package/docs/commands/share.md +15 -0
- package/docs/commands/support.md +16 -0
- package/docs/commands/tip.md +21 -0
- package/docs/commands/trash.md +25 -0
- package/docs/commands/trial.md +12 -0
- package/docs/commands/unlock.md +25 -0
- package/docs/commands/update.md +14 -0
- package/docs/commands/usage.md +14 -0
- package/docs/commands/verify.md +18 -0
- package/docs/commands/wallet.md +67 -0
- package/docs/commands/whoami.md +12 -0
- package/package.json +67 -8
- package/server.json +28 -0
- package/vendor/nmts-crypto/nmts_crypto_wasm.d.ts +23 -2
- package/vendor/nmts-crypto/nmts_crypto_wasm.js +44 -2
- package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm +0 -0
- package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm.d.ts +1 -0
- package/vendor/nmts-crypto/package.json +1 -1
- package/dist/commands/consent.js +0 -77
- package/dist/extend-sign.js +0 -130
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// What the wallet holds against what this extension costs — worked out BEFORE the agreement is
|
|
2
|
+
// asked for and before anything is signed.
|
|
3
|
+
//
|
|
4
|
+
// ⛔ WHY IT IS BEFORE THE AGREEMENT. The agreement ladder exists so that a program cannot sign
|
|
5
|
+
// with somebody's wallet until a person has said so on this machine. Learning that the wallet
|
|
6
|
+
// is short is a read, and a person should not have to grant the one key that matters in order
|
|
7
|
+
// to be told there is nothing to spend. So a shortfall is refused first, with the two numbers,
|
|
8
|
+
// and the agreement is asked for only when the purchase can go through.
|
|
9
|
+
//
|
|
10
|
+
// ⛔ AN UNREAD BALANCE IS NOT A SHORTFALL. `wallet.ts` prints an unreadable balance as that and
|
|
11
|
+
// never as zero, and this file keeps the rule where it costs the most: a zero here would refuse
|
|
12
|
+
// a purchase the wallet can afford. An unread balance is SAID, and the run goes on — the chain
|
|
13
|
+
// refuses the signature itself if the money is not there, exactly as it did before this file.
|
|
14
|
+
//
|
|
15
|
+
// ⛔ THE FEE IS MEASURED, NOT ASSUMED. It is a dry run of the exact transaction that would be
|
|
16
|
+
// signed (`extend-chain.ts`), and when the chain cannot measure it the answer is `null` and the
|
|
17
|
+
// words say so. A plausible number in its place would be indistinguishable from a measured one.
|
|
18
|
+
import { BINARY_NAME } from "./product.js";
|
|
19
|
+
import { coinAmount } from "./wallet.js";
|
|
20
|
+
function held(coin) {
|
|
21
|
+
return coin.read ? coin.baseUnits : null;
|
|
22
|
+
}
|
|
23
|
+
/** Read the wallet and measure the fee, then say whether the known numbers cover the purchase. */
|
|
24
|
+
export async function readBudget(reads, input) {
|
|
25
|
+
const { address, objectIds, epochs, priceFrost } = input;
|
|
26
|
+
const [purse, feeMist] = await Promise.all([
|
|
27
|
+
reads.readWallet(address),
|
|
28
|
+
reads.estimateGas({ sender: address, objectIds, epochs }),
|
|
29
|
+
]);
|
|
30
|
+
const walFrost = held(purse.wal);
|
|
31
|
+
const suiMist = held(purse.sui);
|
|
32
|
+
const unread = [];
|
|
33
|
+
if (!purse.wal.read)
|
|
34
|
+
unread.push(`WAL: ${purse.wal.why}`);
|
|
35
|
+
if (!purse.sui.read)
|
|
36
|
+
unread.push(`SUI: ${purse.sui.why}`);
|
|
37
|
+
let shortfall = null;
|
|
38
|
+
if (walFrost !== null && walFrost < priceFrost) {
|
|
39
|
+
shortfall =
|
|
40
|
+
`The wallet holds ${coinAmount(walFrost)} WAL and this extension costs ` +
|
|
41
|
+
`${coinAmount(priceFrost)} WAL.`;
|
|
42
|
+
}
|
|
43
|
+
else if (suiMist !== null && feeMist !== null && suiMist < feeMist) {
|
|
44
|
+
shortfall =
|
|
45
|
+
`The wallet holds ${coinAmount(suiMist)} SUI and the chain fee for this extension is ` +
|
|
46
|
+
`about ${coinAmount(feeMist)} SUI.`;
|
|
47
|
+
}
|
|
48
|
+
return { address, priceFrost, walFrost, suiMist, feeMist, unread, shortfall };
|
|
49
|
+
}
|
|
50
|
+
/** The budget as the machine-readable answer carries it. ⚠ Base units are strings — see `Facts`. */
|
|
51
|
+
export function budgetFacts(b) {
|
|
52
|
+
return {
|
|
53
|
+
wallet: b.address,
|
|
54
|
+
walletWal: b.walFrost === null ? null : coinAmount(b.walFrost),
|
|
55
|
+
walletSui: b.suiMist === null ? null : coinAmount(b.suiMist),
|
|
56
|
+
feeMist: b.feeMist === null ? null : b.feeMist.toString(),
|
|
57
|
+
feeSui: b.feeMist === null ? null : coinAmount(b.feeMist),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** The next step when the wallet is short: where to send what, said once. */
|
|
61
|
+
export function shortfallNextStep(b) {
|
|
62
|
+
const coin = b.walFrost !== null && b.walFrost < b.priceFrost ? "WAL" : "SUI";
|
|
63
|
+
return (`Nothing was signed and nothing was charged. Send ${coin} to ${b.address} — ` +
|
|
64
|
+
`\`${BINARY_NAME} wallet\` shows the address and both balances — and run this again.`);
|
|
65
|
+
}
|
|
66
|
+
/** The fee and the wallet, for a person, after the price. */
|
|
67
|
+
export function describeBudget(say, b) {
|
|
68
|
+
if (b.feeMist === null) {
|
|
69
|
+
say(` The chain fee (SUI) could not be measured just now; it is charged with the signature.`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
say(` Chain fee about ${coinAmount(b.feeMist)} SUI, measured by a dry run just now — the amount ` +
|
|
73
|
+
`charged is fixed when the transaction executes.`);
|
|
74
|
+
}
|
|
75
|
+
const wal = b.walFrost === null ? "WAL not read" : `${coinAmount(b.walFrost)} WAL`;
|
|
76
|
+
const sui = b.suiMist === null ? "SUI not read" : `${coinAmount(b.suiMist)} SUI`;
|
|
77
|
+
say(` Wallet ${b.address} holds ${wal} and ${sui}.`);
|
|
78
|
+
for (const why of b.unread) {
|
|
79
|
+
say(` A balance could not be read — ${why}. That is not zero: the chain decides at signing.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
|
|
2
|
+
import type { BlobLease, ExtendReads } from "./extend-plan.ts";
|
|
3
|
+
/** How long one chain question gets. A read that stalls is a read that failed. */
|
|
4
|
+
export declare const EXTEND_READ_TIMEOUT_MS = 20000;
|
|
5
|
+
/**
|
|
6
|
+
* A Walrus-aware client for one network.
|
|
7
|
+
*
|
|
8
|
+
* ⛔ THE NETWORK NAME REACHES THE SDK AS WELL AS THE URL, exactly as it does for an upload. A
|
|
9
|
+
* mirror pointed at the wrong chain would otherwise be discovered as a refusal from the storage
|
|
10
|
+
* contract — after a transaction had been signed.
|
|
11
|
+
*/
|
|
12
|
+
export declare function walrusClient(network: string): ReturnType<typeof build>;
|
|
13
|
+
declare function build(network: string): import("@mysten/sui/client").ClientWithExtensions<{
|
|
14
|
+
walrus: import("@mysten/walrus").WalrusClient;
|
|
15
|
+
}, SuiJsonRpcClient>;
|
|
16
|
+
/**
|
|
17
|
+
* One blob's lease, read from the Blob object itself.
|
|
18
|
+
*
|
|
19
|
+
* ⛔ NARROWED FROM `unknown`, NOT FROM THE SDK'S TYPE. `MoveStruct` is a three-way union whose
|
|
20
|
+
* members do not all carry an index signature, so reading a field off it means asserting — and
|
|
21
|
+
* an assertion compiles whether or not the check above it is right. What matters is the shape
|
|
22
|
+
* on the wire, and the predicate in `guards.ts` is what carries that narrowing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function readBlobLease(client: ReturnType<typeof build>, objectId: string): Promise<BlobLease>;
|
|
25
|
+
/**
|
|
26
|
+
* The reads one `nmts extend` run needs, bound to one network.
|
|
27
|
+
*
|
|
28
|
+
* ⚠ THE WINDOW IS `null` RATHER THAN A GUESS when the network cannot be read, exactly as it is for
|
|
29
|
+
* `nmts expiring`: the caller stops. An unread clock and a file in no danger look identical from
|
|
30
|
+
* outside and are the opposite of each other.
|
|
31
|
+
*/
|
|
32
|
+
export declare function extendReads(network: string): ExtendReads;
|
|
33
|
+
/**
|
|
34
|
+
* What a transaction actually costs in MIST: computation plus storage, less the rebate for storage
|
|
35
|
+
* it freed. Clamped at zero — a rebate can exceed the rest and the chain does not pay the sender.
|
|
36
|
+
* The browser app's `netGasFeeBaseUnits` is the same arithmetic.
|
|
37
|
+
*/
|
|
38
|
+
export declare function netGasFee(gasUsed: {
|
|
39
|
+
computationCost: string;
|
|
40
|
+
storageCost: string;
|
|
41
|
+
storageRebate: string;
|
|
42
|
+
}): bigint;
|
|
43
|
+
export {};
|
package/dist/extend-chain.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// what more epochs cost.
|
|
3
3
|
//
|
|
4
4
|
// ⛔ EVERYTHING HERE IS A READ. Nothing in this file builds a transaction, holds a key or moves an
|
|
5
|
-
// asset — the signature lives next door in `
|
|
5
|
+
// asset — the signature lives next door in `wallet-sign.ts`, alone, so that the file which can
|
|
6
6
|
// spend is the smallest one in this tool. What is shared is the client builder below, because
|
|
7
7
|
// the two must talk to the same chain: a quote read from one network and a payment made on
|
|
8
8
|
// another is a payment for nothing.
|
|
@@ -21,7 +21,10 @@ import { NmtsError } from "./errors.js";
|
|
|
21
21
|
import { epochClock } from "./expiry.js";
|
|
22
22
|
import { isRecord } from "./guards.js";
|
|
23
23
|
import { epochStartedMs } from "./walrus-write.js";
|
|
24
|
-
import {
|
|
24
|
+
import { suiRpcTransport } from "./sui-rpc.js";
|
|
25
|
+
import { readBalances, walCoinType } from "./wallet.js";
|
|
26
|
+
import { chainReader } from "./wallet-chain.js";
|
|
27
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
25
28
|
/** How long one chain question gets. A read that stalls is a read that failed. */
|
|
26
29
|
export const EXTEND_READ_TIMEOUT_MS = 20_000;
|
|
27
30
|
/**
|
|
@@ -37,7 +40,7 @@ export function walrusClient(network) {
|
|
|
37
40
|
function build(network) {
|
|
38
41
|
return new SuiJsonRpcClient({
|
|
39
42
|
network: network === "mainnet" ? "mainnet" : "testnet",
|
|
40
|
-
|
|
43
|
+
transport: suiRpcTransport(network),
|
|
41
44
|
}).$extend(walrus({}));
|
|
42
45
|
}
|
|
43
46
|
/** A number off the wire, whether it arrived as a number or as one of Sui's 64-bit strings. */
|
|
@@ -133,5 +136,39 @@ export function extendReads(network) {
|
|
|
133
136
|
const costs = await Promise.all(leases.map((lease) => client.walrus.storageCost(lease.size, epochs)));
|
|
134
137
|
return costs.reduce((sum, cost) => sum + BigInt(cost.storageCost), 0n);
|
|
135
138
|
},
|
|
139
|
+
async readWallet(address) {
|
|
140
|
+
const net = network === "mainnet" ? "mainnet" : "testnet";
|
|
141
|
+
return readBalances(chainReader(net, address), walCoinType(net));
|
|
142
|
+
},
|
|
143
|
+
async estimateGas({ sender, objectIds, epochs }) {
|
|
144
|
+
// ⛔ THE SAME TRANSACTION `wallet-sign.ts` SIGNS — sender, de-duplicated ids, one fragment per
|
|
145
|
+
// blob — so the fee measured is the fee of what would actually be approved. A different
|
|
146
|
+
// shape here would print a number no transaction ever pays.
|
|
147
|
+
try {
|
|
148
|
+
const tx = new Transaction();
|
|
149
|
+
tx.setSender(sender);
|
|
150
|
+
for (const blobObjectId of [...new Set(objectIds)]) {
|
|
151
|
+
tx.add(client.walrus.extendBlob({ blobObjectId, epochs }));
|
|
152
|
+
}
|
|
153
|
+
const bytes = await tx.build({ client });
|
|
154
|
+
const { effects } = await client.dryRunTransactionBlock({ transactionBlock: bytes });
|
|
155
|
+
if (effects.status.status !== "success")
|
|
156
|
+
return null;
|
|
157
|
+
return netGasFee(effects.gasUsed);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Not a number, and not zero: "could not measure" is a different fact from "free".
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
},
|
|
136
164
|
};
|
|
137
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* What a transaction actually costs in MIST: computation plus storage, less the rebate for storage
|
|
168
|
+
* it freed. Clamped at zero — a rebate can exceed the rest and the chain does not pay the sender.
|
|
169
|
+
* The browser app's `netGasFeeBaseUnits` is the same arithmetic.
|
|
170
|
+
*/
|
|
171
|
+
export function netGasFee(gasUsed) {
|
|
172
|
+
const fee = BigInt(gasUsed.computationCost) + BigInt(gasUsed.storageCost) - BigInt(gasUsed.storageRebate);
|
|
173
|
+
return fee > 0n ? fee : 0n;
|
|
174
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { EpochClock } from "./expiry.ts";
|
|
2
|
+
import type { WalletBalances } from "./wallet.ts";
|
|
3
|
+
/**
|
|
4
|
+
* The longest extension the NMTS server will RECORD, in epochs.
|
|
5
|
+
*
|
|
6
|
+
* ⛔ IT IS THE SERVER'S NUMBER AND IT IS CHECKED HERE ANYWAY, before the money moves. `api`'s
|
|
7
|
+
* `MAX_EXTEND_EPOCHS` (routes/storage.rs) refuses to record anything longer — and the recording
|
|
8
|
+
* happens AFTER the signature, so a length the chain would happily sell and the server would
|
|
9
|
+
* refuse to write down produces the worst outcome this command has: storage that is really
|
|
10
|
+
* extended, paid for, and a drive that goes on saying the old date.
|
|
11
|
+
*
|
|
12
|
+
* ⚠ A SECOND COPY, deliberately. The alternative is discovering the limit from a 400 after
|
|
13
|
+
* spending. `check:cli-routes` holds the addresses level; nothing holds this number level, so it
|
|
14
|
+
* is named with its origin and the refusal it produces says what the server would have said.
|
|
15
|
+
*/
|
|
16
|
+
export declare const MAX_RECORDABLE_EPOCHS = 104;
|
|
17
|
+
/**
|
|
18
|
+
* How long an extension is when nobody says.
|
|
19
|
+
*
|
|
20
|
+
* The same term one credit buys on the upload rail (`upload-price.ts`, `UPLOAD_EPOCHS`) and the
|
|
21
|
+
* cheapest rung the browser's picker offers. ⚠ It is a number of EPOCHS, not of days: two epochs
|
|
22
|
+
* is two days on testnet and twenty-eight on mainnet, so every surface that prints it prints the
|
|
23
|
+
* days beside it, read from the network's own clock.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_EXTEND_EPOCHS = 2;
|
|
26
|
+
/** One blob an extension would name, as the NMTS server describes it. */
|
|
27
|
+
export interface ExtendTarget {
|
|
28
|
+
/** The Sui object id of the blob — the argument the extend transaction takes. */
|
|
29
|
+
objectId: string;
|
|
30
|
+
/**
|
|
31
|
+
* How many of this account's files ride on this blob, trash included.
|
|
32
|
+
*
|
|
33
|
+
* 1 for a file with a blob to itself; more for a quilt, where ONE payment extends the whole
|
|
34
|
+
* cohort. It is printed rather than used: somebody paying for one file deserves to know the
|
|
35
|
+
* payment reaches five.
|
|
36
|
+
*/
|
|
37
|
+
sharedItems: number;
|
|
38
|
+
}
|
|
39
|
+
/** What `GET /v1/items/{id}/extend-preview` says, narrowed rather than trusted. */
|
|
40
|
+
export interface ExtendPreview {
|
|
41
|
+
targets: ExtendTarget[];
|
|
42
|
+
/** Parts on treasury-paid storage — not this account's to extend. */
|
|
43
|
+
treasuryParts: number;
|
|
44
|
+
/** Parts with no recorded Sui object id (pre-0010): nothing to name on-chain. */
|
|
45
|
+
untrackedParts: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The preview, or a refusal.
|
|
49
|
+
*
|
|
50
|
+
* ⛔ A TARGET THIS CANNOT READ IS A REFUSAL, NOT A TARGET TO SKIP. Skipping one would produce a
|
|
51
|
+
* transaction that extends some of a file's blobs and leaves the others to expire — and the
|
|
52
|
+
* file is unreadable if any single one of them goes, so the money would buy nothing.
|
|
53
|
+
*/
|
|
54
|
+
export declare function asExtendPreview(value: unknown): ExtendPreview;
|
|
55
|
+
/** One blob's lease, as the chain currently has it. */
|
|
56
|
+
export interface BlobLease {
|
|
57
|
+
objectId: string;
|
|
58
|
+
/** Unencoded size in bytes — what the storage price is computed from. */
|
|
59
|
+
size: number;
|
|
60
|
+
/** The epoch the lease runs out at. THE authoritative expiry. */
|
|
61
|
+
endEpoch: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* When the file actually runs out: the SOONEST end epoch across the blobs it rides on.
|
|
65
|
+
*
|
|
66
|
+
* ⛔ SOONEST, NOT FURTHEST. One expired blob is enough to make the file unreadable, so the file's
|
|
67
|
+
* deadline is the first of them. Null when there is no lease to read, which is a real state
|
|
68
|
+
* (every part on treasury-paid storage) and is never drawn as "now".
|
|
69
|
+
*/
|
|
70
|
+
export declare function soonestEnd(leases: readonly BlobLease[]): number | null;
|
|
71
|
+
/**
|
|
72
|
+
* The largest number of epochs these leases can ALL be extended by.
|
|
73
|
+
*
|
|
74
|
+
* The ceiling is per-blob — a lease may not end more than `maxAhead` epochs past the current one —
|
|
75
|
+
* so the blob that already reaches furthest into the future is the binding one. 0 is a real
|
|
76
|
+
* answer ("already paid as far ahead as the network allows"), not a failure.
|
|
77
|
+
*/
|
|
78
|
+
export declare function headroom(leases: readonly BlobLease[], current: number, maxAhead: number): number;
|
|
79
|
+
/**
|
|
80
|
+
* How many epochs to buy: what was asked for, or the default, checked against both ceilings.
|
|
81
|
+
*
|
|
82
|
+
* ⛔ IT REFUSES RATHER THAN CLAMPS. Quietly buying fewer epochs than somebody asked for spends
|
|
83
|
+
* their money on something they did not ask for, and quietly buying more spends more of it.
|
|
84
|
+
* Each refusal names the ceiling that produced it, because the two have different remedies:
|
|
85
|
+
* the network's is a wait, the server's is a shorter extension repeated later.
|
|
86
|
+
*/
|
|
87
|
+
export declare function chooseEpochs(asked: string | number | undefined, available: number): number;
|
|
88
|
+
/** Where the storage network's clock stands, and how far ahead it will sell. */
|
|
89
|
+
export interface ExtendWindow {
|
|
90
|
+
clock: EpochClock;
|
|
91
|
+
/**
|
|
92
|
+
* How many epochs past the current one a lease may reach — the protocol's own ceiling, read from
|
|
93
|
+
* the chain. ⛔ Never a constant: too high and the last length offered is refused on-chain after
|
|
94
|
+
* the transaction is signed; too low and this tool refuses to buy what the network would sell.
|
|
95
|
+
*/
|
|
96
|
+
maxAhead: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The chain, as this command needs it to READ.
|
|
100
|
+
*
|
|
101
|
+
* ⛔ A SEAM, NOT AN OPTION. No flag reaches it and nothing on a command line can supply one. It
|
|
102
|
+
* exists because the alternative is a test that talks to a live storage network — which cannot
|
|
103
|
+
* run offline, answers differently every fortnight, and can never be asked to be at its own
|
|
104
|
+
* ceiling on demand, which is most of what this command has to get right.
|
|
105
|
+
*/
|
|
106
|
+
export interface ExtendReads {
|
|
107
|
+
/** The clock and the ceiling, or null when the network could not be read at all. */
|
|
108
|
+
readWindow(): Promise<ExtendWindow | null>;
|
|
109
|
+
/** Each blob's own lease, in the order asked for. Rejects rather than guessing. */
|
|
110
|
+
readLeases(objectIds: readonly string[]): Promise<BlobLease[]>;
|
|
111
|
+
/** What extending all of them by `epochs` costs, in FROST (WAL base units). */
|
|
112
|
+
quote(leases: readonly BlobLease[], epochs: number): Promise<bigint>;
|
|
113
|
+
/**
|
|
114
|
+
* What the wallet that would sign holds right now, each coin answering for itself.
|
|
115
|
+
*
|
|
116
|
+
* ⛔ A BALANCE THAT COULD NOT BE READ COMES BACK AS THAT, never as zero — `wallet.ts` states the
|
|
117
|
+
* rule and this is where it matters most: a zero here would refuse a purchase the wallet can
|
|
118
|
+
* afford, and an unread balance drawn as enough would sign a transaction that fails.
|
|
119
|
+
*/
|
|
120
|
+
readWallet(address: string): Promise<WalletBalances>;
|
|
121
|
+
/**
|
|
122
|
+
* The chain fee of THIS extension in MIST (SUI base units), measured by dry-running the exact
|
|
123
|
+
* transaction that would be signed — or `null` when the chain could not measure it (an empty
|
|
124
|
+
* wallet has no gas coin to dry-run with; a node can be down). ⛔ NEVER ZERO FOR "UNKNOWN".
|
|
125
|
+
*/
|
|
126
|
+
estimateGas(input: {
|
|
127
|
+
sender: string;
|
|
128
|
+
objectIds: readonly string[];
|
|
129
|
+
epochs: number;
|
|
130
|
+
}): Promise<bigint | null>;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The one thing in this tool that signs.
|
|
134
|
+
*
|
|
135
|
+
* ⛔ IT IS A SEPARATE SEAM FROM THE READS ON PURPOSE. A test can then prove what matters most
|
|
136
|
+
* about this command — that `--dry-run` and a missing agreement both stop BEFORE this function
|
|
137
|
+
* is reached — by handing it one that records being called and fails the test if it ever is.
|
|
138
|
+
* Folded into `ExtendReads`, "did it sign" would be a question about which method ran.
|
|
139
|
+
*
|
|
140
|
+
* Returns the transaction digest, which is what the server records as the replay guard.
|
|
141
|
+
*/
|
|
142
|
+
export type SignExtension = (input: {
|
|
143
|
+
network: string;
|
|
144
|
+
/** ⛔ The NMTS key. It never leaves this machine: it derives the wallet and nothing else. */
|
|
145
|
+
code: string;
|
|
146
|
+
objectIds: readonly string[];
|
|
147
|
+
epochs: number;
|
|
148
|
+
}) => Promise<string>;
|
package/dist/extend-plan.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// ⛔ NO NETWORK, NO SDK, NO KEY. Everything here is arithmetic over numbers somebody else read, so
|
|
4
4
|
// `node --test` can drive every branch — including the ones a live storage network only reaches
|
|
5
5
|
// by being at its ceiling, or by having sold a lease that already ran out. The reads live in
|
|
6
|
-
// `extend-chain.ts`, the signature in `
|
|
6
|
+
// `extend-chain.ts`, the signature in `wallet-sign.ts`, and neither can be reached from here.
|
|
7
7
|
//
|
|
8
8
|
// ⛔ THE CHAIN IS THE AUTHORITY ON WHEN A LEASE ENDS, not the server's `expiry_epoch`. That column
|
|
9
9
|
// is client-reported and advisory — it is what `nmts expiring` ranks by, because ranking is all
|
package/dist/gate.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Autonomy } from "./autonomy.ts";
|
|
2
|
+
import type { ParsedArgs } from "./args.ts";
|
|
3
|
+
import { CONSENTS } from "./consent.ts";
|
|
4
|
+
import { type ActId } from "./risk.ts";
|
|
5
|
+
export interface GateIo {
|
|
6
|
+
write?: ((line: string) => void) | undefined;
|
|
7
|
+
/** Injected in tests: answers the y/N. Its presence stands in for a terminal. */
|
|
8
|
+
readLine?: ((question: string) => Promise<string>) | undefined;
|
|
9
|
+
now?: (() => Date) | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface Passage {
|
|
12
|
+
/** The command must still get a yes in its own words — a review and --yes, a typed sentence. */
|
|
13
|
+
ask: boolean;
|
|
14
|
+
mode: Autonomy;
|
|
15
|
+
}
|
|
16
|
+
/** Whether the unlock behind an act is open right now. */
|
|
17
|
+
export declare function unlocked(key: keyof typeof CONSENTS, now: Date): Promise<boolean>;
|
|
18
|
+
export declare function gate(act: ActId, args: ParsedArgs, io?: GateIo): Promise<Passage>;
|
package/dist/gate.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// The one place a tier meets a mode: refuse, ask, or wave through.
|
|
2
|
+
//
|
|
3
|
+
// ⛔ EVERY COMMAND PASSES HERE BEFORE IT RUNS (`main.ts`), with the act `risk.ts` names for its
|
|
4
|
+
// command line. What it decides, in this order and nowhere else:
|
|
5
|
+
// 1. none runs.
|
|
6
|
+
// 2. skip-permissions runs everything — an ultra-high act with a written --reason, kept in the
|
|
7
|
+
// run log.
|
|
8
|
+
// 3. ultra-high: a person at the terminal (mode default) may go on to the command's own typed
|
|
9
|
+
// sentence; an auto mode is refused, unlocked or not.
|
|
10
|
+
// 4. high sits behind an unlock. Locked is refused with the one command that unlocks it, which
|
|
11
|
+
// only a person at a terminal can run.
|
|
12
|
+
// 5. A yes is needed for high in every mode, and for low and medium in default. An act that
|
|
13
|
+
// asks itself is told so and asks in its own words; anything else is asked here — y/N at a
|
|
14
|
+
// terminal, or exit 5 with the sentence an agent shows the person, answered by --yes.
|
|
15
|
+
//
|
|
16
|
+
// ⛔ WHAT `--yes` PROVES: nothing. No command-line tool can tell whether a person or a program typed
|
|
17
|
+
// it. The instructions say an agent passes it only after the person said yes; this file makes the
|
|
18
|
+
// stop impossible to miss and the question the same every time. Saying more would be a claim.
|
|
19
|
+
import { currentMode } from "./autonomy.js";
|
|
20
|
+
import { CONSENTS, isGranted } from "./consent.js";
|
|
21
|
+
import { NmtsError } from "./errors.js";
|
|
22
|
+
import { BINARY_NAME } from "./product.js";
|
|
23
|
+
import { promptLine, stdinIsATerminal } from "./prompt.js";
|
|
24
|
+
import { ACTS } from "./risk.js";
|
|
25
|
+
/** Whether the unlock behind an act is open right now. */
|
|
26
|
+
export async function unlocked(key, now) {
|
|
27
|
+
if (key === "wallet") {
|
|
28
|
+
// ⚠ Loaded here, not at the top: the wallet module reaches the chain SDK, and this file
|
|
29
|
+
// runs on every command (`check:cli-startup`).
|
|
30
|
+
const { readWalletGrant, walletGrantState } = await import("./wallet-grant.js");
|
|
31
|
+
return walletGrantState(readWalletGrant(), now) === "active";
|
|
32
|
+
}
|
|
33
|
+
return isGranted(key);
|
|
34
|
+
}
|
|
35
|
+
export async function gate(act, args, io = {}) {
|
|
36
|
+
const a = ACTS[act];
|
|
37
|
+
const mode = currentMode();
|
|
38
|
+
const now = io.now ?? (() => new Date());
|
|
39
|
+
if (a.tier === "none")
|
|
40
|
+
return { ask: false, mode };
|
|
41
|
+
if (mode === "skip-permissions") {
|
|
42
|
+
if (a.tier === "ultra-high" && (args.reason === undefined || args.reason.trim() === "")) {
|
|
43
|
+
throw new NmtsError(`${a.what} This is permanent, and skip-permissions still wants the reason written down.`, {
|
|
44
|
+
exitCode: 5,
|
|
45
|
+
nextStep: `Think it through first — is this really what the person would want done right now, and ` +
|
|
46
|
+
`why? Then run the same command with --reason "<that, in a sentence>". The reason is kept ` +
|
|
47
|
+
`in this machine's run log.`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return { ask: false, mode };
|
|
51
|
+
}
|
|
52
|
+
if (a.tier === "ultra-high") {
|
|
53
|
+
if (mode !== "default") {
|
|
54
|
+
throw new NmtsError(`${a.what} Not from an agent, in any auto mode.`, {
|
|
55
|
+
exitCode: 5,
|
|
56
|
+
nextStep: `A person does this at the terminal (mode default). Tell them what you wanted and stop; ` +
|
|
57
|
+
`there is no unlock for it.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return { ask: true, mode };
|
|
61
|
+
}
|
|
62
|
+
if ("lock" in a && !(await unlocked(a.lock, now()))) {
|
|
63
|
+
const c = CONSENTS[a.lock];
|
|
64
|
+
throw new NmtsError(`${a.what} This is locked until a person unlocks it on this machine.`, {
|
|
65
|
+
exitCode: 5,
|
|
66
|
+
nextStep: [
|
|
67
|
+
c.risk,
|
|
68
|
+
"",
|
|
69
|
+
c.limit,
|
|
70
|
+
"",
|
|
71
|
+
`To unlock, at a terminal, once: ${BINARY_NAME} unlock ${a.lock}`,
|
|
72
|
+
`To see what is unlocked: ${BINARY_NAME} unlock`,
|
|
73
|
+
"",
|
|
74
|
+
`⛔ If a program is reading this on somebody's behalf: show it to them and let them decide.`,
|
|
75
|
+
` Do not run the unlock command yourself.`,
|
|
76
|
+
].join("\n"),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const needsYes = a.tier === "high" ? !("standing" in a) : mode === "default";
|
|
80
|
+
if (!needsYes)
|
|
81
|
+
return { ask: false, mode };
|
|
82
|
+
if ("asksItself" in a)
|
|
83
|
+
return { ask: !args.yes, mode };
|
|
84
|
+
if (args.yes)
|
|
85
|
+
return { ask: false, mode };
|
|
86
|
+
const say = io.write ?? ((line) => process.stderr.write(`${line}\n`));
|
|
87
|
+
if (io.readLine !== undefined || stdinIsATerminal()) {
|
|
88
|
+
const ask = io.readLine ?? promptLine;
|
|
89
|
+
say(a.what ?? act);
|
|
90
|
+
const answer = (await ask(`Go ahead? [y/N] `)).trim();
|
|
91
|
+
if (answer === "y" || answer === "Y")
|
|
92
|
+
return { ask: false, mode };
|
|
93
|
+
throw new NmtsError(`Nothing was done.`, { exitCode: 1, nextStep: null });
|
|
94
|
+
}
|
|
95
|
+
throw new NmtsError(a.what ?? act, {
|
|
96
|
+
exitCode: 5,
|
|
97
|
+
nextStep: `This needs the person's yes. Tell them, in plain words, what this does and what it costs; ` +
|
|
98
|
+
`if they say yes, run the same command with --yes. Nothing was done.`,
|
|
99
|
+
});
|
|
100
|
+
}
|
package/dist/guards.d.ts
ADDED
package/dist/help.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function helpText(version: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* `nmts help <command>`: the document for one command, from `docs/commands/`, or the list of
|
|
4
|
+
* documents when the name matches none.
|
|
5
|
+
*
|
|
6
|
+
* ⚠ The directory is read only here, so `--help` itself pays nothing for it (`check:cli-startup`).
|
|
7
|
+
* Each document names the commands it covers on its `Commands:` line; that line is the index.
|
|
8
|
+
*/
|
|
9
|
+
export declare function helpFor(topic: string): Promise<{
|
|
10
|
+
text: string;
|
|
11
|
+
found: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* What `--help`, a bare run, `help`, and `help <command>` print, and the exit code.
|
|
15
|
+
* ⛔ `support` has help of its own: it is READ before deciding, not scanned for an option name.
|
|
16
|
+
*/
|
|
17
|
+
export declare function printHelp(args: {
|
|
18
|
+
command: string | null;
|
|
19
|
+
operands: readonly string[];
|
|
20
|
+
}, write: (text: string) => void): Promise<number>;
|