Waldrop SDK · Recipe

Upload a plaintext blob

Single Walrus blob from a Uint8Array — one publisher PUT, one on-chain register_blob transaction, no encryption. The most common path.

When to use this

Use plaintext upload for public assets — anything you'd serve from a CDN. If the bytes shouldn't be readable by anyone with the blob_id, jump to Upload encrypted instead.

Prerequisites

npm install @waldrop/sdk @mysten/sui

You'll need:

  • A funded testnet Sui address (faucet: curl -X POST https://faucet.testnet.sui.io/v2/gas -H "Content-Type: application/json" -d '{"FixedAmountRequest":{"recipient":"0x…"}}')
  • An active Subscription object id (subscribe via the Waldrop dapp once; the SDK will read its id)

Recipe

import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
import { SuiGrpcClient } from "@mysten/sui/grpc";
import type { Transaction } from "@mysten/sui/transactions";
import { WaldropClient, type TransactionSigner } from "@waldrop/sdk";

// 1. Build a signer adapter the SDK understands.
const keypair = Ed25519Keypair.fromSecretKey(process.env.WALDROP_PRIVATE_KEY!);
const suiClient = new SuiGrpcClient({
  network: "testnet",
  baseUrl: "https://fullnode.testnet.sui.io:443",
});

const signer: TransactionSigner = {
  async signAndExecuteTransaction({ transaction }) {
    const r = await (suiClient as any).signAndExecuteTransaction({
      transaction: transaction as Transaction,
      signer: keypair,
      include: { effects: true },
    });
    const digest = r?.digest ?? r?.effects?.transactionDigest ?? "";
    if (digest) await (suiClient as any).waitForTransaction?.({ digest });
    return { digest, effects: r?.effects };
  },
};

// 2. Construct the client (shares the suiClient).
const client = new WaldropClient({ network: "testnet", suiClient });

// 3. Upload.
const data = new TextEncoder().encode("hello waldrop");
const result = await client.blob.upload({
  data,
  fileName: "hello.txt",
  contentType: "text/plain",
  epochs: 2,                                 // ≈ 2 days on testnet
  senderAddress: keypair.toSuiAddress(),
  subscriptionId: process.env.WALDROP_SUBSCRIPTION_ID!,
  signer,
  onProgress: (e) => console.log(`[${e.stage}] ${e.percent}%`),
});

console.log(result.blobId);                  // → "Zb4z_LLozYWPNhTFHO15Zq…"
console.log(result.transactionDigest);

What happens

1. SHA-256
Hashes original bytes — recorded on the BlobRef.
2. Publisher PUT
HTTP upload to Walrus (https://publisher.walrus-testnet.walrus.space).
3. register_blob
PTB signed by your keypair. Creates a BlobStore if none exists.
4. waitForTransaction
Block until the fullnode has indexed it so the digest is queryable.

Output

{
  blobId: "Zb4z_LLozYWPNhTFHO15Zq15AT0FDuwAt4tITl-rh8w",
  sizeBytes: 13,
  storedEpoch: 1098,
  expiryEpoch: 1100,
  transactionDigest: "9pH3…",
  blobStoreId: "0x…",
  sealMarker: null,
}

Inspect the tx on testnet: https://testnet.suivision.xyz/txblock/<transactionDigest>

Edit this page on GitHub ↗
Waldrop · 2026cryptokarigar