Waldrop SDK · Recipe

Bundle multiple files into one blob

Pack N files into a tar, upload as a single Walrus blob — one publisher PUT, one on-chain register tx, no matter how many files. Filenames are preserved inside the tar so unpackTar recovers the originals on read.

Bundle vs. per-file uploads

Bundle is the right call when files travel together — archives, datasets, static-site builds, lecture series. If files need independent sharing, expiry, or replacement, upload each one separately so they get distinct blob_ids and BlobRef rows.

Upload

import { WaldropClient } from "@waldrop/sdk";

const client = new WaldropClient({ network: "testnet", suiClient });
const enc = (s: string) => new TextEncoder().encode(s);

const result = await client.blob.uploadBundle({
  files: [
    { name: "users.csv",   data: enc("id,name\n1,alice\n2,bob\n") },
    { name: "config.json", data: enc('{"env":"prod"}') },
    { name: "README.md",   data: enc("# Demo bundle\n") },
  ],
  epochs: 26,
  senderAddress,
  subscriptionId,
  signer,
  blobStoreId,                                // optional; creates one if omitted
  // fileName: "my-bundle.tar",                // optional; default = waldrop-bundle-<timestamp>.tar
  onProgress: (e) => console.log(`[${e.stage}] ${e.percent}%`),
});

console.log(result.blobId);                   // single Walrus id for the whole bundle
console.log(result.sizeBytes);                // tar overhead included (~10 KiB minimum)

Download + unpack

import { unpackTar } from "@waldrop/sdk";

const { bytes } = await client.blob.fetch({ blobId: result.blobId });

const entries = unpackTar(bytes);
for (const e of entries) {
  console.log(e.name, e.size, e.contentType);
  // → users.csv     22  text/csv
  // → config.json   14  application/json
  // → README.md     14  text/markdown
}

// e.bytes is a Uint8Array of the original file content.

unpackTar filters out malformed/empty entries silently — compare entries.length against the upload's files.length if you want to detect partial parses.

What you get for free

01
Filename preservation
Each file keeps its name in the tar header — recovered on unpack.
02
MIME inference
unpackTar guesses content-type from extension (csv, json, md, png, …).
03
One tx, one gas spend
Bundling 50 files costs the same gas as uploading 1.
04
Encryption works the same
Pass encrypted: true — the whole tar gets SEAL-encrypted as one blob.

Tar format details

  • No compression — Walrus storage is efficient, gzip-in-the-browser adds a slow read-path step. Switch to application/x-tar+gzip later if needed.
  • Library: nanotar — same as the Waldrop dapp's bundle strategy. Filenames + mtime preserved; default mode is 0o644.

Power-user

packFilesAsTar is exported standalone if you want to upload the bundle through your own pipeline:

import { packFilesAsTar } from "@waldrop/sdk";

const { bytes, name, size, contentType } = packFilesAsTar(files);
// → upload `bytes` via any HTTP client that talks to a Walrus publisher
Edit this page on GitHub ↗
Waldrop · 2026cryptokarigar