@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,182 @@
|
|
|
1
|
+
import { type Hash } from "node:crypto";
|
|
2
|
+
/** Where unfinished uploads live. */
|
|
3
|
+
export declare function uploadsDir(): string;
|
|
4
|
+
/**
|
|
5
|
+
* A stable, account-scoped name for one file's upload attempt.
|
|
6
|
+
*
|
|
7
|
+
* Same account, same bytes, same destination give the same key — which is what lets a second `put`
|
|
8
|
+
* of a file whose first attempt died find the reservation instead of paying again.
|
|
9
|
+
*
|
|
10
|
+
* ⛔ THE DESTINATION IS PART OF IT, and leaving it out was a real defect. Two local files with
|
|
11
|
+
* identical content — a copy, a re-download, `a.bin` and `backup/a.bin` — would otherwise share
|
|
12
|
+
* one reservation, and putting the second one would silently resume the first: it would report
|
|
13
|
+
* success, spend nothing, and write a SECOND file-list entry pointing at the FIRST file's item.
|
|
14
|
+
* Deleting either would then break the other. They are two files in the drive, so they are two
|
|
15
|
+
* uploads.
|
|
16
|
+
*
|
|
17
|
+
* ⚠ It is the destination AS TYPED, not the folder id, because the id needs a network round trip
|
|
18
|
+
* and this key is wanted before one. Two spellings of one folder therefore make two reservations
|
|
19
|
+
* — one extra unfinished record, never a wrong file.
|
|
20
|
+
*/
|
|
21
|
+
export declare function reservationKey(dataKey: Uint8Array, plaintext: Uint8Array, name: string, destination: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* The same key, computed without ever holding the file.
|
|
24
|
+
*
|
|
25
|
+
* ⛔ IT MUST HASH THE IDENTICAL BYTE SEQUENCE. A file large enough to need several parts is a file
|
|
26
|
+
* too large to hand `reservationKey` as one array, and a second construction here — hashing a
|
|
27
|
+
* hash, hashing the parts' digests — would give the same file two different keys depending on
|
|
28
|
+
* how it was read. The one above is written in terms of this one so there is only ever one
|
|
29
|
+
* answer, and a test feeds the same file both ways to hold that.
|
|
30
|
+
*/
|
|
31
|
+
export declare function reservationKeyStreamed(dataKey: Uint8Array, plaintextChunks: Iterable<Uint8Array>, name: string, destination: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Begin the hash a reservation key is made from.
|
|
34
|
+
*
|
|
35
|
+
* ⛔ TWO HASHES, ONE READ. A file large enough to need parts is read once to work out its key AND
|
|
36
|
+
* the SHA-256 the account checks its contents against; handing the caller the running hash is
|
|
37
|
+
* what lets both come out of a single pass instead of two reads of a very large file.
|
|
38
|
+
*/
|
|
39
|
+
export declare function startReservationKey(dataKey: Uint8Array): Hash;
|
|
40
|
+
/** Finish it. The name and the destination go in last, exactly as the one-shot form does. */
|
|
41
|
+
export declare function finishReservationKey(hash: Hash, name: string, destination: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* The record name for ONE part of a file.
|
|
44
|
+
*
|
|
45
|
+
* ⛔ EVERY PART IS ITS OWN RESERVATION. Each one buys its own storage, under its own idempotency
|
|
46
|
+
* key, and can fail or resume on its own — so each one is written down on its own. Sharing a
|
|
47
|
+
* record between parts would mean a run that died between part 3 and part 4 could not say which
|
|
48
|
+
* of them the credits had already been spent on.
|
|
49
|
+
*/
|
|
50
|
+
export declare function partKey(fileKey: string, partIndex: number): string;
|
|
51
|
+
/** What is known about an upload that has not finished. Written before the credits move. */
|
|
52
|
+
export interface Reservation {
|
|
53
|
+
/** The storage network's id for the sealed bytes. Deterministic in (bytes, nonce). */
|
|
54
|
+
blobId: string;
|
|
55
|
+
/** The relay tip nonce, base64url. Re-fed on a retry so the digest repeats. */
|
|
56
|
+
nonceB64: string;
|
|
57
|
+
/** Merkle root of the encoded blob, base64url. The server hands it to the chain verbatim. */
|
|
58
|
+
rootHashB64: string;
|
|
59
|
+
/** The relay the tip was paid to. A retry must go to the SAME one. */
|
|
60
|
+
relayUrl: string;
|
|
61
|
+
/** Storage term, in storage-network epochs. */
|
|
62
|
+
epochs: number;
|
|
63
|
+
/** Sealed byte count — what storage was bought for and what the credits counted. */
|
|
64
|
+
sealedLen: number;
|
|
65
|
+
/**
|
|
66
|
+
* The WHOLE FILE's plaintext byte count — what the file list records.
|
|
67
|
+
*
|
|
68
|
+
* ⚠ NOT THIS PART'S LENGTH. A file stored in several parts has one entry in the list and that
|
|
69
|
+
* entry names the file's size; `partPlaintextLen` below is the piece this record covers. They
|
|
70
|
+
* are equal for a file that fits in one part, which is why keeping the field's meaning
|
|
71
|
+
* unchanged matters: it is read straight into the list entry.
|
|
72
|
+
*/
|
|
73
|
+
plaintextLen: number;
|
|
74
|
+
/** This part's own plaintext byte count. Equal to `plaintextLen` when the file is one part. */
|
|
75
|
+
partPlaintextLen: number;
|
|
76
|
+
/**
|
|
77
|
+
* Where this part sits in the file — its index, and how many parts there are.
|
|
78
|
+
*
|
|
79
|
+
* ⛔ SEALED INTO THE BYTES, NOT JUST RECORDED HERE. NCF-3 puts both numbers in each part's
|
|
80
|
+
* header and therefore in every chunk's associated data, so a part served in another part's
|
|
81
|
+
* position fails authentication rather than decrypting into the wrong place. What is here is
|
|
82
|
+
* a copy for the resume: a run that came back has to seal the SAME piece of the file under
|
|
83
|
+
* the SAME placement, or the bytes it pushes are not the blob that was paid for.
|
|
84
|
+
*/
|
|
85
|
+
partIndex: number;
|
|
86
|
+
partTotal: number;
|
|
87
|
+
/** The file's own key, wrapped. Carried so a resumed commit writes the same list entry. */
|
|
88
|
+
dekWrapped: string;
|
|
89
|
+
/** The sealed content hash. Same reason. */
|
|
90
|
+
contentHashCt: string;
|
|
91
|
+
/** The name this file is to have in the account's file list. */
|
|
92
|
+
name: string;
|
|
93
|
+
/** The folder id it goes in, or null for the root. */
|
|
94
|
+
parentId: string | null;
|
|
95
|
+
/**
|
|
96
|
+
* How many reservations this file has needed. Part of the idempotency key.
|
|
97
|
+
*
|
|
98
|
+
* ⛔ WITHOUT IT, A FAILED RESERVATION BRICKS THIS FILE FOREVER. The idempotency key is derived
|
|
99
|
+
* from a key that is a pure function of (account, bytes, destination), and the server replays
|
|
100
|
+
* a reservation row under its key WHATEVER STATE IT IS IN — including `failed`, which can
|
|
101
|
+
* never become storage. So every later attempt would be handed the same dead row, be told to
|
|
102
|
+
* start over, start over into the same dead row, and this account could never upload this
|
|
103
|
+
* file again unless a byte of it changed. Counting up is what "start over" actually means.
|
|
104
|
+
*/
|
|
105
|
+
attempt: number;
|
|
106
|
+
/** Present once the server answered: the reservation row. */
|
|
107
|
+
ledgerId?: number;
|
|
108
|
+
/** Present once registered: the transaction the relay checks its tip in. */
|
|
109
|
+
registerTxDigest?: string;
|
|
110
|
+
/** Present once registered: the on-chain blob object. */
|
|
111
|
+
blobObjectId?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Present when the PERSON'S OWN WALLET is paying (`upload-wallet.ts`), absent on the credit rail.
|
|
114
|
+
*
|
|
115
|
+
* ⛔ WRITTEN SO THE OTHER RAIL REFUSES THE RECORD. The bytes and the blob id are the same
|
|
116
|
+
* whoever pays, but what "paid" means is not: a credit record names a reservation the server
|
|
117
|
+
* can be asked about, a wallet record names a transaction the person signed. A run on one
|
|
118
|
+
* rail that resumed the other's record would either buy the storage a second time or commit
|
|
119
|
+
* a part under the wrong payer.
|
|
120
|
+
*/
|
|
121
|
+
paidFrom?: "wallet";
|
|
122
|
+
/** Wallet rail: present once the certify transaction executed — the part is finished on-chain. */
|
|
123
|
+
certifyTxDigest?: string;
|
|
124
|
+
/** Wallet rail: the epoch the bought storage ends at, read from the blob object after registering. */
|
|
125
|
+
endEpoch?: number;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The waiting reservation's RECORD, without its sealed bytes.
|
|
129
|
+
*
|
|
130
|
+
* ⛔ THE BYTES ARE THE FILE. Reading them to answer "has this part been paid for?" would mean a
|
|
131
|
+
* resume that only needs to commit still reads every byte of a very large upload off the disk.
|
|
132
|
+
* They are fetched separately, by the one step that actually pushes them.
|
|
133
|
+
*/
|
|
134
|
+
export declare function readReservationRecord(key: string): Reservation | null;
|
|
135
|
+
/**
|
|
136
|
+
* The sealed bytes a reservation bought.
|
|
137
|
+
*
|
|
138
|
+
* ⛔ NEVER RE-SEALED ONES. Sealing is non-deterministic, so bytes produced by a later run are a
|
|
139
|
+
* different blob from the one the treasury registered — the relay refuses them, forever, and
|
|
140
|
+
* the credits are gone.
|
|
141
|
+
*/
|
|
142
|
+
export declare function readReservationBytes(key: string): Uint8Array;
|
|
143
|
+
/** The record and its bytes together, for the callers that need both. */
|
|
144
|
+
export declare function readReservation(key: string): {
|
|
145
|
+
record: Reservation;
|
|
146
|
+
sealed: Uint8Array;
|
|
147
|
+
} | null;
|
|
148
|
+
/** Write the record and its sealed bytes. Called BEFORE the reserve, and again after it answers. */
|
|
149
|
+
export declare function writeReservation(key: string, record: Reservation, sealed: Uint8Array): void;
|
|
150
|
+
/**
|
|
151
|
+
* Forget a reservation.
|
|
152
|
+
*
|
|
153
|
+
* ⚠ Called on success AND on a couple of failure paths, so the comment that used to say "the
|
|
154
|
+
* upload already succeeded" was not true of every caller. What IS true of all of them is that
|
|
155
|
+
* nothing further depends on the record, which is why it never throws.
|
|
156
|
+
*/
|
|
157
|
+
export declare function clearReservation(key: string): void;
|
|
158
|
+
/**
|
|
159
|
+
* The FILE-level half of an unfinished upload: what happened after every part was paid for.
|
|
160
|
+
*
|
|
161
|
+
* ⛔ IT CANNOT LIVE ON A PART. Committing is one act for the whole file — one `POST /v1/items`
|
|
162
|
+
* naming every part — so "this file is committed" is not a fact about part 3. Writing it onto
|
|
163
|
+
* one arbitrary part would work until somebody reordered the resume, and then a committed file
|
|
164
|
+
* would be committed a second time.
|
|
165
|
+
*/
|
|
166
|
+
export interface ItemRecord {
|
|
167
|
+
/** Present once `POST /v1/items` answered: the file exists on the server and is paid for. */
|
|
168
|
+
itemId?: string;
|
|
169
|
+
/**
|
|
170
|
+
* How many commits this file has attempted. Part of the commit's idempotency key.
|
|
171
|
+
*
|
|
172
|
+
* Separate from a part's `attempt` for the same reason the record is: a part that had to buy its
|
|
173
|
+
* storage twice says nothing about how many times the file was committed.
|
|
174
|
+
*/
|
|
175
|
+
attempt: number;
|
|
176
|
+
}
|
|
177
|
+
/** What is known about this file's commit, or `null` when it has not been attempted. */
|
|
178
|
+
export declare function readItemRecord(fileKey: string): ItemRecord | null;
|
|
179
|
+
/** Write the file-level record. Called before the commit, and again once it has an id. */
|
|
180
|
+
export declare function writeItemRecord(fileKey: string, record: ItemRecord): void;
|
|
181
|
+
/** Forget the file-level record. Never throws, for the same reason `clearReservation` does not. */
|
|
182
|
+
export declare function clearItemRecord(fileKey: string): void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
|
|
2
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
3
|
+
import type { Network } from "./network.ts";
|
|
4
|
+
import type { RegisterShape, WalletUploadReads } from "./upload-wallet-plan.ts";
|
|
5
|
+
import type { Certificate } from "./upload-wire.ts";
|
|
6
|
+
/**
|
|
7
|
+
* The most this tool will pay an upload relay as a tip, in MIST, per network.
|
|
8
|
+
*
|
|
9
|
+
* ⚠ A SECOND COPY of the browser's `RELAY_TIP_MAX_MIST`, for the same reason `WAL_COIN_TYPES` is:
|
|
10
|
+
* this package imports nothing from that tree. It is a CEILING, not the charge — the relay's own
|
|
11
|
+
* tip configuration sets the amount, which the review prints — and a relay asking for more than
|
|
12
|
+
* this is refused by the SDK before anything is signed.
|
|
13
|
+
*/
|
|
14
|
+
export declare const RELAY_TIP_CEILING_MIST: Readonly<Record<Network, number>>;
|
|
15
|
+
/** The Walrus package addresses of one network. Exported from the SDK; the system object survives upgrades. */
|
|
16
|
+
export declare function packageConfig(network: Network): {
|
|
17
|
+
systemObjectId: string;
|
|
18
|
+
};
|
|
19
|
+
declare function build(network: Network, relayUrl: string): import("@mysten/sui/client").ClientWithExtensions<{
|
|
20
|
+
walrus: import("@mysten/walrus").WalrusClient;
|
|
21
|
+
}, SuiJsonRpcClient>;
|
|
22
|
+
export type PayingClient = ReturnType<typeof build>;
|
|
23
|
+
/** A Walrus client bound to ONE relay, able to pay that relay's tip. */
|
|
24
|
+
export declare function payingClient(network: Network, relayUrl: string): PayingClient;
|
|
25
|
+
/**
|
|
26
|
+
* The register transaction of ONE part — the tip, then either a purchase or a held resource.
|
|
27
|
+
*
|
|
28
|
+
* ⛔ SENDER FIRST. `coinWithBalance` and the SDK's own coin selection pick WAL and SUI from the
|
|
29
|
+
* sender's address when the fragments resolve; without it the build fails late.
|
|
30
|
+
*/
|
|
31
|
+
export declare function registerTransaction(client: PayingClient, network: Network, input: RegisterShape & {
|
|
32
|
+
sender: string;
|
|
33
|
+
}): Promise<Transaction>;
|
|
34
|
+
/** The certify transaction of ONE part, from the certificate the relay handed back. */
|
|
35
|
+
export declare function certifyTransaction(client: PayingClient, input: {
|
|
36
|
+
blobId: string;
|
|
37
|
+
blobObjectId: string;
|
|
38
|
+
certificate: Certificate;
|
|
39
|
+
}): Transaction;
|
|
40
|
+
/**
|
|
41
|
+
* The blob object a register transaction created, and when its storage ends.
|
|
42
|
+
*
|
|
43
|
+
* ⛔ THE OBJECT IS FOUND BY ITS TYPE, not by position: the transaction also creates the leftover
|
|
44
|
+
* resource on a cut, and on a purchase the storage object is created and consumed inside it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function createdBlob(client: PayingClient, objectChanges: unknown): Promise<{
|
|
47
|
+
blobObjectId: string;
|
|
48
|
+
endEpoch: number;
|
|
49
|
+
}>;
|
|
50
|
+
/** What this part is once the network has encoded it — the number registration compares a resource against. */
|
|
51
|
+
export declare function encodedLength(client: PayingClient, sender: string, sealedLen: number): Promise<number>;
|
|
52
|
+
/** The live reads one wallet-paid upload needs, bound to one network and one relay. */
|
|
53
|
+
export declare function walletUploadReads(network: Network, relayUrl: string): WalletUploadReads;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// The chain behind a WALLET-PAID upload: the client that can pay a relay's tip, the register and
|
|
2
|
+
// certify transactions, the live reads that price an upload, and the two facts read back after
|
|
3
|
+
// the register signature.
|
|
4
|
+
//
|
|
5
|
+
// ⛔ ONE BUILDER FOR THE FEE AND THE SIGNATURE. `registerTransaction` is what the dry run measures
|
|
6
|
+
// and what `wallet-sign.ts` signs — the same rule `wallet-send-chain.ts` keeps. Two builders
|
|
7
|
+
// would let the review price one transaction and the wallet approve another.
|
|
8
|
+
//
|
|
9
|
+
// ⛔ THE TIP IS IN THE REGISTER TRANSACTION, exactly as the SDK's own flow orders it: the auth
|
|
10
|
+
// payload and the transfer to the relay first, then the registration. On the credit rail the
|
|
11
|
+
// treasury pays that tip inside its own transaction; here the person does, and the relay checks
|
|
12
|
+
// it in the transaction named when the bytes arrive (`walrus-write.ts`).
|
|
13
|
+
//
|
|
14
|
+
// ⛔ THE ENCODED SIZE IS THE CHAIN'S ARITHMETIC, NOT A COPY. Registration checks
|
|
15
|
+
// `encoded_size <= storage_size` with `walrus::encoding::encoded_blob_length`, and the SDK keeps
|
|
16
|
+
// its own copy unexported. Cutting a held resource to fit needs that exact number, so it is
|
|
17
|
+
// asked of the chain itself, in a dev-inspect that costs nothing — a copy kept here would be
|
|
18
|
+
// wrong the day the protocol changed it, and the way that surfaces is a refused registration
|
|
19
|
+
// after the split was signed.
|
|
20
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
21
|
+
import { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
|
|
22
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
23
|
+
import { blobIdFromInt, blobIdToInt, MAINNET_WALRUS_PACKAGE_CONFIG, TESTNET_WALRUS_PACKAGE_CONFIG, walrus, } from "@mysten/walrus";
|
|
24
|
+
import { NmtsError } from "./errors.js";
|
|
25
|
+
import { extendReads, netGasFee, readBlobLease } from "./extend-chain.js";
|
|
26
|
+
import { readOwnedStorage, readStorageType } from "./shared/lib/storage-control/chain.js";
|
|
27
|
+
import { registerIntoStorage, splitStorageToFit } from "./shared/lib/storage-control/reuse.js";
|
|
28
|
+
import { suiRpcTransport } from "./sui-rpc.js";
|
|
29
|
+
import { readBalances, walCoinType } from "./wallet.js";
|
|
30
|
+
import { chainReader } from "./wallet-chain.js";
|
|
31
|
+
/**
|
|
32
|
+
* The most this tool will pay an upload relay as a tip, in MIST, per network.
|
|
33
|
+
*
|
|
34
|
+
* ⚠ A SECOND COPY of the browser's `RELAY_TIP_MAX_MIST`, for the same reason `WAL_COIN_TYPES` is:
|
|
35
|
+
* this package imports nothing from that tree. It is a CEILING, not the charge — the relay's own
|
|
36
|
+
* tip configuration sets the amount, which the review prints — and a relay asking for more than
|
|
37
|
+
* this is refused by the SDK before anything is signed.
|
|
38
|
+
*/
|
|
39
|
+
export const RELAY_TIP_CEILING_MIST = {
|
|
40
|
+
testnet: 100_000,
|
|
41
|
+
mainnet: 250_000_000,
|
|
42
|
+
};
|
|
43
|
+
/** The Walrus package addresses of one network. Exported from the SDK; the system object survives upgrades. */
|
|
44
|
+
export function packageConfig(network) {
|
|
45
|
+
return network === "mainnet" ? MAINNET_WALRUS_PACKAGE_CONFIG : TESTNET_WALRUS_PACKAGE_CONFIG;
|
|
46
|
+
}
|
|
47
|
+
function build(network, relayUrl) {
|
|
48
|
+
return new SuiJsonRpcClient({ network, transport: suiRpcTransport(network) }).$extend(walrus({ uploadRelay: { host: relayUrl, sendTip: { max: RELAY_TIP_CEILING_MIST[network] } } }));
|
|
49
|
+
}
|
|
50
|
+
/** A Walrus client bound to ONE relay, able to pay that relay's tip. */
|
|
51
|
+
export function payingClient(network, relayUrl) {
|
|
52
|
+
return build(network, relayUrl);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The register transaction of ONE part — the tip, then either a purchase or a held resource.
|
|
56
|
+
*
|
|
57
|
+
* ⛔ SENDER FIRST. `coinWithBalance` and the SDK's own coin selection pick WAL and SUI from the
|
|
58
|
+
* sender's address when the fragments resolve; without it the build fails late.
|
|
59
|
+
*/
|
|
60
|
+
export async function registerTransaction(client, network, input) {
|
|
61
|
+
const tx = new Transaction();
|
|
62
|
+
tx.setSender(input.sender);
|
|
63
|
+
const { part } = input;
|
|
64
|
+
tx.add(client.walrus.sendUploadRelayTip({ size: part.sealedLen, blobDigest: part.blobDigest, nonce: part.nonce }));
|
|
65
|
+
if (input.storage.kind === "buy") {
|
|
66
|
+
const blob = tx.add(client.walrus.registerBlob({
|
|
67
|
+
size: part.sealedLen,
|
|
68
|
+
epochs: input.epochs,
|
|
69
|
+
blobId: part.blobId,
|
|
70
|
+
rootHash: part.rootHash,
|
|
71
|
+
deletable: true,
|
|
72
|
+
}));
|
|
73
|
+
tx.transferObjects([blob], input.sender);
|
|
74
|
+
return tx;
|
|
75
|
+
}
|
|
76
|
+
const walrusPackageId = (await client.walrus.systemObject()).package_id;
|
|
77
|
+
if (input.storage.cutToBytes !== null) {
|
|
78
|
+
splitStorageToFit({
|
|
79
|
+
walrusPackageId,
|
|
80
|
+
storageObjectId: input.storage.objectId,
|
|
81
|
+
keepBytes: input.storage.cutToBytes,
|
|
82
|
+
owner: input.sender,
|
|
83
|
+
}, tx);
|
|
84
|
+
}
|
|
85
|
+
registerIntoStorage({
|
|
86
|
+
systemObjectId: packageConfig(network).systemObjectId,
|
|
87
|
+
walrusPackageId,
|
|
88
|
+
walType: walCoinType(network),
|
|
89
|
+
storageObjectId: input.storage.objectId,
|
|
90
|
+
blobIdAsInt: blobIdToInt(part.blobId),
|
|
91
|
+
rootHash: part.rootHash,
|
|
92
|
+
rawBytes: part.sealedLen,
|
|
93
|
+
writeCost: input.storage.writeFrost,
|
|
94
|
+
deletable: true,
|
|
95
|
+
owner: input.sender,
|
|
96
|
+
}, tx);
|
|
97
|
+
return tx;
|
|
98
|
+
}
|
|
99
|
+
/** The certify transaction of ONE part, from the certificate the relay handed back. */
|
|
100
|
+
export function certifyTransaction(client, input) {
|
|
101
|
+
return client.walrus.certifyBlobTransaction({
|
|
102
|
+
blobId: input.blobId,
|
|
103
|
+
blobObjectId: input.blobObjectId,
|
|
104
|
+
deletable: true,
|
|
105
|
+
certificate: {
|
|
106
|
+
signers: input.certificate.signers,
|
|
107
|
+
serializedMessage: new Uint8Array(Buffer.from(input.certificate.serialized_message_b64, "base64url")),
|
|
108
|
+
signature: new Uint8Array(Buffer.from(input.certificate.signature_b64, "base64url")),
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The blob object a register transaction created, and when its storage ends.
|
|
114
|
+
*
|
|
115
|
+
* ⛔ THE OBJECT IS FOUND BY ITS TYPE, not by position: the transaction also creates the leftover
|
|
116
|
+
* resource on a cut, and on a purchase the storage object is created and consumed inside it.
|
|
117
|
+
*/
|
|
118
|
+
export async function createdBlob(client, objectChanges) {
|
|
119
|
+
const created = Array.isArray(objectChanges)
|
|
120
|
+
? objectChanges.find((change) => typeof change === "object" &&
|
|
121
|
+
change !== null &&
|
|
122
|
+
Reflect.get(change, "type") === "created" &&
|
|
123
|
+
typeof Reflect.get(change, "objectType") === "string" &&
|
|
124
|
+
String(Reflect.get(change, "objectType")).endsWith("::blob::Blob"))
|
|
125
|
+
: undefined;
|
|
126
|
+
const id = created === undefined ? undefined : Reflect.get(created, "objectId");
|
|
127
|
+
if (typeof id !== "string") {
|
|
128
|
+
throw new NmtsError("The registration executed but the chain did not list the blob object it created.", {
|
|
129
|
+
exitCode: 1,
|
|
130
|
+
nextStep: "The storage is bought. Running the same command again does not pay again: it reads the record and continues.",
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const lease = await readBlobLease(client, id);
|
|
134
|
+
return { blobObjectId: id, endEpoch: lease.endEpoch };
|
|
135
|
+
}
|
|
136
|
+
/** What this part is once the network has encoded it — the number registration compares a resource against. */
|
|
137
|
+
export async function encodedLength(client, sender, sealedLen) {
|
|
138
|
+
const [system, state] = await Promise.all([client.walrus.systemObject(), client.walrus.systemState()]);
|
|
139
|
+
const tx = new Transaction();
|
|
140
|
+
tx.moveCall({
|
|
141
|
+
package: system.package_id,
|
|
142
|
+
module: "encoding",
|
|
143
|
+
function: "encoded_blob_length",
|
|
144
|
+
// 1 = RS2, the encoding every registration in this tool names (`reuse.ts`).
|
|
145
|
+
arguments: [tx.pure.u64(sealedLen), tx.pure.u8(1), tx.pure.u16(state.committee.n_shards)],
|
|
146
|
+
});
|
|
147
|
+
const result = await client.devInspectTransactionBlock({ sender, transactionBlock: tx });
|
|
148
|
+
const value = result.results?.[0]?.returnValues?.[0]?.[0];
|
|
149
|
+
if (value === undefined) {
|
|
150
|
+
throw new NmtsError("The chain did not say how large this part is once encoded.", {
|
|
151
|
+
exitCode: 1,
|
|
152
|
+
nextStep: "Nothing was signed. A held resource cannot be cut to fit without that number; buy new storage instead, or try again.",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return Number(bcs.u64().parse(Uint8Array.from(value)));
|
|
156
|
+
}
|
|
157
|
+
/** A part shaped like a real one, for measuring the fee of a registration before anything is sealed. */
|
|
158
|
+
function placeholderPart(sealedLen) {
|
|
159
|
+
return {
|
|
160
|
+
sealedLen,
|
|
161
|
+
blobId: blobIdFromInt(1n),
|
|
162
|
+
rootHash: new Uint8Array(32),
|
|
163
|
+
nonce: new Uint8Array(32),
|
|
164
|
+
blobDigest: new Uint8Array(32),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/** The live reads one wallet-paid upload needs, bound to one network and one relay. */
|
|
168
|
+
export function walletUploadReads(network, relayUrl) {
|
|
169
|
+
const client = build(network, relayUrl);
|
|
170
|
+
return {
|
|
171
|
+
readWindow: () => extendReads(network).readWindow(),
|
|
172
|
+
async quoteParts(sealedLens, epochs) {
|
|
173
|
+
return Promise.all(sealedLens.map(async (sealedLen) => {
|
|
174
|
+
const [cost, tip] = await Promise.all([
|
|
175
|
+
client.walrus.storageCost(sealedLen, epochs),
|
|
176
|
+
client.walrus.calculateUploadRelayTip({ size: sealedLen }),
|
|
177
|
+
]);
|
|
178
|
+
return { sealedLen, storageFrost: cost.storageCost, writeFrost: cost.writeCost, tipMist: BigInt(tip) };
|
|
179
|
+
}));
|
|
180
|
+
},
|
|
181
|
+
readWallet: (address) => readBalances(chainReader(network, address), walCoinType(network)),
|
|
182
|
+
async estimateRegisterGas({ sender, sealedLen, epochs, storage }) {
|
|
183
|
+
// ⛔ THE SAME BUILDER THE SIGNATURE USES, with a placeholder blob: the gas of `register_blob`
|
|
184
|
+
// does not depend on which id is registered, and the real id exists only after sealing.
|
|
185
|
+
try {
|
|
186
|
+
const tx = await registerTransaction(client, network, { sender, epochs, storage, part: placeholderPart(sealedLen) });
|
|
187
|
+
const bytes = await tx.build({ client });
|
|
188
|
+
const { effects } = await client.dryRunTransactionBlock({ transactionBlock: bytes });
|
|
189
|
+
if (effects.status.status !== "success")
|
|
190
|
+
return null;
|
|
191
|
+
return netGasFee(effects.gasUsed);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
async readStorage(address) {
|
|
198
|
+
const type = await readStorageType(client, packageConfig(network).systemObjectId);
|
|
199
|
+
return readOwnedStorage(client, address, type);
|
|
200
|
+
},
|
|
201
|
+
encodedLength: (sender, sealedLen) => encodedLength(client, sender, sealedLen),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { ExtendWindow } from "./extend-plan.ts";
|
|
2
|
+
import type { StorageResource } from "./shared/lib/storage-control/chain.ts";
|
|
3
|
+
import { type WalletBalances } from "./wallet.ts";
|
|
4
|
+
/** The browser's default rung, and the term one credit buys. A number of EPOCHS, not days. */
|
|
5
|
+
export declare const DEFAULT_UPLOAD_EPOCHS = 2;
|
|
6
|
+
/** What ONE part costs, as the chain quotes it. Base units throughout. */
|
|
7
|
+
export interface PartQuote {
|
|
8
|
+
sealedLen: number;
|
|
9
|
+
/** Storage over time, in FROST. Zero when a held resource supplies the storage. */
|
|
10
|
+
storageFrost: bigint;
|
|
11
|
+
/** The write, in FROST. Charged whoever supplies the storage. */
|
|
12
|
+
writeFrost: bigint;
|
|
13
|
+
/** The relay's tip, in MIST. */
|
|
14
|
+
tipMist: bigint;
|
|
15
|
+
}
|
|
16
|
+
/** Where a part's storage comes from. */
|
|
17
|
+
export type StorageChoice = {
|
|
18
|
+
kind: "buy";
|
|
19
|
+
} | {
|
|
20
|
+
kind: "reuse";
|
|
21
|
+
objectId: string;
|
|
22
|
+
/** Cut the resource down to this many bytes first (`fit`), or null to bind it whole. */
|
|
23
|
+
cutToBytes: number | null;
|
|
24
|
+
/** The write cost, which a held resource does not cover. */
|
|
25
|
+
writeFrost: bigint;
|
|
26
|
+
/** What the resource holds beyond this part, once encoded — bound with the file, or left over. */
|
|
27
|
+
leftoverBytes: number;
|
|
28
|
+
resource: StorageResource;
|
|
29
|
+
};
|
|
30
|
+
/** One part as the register transaction needs it. */
|
|
31
|
+
export interface RegisterShape {
|
|
32
|
+
epochs: number;
|
|
33
|
+
storage: {
|
|
34
|
+
kind: "buy";
|
|
35
|
+
} | {
|
|
36
|
+
kind: "reuse";
|
|
37
|
+
objectId: string;
|
|
38
|
+
cutToBytes: number | null;
|
|
39
|
+
writeFrost: bigint;
|
|
40
|
+
};
|
|
41
|
+
part: {
|
|
42
|
+
sealedLen: number;
|
|
43
|
+
blobId: string;
|
|
44
|
+
rootHash: Uint8Array;
|
|
45
|
+
nonce: Uint8Array;
|
|
46
|
+
blobDigest: Uint8Array;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** The chain, as a wallet-paid upload READS it. ⚠ A seam — no flag reaches it. */
|
|
50
|
+
export interface WalletUploadReads {
|
|
51
|
+
readWindow(): Promise<ExtendWindow | null>;
|
|
52
|
+
quoteParts(sealedLens: readonly number[], epochs: number): Promise<PartQuote[]>;
|
|
53
|
+
readWallet(address: string): Promise<WalletBalances>;
|
|
54
|
+
/** The fee of ONE register signature, measured by a dry run — or null when it could not be. */
|
|
55
|
+
estimateRegisterGas(input: {
|
|
56
|
+
sender: string;
|
|
57
|
+
sealedLen: number;
|
|
58
|
+
epochs: number;
|
|
59
|
+
storage: RegisterShape["storage"];
|
|
60
|
+
}): Promise<bigint | null>;
|
|
61
|
+
/** The free storage resources the wallet holds. Rejects when they could not be read. */
|
|
62
|
+
readStorage(address: string): Promise<StorageResource[]>;
|
|
63
|
+
/** What a part of this many sealed bytes occupies once encoded — the chain's own number. */
|
|
64
|
+
encodedLength(sender: string, sealedLen: number): Promise<number>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* How many epochs to buy: what was asked for, or the browser's default, held against the ceiling.
|
|
68
|
+
*
|
|
69
|
+
* ⛔ IT REFUSES RATHER THAN CLAMPS, for the reason `extend-plan.ts` gives: quietly buying fewer
|
|
70
|
+
* epochs spends money on something nobody asked for.
|
|
71
|
+
*/
|
|
72
|
+
export declare function chooseUploadEpochs(asked: string | number | undefined, window: ExtendWindow): number;
|
|
73
|
+
/** A number of epochs as days, read from the network's own clock. */
|
|
74
|
+
export declare function daysOf(window: ExtendWindow, epochs: number): string;
|
|
75
|
+
/** What `--storage` asks for. */
|
|
76
|
+
export type StorageAsk = {
|
|
77
|
+
mode: "fit";
|
|
78
|
+
} | {
|
|
79
|
+
mode: "whole";
|
|
80
|
+
} | {
|
|
81
|
+
mode: "object";
|
|
82
|
+
objectId: string;
|
|
83
|
+
};
|
|
84
|
+
export declare function parseStorageAsk(text: string | undefined): StorageAsk | null;
|
|
85
|
+
/**
|
|
86
|
+
* Which held resource supplies this part's storage, and how much of it.
|
|
87
|
+
*
|
|
88
|
+
* ⛔ THE LEFTOVER IS A NUMBER THE PERSON SEES — the owner's rule: registration binds the WHOLE resource,
|
|
89
|
+
* so `whole` says how many bytes go in with the file, and `fit` cuts first and says what stays
|
|
90
|
+
* free. `fit` and `whole` pick the smallest usable resource that fits; an object id names one.
|
|
91
|
+
*/
|
|
92
|
+
export declare function pickResource(ask: StorageAsk, resources: readonly StorageResource[], encodedBytes: number, currentEpoch: number, needUntilEpoch: number, writeFrost: bigint): StorageChoice;
|
|
93
|
+
/** The wallet against the price — before the agreement, before any signature. */
|
|
94
|
+
export interface UploadBudget {
|
|
95
|
+
readonly address: string;
|
|
96
|
+
readonly walNeededFrost: bigint;
|
|
97
|
+
/** Tips plus the measured register fee per part. The certify fees are on top and unmeasured. */
|
|
98
|
+
readonly suiNeededMist: bigint;
|
|
99
|
+
readonly walFrost: bigint | null;
|
|
100
|
+
readonly suiMist: bigint | null;
|
|
101
|
+
readonly feeMist: bigint | null;
|
|
102
|
+
readonly unread: readonly string[];
|
|
103
|
+
readonly shortfall: string | null;
|
|
104
|
+
}
|
|
105
|
+
export declare function uploadBudget(input: {
|
|
106
|
+
address: string;
|
|
107
|
+
purse: WalletBalances;
|
|
108
|
+
feeMist: bigint | null;
|
|
109
|
+
quotes: readonly PartQuote[];
|
|
110
|
+
storage: StorageChoice;
|
|
111
|
+
}): UploadBudget;
|
|
112
|
+
/** WAL for the whole file: storage and write when buying, the write alone on a held resource. */
|
|
113
|
+
export declare function walPrice(quotes: readonly PartQuote[], storage: StorageChoice): bigint;
|
|
114
|
+
/** The next step when the wallet is short: where to send what, said once. */
|
|
115
|
+
export declare function uploadShortfallNextStep(b: UploadBudget): string;
|
|
116
|
+
/** The numbers, for a person, in the order somebody deciding needs them. */
|
|
117
|
+
export declare function describeUploadReview(say: (line: string) => void, facts: {
|
|
118
|
+
name: string;
|
|
119
|
+
bytes: number;
|
|
120
|
+
parts: number;
|
|
121
|
+
epochs: number;
|
|
122
|
+
days: string;
|
|
123
|
+
endEpoch: number;
|
|
124
|
+
walNeeded: bigint;
|
|
125
|
+
tipMist: bigint;
|
|
126
|
+
storage: StorageChoice;
|
|
127
|
+
heldResources: number | null;
|
|
128
|
+
}, budget: UploadBudget): void;
|