client.cost.estimate re-fetches Walrus pricing every call by default. If
you're computing N estimates back-to-back (e.g. a per-file table), fetch
once and pass it through:
const pricing = await client.cost.getPricing();const estimates = files.map((f) => client.cost.estimate({ bytesPerBlob: f.size, epochs: 26, pricing, // ← skips the live fetch }),);const all = await Promise.all(estimates);
Multiple blobs at once
const r = await client.cost.estimate({ bytesPerBlob: 1 * 1024 * 1024, numBlobs: 100, // 100 separate 1 MiB blobs epochs: 26,});console.log(r.totalUnits); // 500 (5× redundancy × 100 blobs)console.log(r.totalWal); // cost for the whole batch
For a tar bundle, the bundle is a single blob — pass bytesPerBlob: tar.size
and numBlobs: 1, not the file count.
Walrus encodes data with RaptorQ + erasure coding across storage shards.
Your 1 MiB pays for ~5 MiB of encoded storage. The factor depends on
n_shards, but 5× is a safe upper bound used by the dapp + SDK. The
publisher does the authoritative calculation at PUT time, so this estimate
is approximate-but-bounded.
Days unavailable on testnet
epochDays returns 0 on testnet because epoch_duration_ms lives on the
Walrus StakingInner object, not the System object. Default to "1 day"
for testnet display; query the staking object directly if you need
mainnet's 14-day epochs.