bee-rs 1.4.1

Rust client for the Swarm Bee API. Functional parity with bee-js / bee-go.
Documentation

bee-rs

Rust client for the Swarm Bee API. Async-first, MSRV 1.85, forbid(unsafe_code).

The functional target is parity with bee-js (canonical TypeScript client) and bee-go (typed Go port). bee-go is the primary reference for shape and behavior since the typed-language → typed-language mapping is direct; bee-js is the source of truth for wire-format edge cases.

Quick start

use bee::Client;

#[tokio::main]
async fn main() -> Result<(), bee::Error> {
    let client = Client::new("http://localhost:1633")?;

    let health = client.debug().health().await?;
    println!("bee {} api {}", health.version, health.api_version);

    Ok(())
}

Run the live-Bee smoke test:

BEE_URL=http://localhost:1633 cargo run --example integration-check

Set BEE_BATCH_ID=<hex> to reuse an existing postage batch (the first usability of a fresh batch on Sepolia takes minutes).

Layout

Module bee-go counterpart Scope
bee::swarm pkg/swarm Typed bytes, BMT, SOC, BZZ/DAI, Duration, Size, errs
bee::api pkg/api Upload/download options, pin, tag, grantee, envelope
bee::file pkg/file Data/file/chunk/SOC/feed/collection uploads
bee::postage pkg/postage Batch CRUD, pure stamp math
bee::debug pkg/debug Health, versions, accounting, chequebook, stake
bee::pss pkg/pss PSS send/subscribe/receive (websocket)
bee::gsoc pkg/gsoc GSOC send/subscribe + offline SOC address
bee::manifest pkg/manifest Mantaray trie, v0.2 wire format, ResourceLocator
bee::storage bee-js only High-level buy_storage / extend_storage_*
bee::dev bee-js only DevClient newtype around Client

Stack

  • reqwest (rustls-tls) for HTTP, tokio-tungstenite for websockets
  • k256 for secp256k1, sha3 for keccak256
  • thiserror for typed errors, serde for JSON
  • num-bigint for BZZ/DAI / chain-state amounts
  • tar for in-memory collection uploads

Migration cheat sheet

bee-js / bee-go callers should find the bee-rs surface familiar. Each row gives the bee-js method, the bee-go method, and the bee-rs equivalent. All bee-rs methods are async.

Connection + node info

bee-js bee-go bee-rs
new Bee(url) bee.NewClient(url) Client::new(url)?
Bee.getHealth() c.Debug.GetHealth(ctx) client.debug().health().await
Bee.getVersions() c.Debug.GetVersions(ctx) client.debug().versions().await
Bee.isConnected() c.Debug.IsConnected(ctx) client.debug().is_connected().await
Bee.getNodeAddresses() c.Debug.Addresses(ctx) client.debug().addresses().await
Bee.getTopology() c.Debug.Topology(ctx) client.debug().topology().await
Bee.getChainState() c.Debug.ChainState(ctx) client.debug().chain_state().await

Postage batches

bee-js bee-go bee-rs
Bee.createPostageBatch(…) c.Postage.CreatePostageBatch(ctx, …) client.postage().create_postage_batch(amount, depth, …)
Bee.getPostageBatches() c.Postage.GetPostageBatches(ctx) client.postage().get_postage_batches().await
Bee.topUpBatch(id, amount) c.Postage.TopUpBatch(ctx, id, amount) client.postage().top_up_batch(&id, &amount).await
Bee.diluteBatch(id, depth) c.Postage.DiluteBatch(ctx, id, depth) client.postage().dilute_batch(&id, depth).await

Bytes / file / collection

bee-js bee-go bee-rs
Bee.uploadData(batch, data) c.File.UploadData(ctx, batch, data, opts) client.file().upload_data(&batch, data, opts).await
Bee.downloadData(ref) c.File.DownloadData(ctx, ref, opts) client.file().download_data(&reference, opts).await
Bee.uploadFile(batch, data, …) c.File.UploadFile(ctx, batch, data, …) client.file().upload_file(&batch, data, name, content_type, opts).await
Bee.downloadFile(ref, path?) c.File.DownloadFile(ctx, ref, opts) client.file().download_file(&reference, opts).await
Bee.uploadCollection(entries) c.File.UploadCollectionEntries(ctx, …) client.file().upload_collection_entries(&batch, &entries, opts).await
Bee.uploadFilesFromDirectory(d) c.File.UploadCollection(ctx, batch, dir) client.file().upload_collection(&batch, dir, opts).await
bee.hashCollectionEntries(…) n/a bee::file::hash_collection_entries(&entries)?
bee.hashDirectory(dir) n/a bee::file::hash_directory(dir)?

Pin / tag / stewardship / grantee / envelope

bee-js bee-go bee-rs
Bee.pin(ref) / Bee.unpin(ref) c.API.Pin / Unpin client.api().pin(&reference).await
Bee.isPinned(ref) c.API.GetPin(ctx, ref) client.api().get_pin(&reference).await
Bee.createTag() c.API.CreateTag(ctx) client.api().create_tag().await
Bee.reupload(ref, batch) c.API.Reupload(ctx, ref, batch) client.api().reupload(&reference, &batch).await
Bee.isRetrievable(ref) c.API.IsRetrievable(ctx, ref) client.api().is_retrievable(&reference).await
Bee.createGrantees(batch, list) c.API.CreateGrantees(ctx, batch, list) client.api().create_grantees(&batch, &grantees).await
Bee.postEnvelope(ref, batch) c.API.PostEnvelope(ctx, ref, batch) client.api().post_envelope(&batch, &reference).await

Feeds + SOC + GSOC + PSS

bee-js bee-go bee-rs
Bee.updateFeed(signer, topic, data) c.File.UpdateFeed(ctx, batch, signer, topic, …) client.file().update_feed(&batch, &signer, &topic, data).await
Bee.fetchLatestFeedUpdate(...) c.File.FetchLatestFeedUpdate(ctx, owner, topic) client.file().fetch_latest_feed_update(&owner, &topic).await
Bee.makeFeedReader(topic, owner) n/a client.file().make_feed_reader(owner, topic)
Bee.makeFeedWriter(topic, signer) n/a client.file().make_feed_writer(signer, topic)?
Bee.uploadSoc(...) c.File.UploadSOC(ctx, batch, owner, id, sig, …) client.file().upload_soc(&batch, &owner, &id, &sig, data, …)
Bee.gsocSend(batch, signer, id, …) gsocSvc.Send(ctx, batch, signer, id, data, opts) client.gsoc().send(&batch, &signer, &id, data, opts).await
Bee.gsocSubscribe(owner, id) gsocSvc.Subscribe(ctx, owner, id) client.gsoc().subscribe(&owner, &id).await
Bee.pssSend(topic, target, data, …) pssSvc.PssSend(ctx, batch, topic, target, …) client.pss().send(&batch, &topic, target, data, recipient).await
Bee.pssSubscribe(topic) api.PSSSubscribe(ctx, base, dialer, topic) client.pss().subscribe(&topic).await
Bee.pssReceive(topic, timeout) n/a client.pss().receive(&topic, timeout).await

Offline primitives

bee-js bee-go bee-rs
new Stamper(signer, batchId, depth) postage.NewStamper(signer, batchID, depth) bee::postage::Stamper::from_blank(signer, batch_id, depth)?
Stamper.stamp(chunk) (*Stamper).Stamp(chunkAddr) stamper.stamp(&chunk_addr)?bee::postage::Envelope
convertEnvelopeToMarshaledStamp(env) postage.ConvertEnvelopeToMarshaledStamp(env) bee::postage::convert_envelope_to_marshaled_stamp(&env)? (113 bytes)
marshalStamp(sig, batch, ts, idx) postage.MarshalStamp(batch, idx, ts, sig) bee::postage::marshal_stamp(&batch, &idx, &ts, &sig)?
convertReferenceToCid(ref, type) swarm.ConvertReferenceToCID(ref, type) bee::swarm::convert_reference_to_cid(&reference, CidType::Feed)?
convertCidToReference(cid) swarm.ConvertCIDToReference(cid) bee::swarm::convert_cid_to_reference(&cid)?

Storage helpers (top-level, bee-js only)

bee-js bee-rs
Bee.getStorageCost(size, duration) bee::storage::get_storage_cost(&client, size, duration, network)
Bee.buyStorage(size, duration, …) bee::storage::buy_storage(&client, size, duration, &opts)
Bee.extendStorageDuration(id, dur) bee::storage::extend_storage_duration(&client, &id, duration, …)
Bee.extendStorageSize(id, size) bee::storage::extend_storage_size(&client, &id, size)
Bee.calculateTopUpForBzz(id, bzz) bee::storage::calculate_top_up_for_bzz(&client, &id, &target_bzz)

Utility types

Concept Type Notes
Reference (32 / 64) bee::swarm::Reference Hex parse via Reference::from_hex(s)
Batch ID bee::swarm::BatchId BatchId::from_hex(s)? / BatchId::new(&[u8; 32])?
Topic / Identifier Topic / Identifier Both have from_string(label) keccak256-derived constructors
BZZ / DAI bee::swarm::Bzz / Dai Fixed-point on BigInt, Display + FromStr
Duration bee::swarm::BeeDuration Duration::parse("1d 4h 5m 30s")?
Size bee::swarm::Size Decimal base (1 kB = 1000 B), Size::parse("28MB")?
Resource locator bee::manifest::ResourceLocator Reference or <label>.eth

Stability

The crate is currently 0.x — breaking changes are allowed in minor bumps. The 1.0 line will follow once the live Bee soak (P4) and the integration-check coverage match bee-go's. See CHANGELOG.md and RELEASE.md.