A Go client library for connecting to Swarm Bee nodes.
bee-go provides a type-safe interface for interacting with the Bee API. It targets functional parity with bee-js while keeping a Go shape: sub-packages per domain, context.Context first arg, errors as values, typed-bytes wrappers for length-validated identifiers.
go get github.com/ethswarm-tools/bee-gopackage main
import (
"context"
"fmt"
"log"
"strings"
bee "github.com/ethswarm-tools/bee-go"
"github.com/ethswarm-tools/bee-go/pkg/swarm"
)
func main() {
c, err := bee.NewClient("http://localhost:1633")
if err != nil {
log.Fatal(err)
}
ok, err := c.Debug.Health(context.Background())
if err != nil || !ok {
log.Fatal(err)
}
// Buy storage for 1 GB / 30 days using current chain pricing.
size, _ := swarm.SizeFromGigabytes(1)
batchID, err := c.BuyStorage(context.Background(), size, swarm.DurationFromDays(30), nil)
if err != nil {
log.Fatal(err)
}
res, err := c.File.UploadData(context.Background(), batchID, strings.NewReader("Hello Swarm!"), nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Uploaded reference: %s\n", res.Reference.Hex())
}bee-go is a sub-service client: the top-level Client exposes one
sub-service per Bee API domain. This is a deliberate Go idiom — it keeps
each domain's surface focused, allows compiler-checked imports of just
what callers need, and avoids a single 100-method God object. (bee-js
uses one flat Bee class because TypeScript has no equivalent of the
import-pruning Go gives us for free.)
| Package | Purpose |
|---|---|
pkg/swarm |
Typed bytes (Reference, BatchID, EthAddress, PublicKey, Signature, …), token math (BZZ, DAI), Duration, Size, BMT chunk ops, SOC creation, GSOC mining, typed errors (BeeError, BeeArgumentError, BeeResponseError), CheckResponse. |
pkg/api |
Core HTTP client + shared options/headers. UploadOptions, RedundantUploadOptions, FileUploadOptions, CollectionUploadOptions, DownloadOptions, PostageBatchOptions. Pin/Tag/Stewardship/Grantee/Envelope endpoints. |
pkg/file |
Data, file, chunk, SOC, feed and collection uploads/downloads. FeedReader/FeedWriter, MakeFeedIdentifier, FeedUpdateChunkReference, IsFeedRetrievable, AreAllSequentialFeedsUpdateRetrievable, in-memory UploadCollectionEntries. |
pkg/postage |
Postage batch CRUD + stamp math (GetStampCost, GetStampDuration, GetAmountForDuration, GetDepthForSize, GetStampEffectiveBytes). Stamper for offline stamp generation. |
pkg/debug |
Node info, peers, topology, balances, settlements, chequebook, stake, transactions, redistribution. |
pkg/pss |
PSS send/subscribe/receive over WebSockets. |
pkg/gsoc |
Generic Single-Owner Chunk send/subscribe (built on pkg/file SOC upload). |
pkg/manifest |
Mantaray trie + v0.2 wire format (single-chunk). |
Full API reference: pkg.go.dev/github.com/ethswarm-tools/bee-go.
Top-level Client (in client.go) wires every sub-service to the same
HTTP client and base URL. High-level helpers that span multiple
sub-services (e.g. BuyStorage, ExtendStorage, GetStorageCost)
live on Client itself in storage.go.
| bee-js method | bee-go call |
|---|---|
bee.uploadData(stamp, data, opts) |
client.File.UploadData(ctx, batchID, data, opts) |
bee.uploadFile(stamp, data, name, opts) |
client.File.UploadFile(ctx, batchID, data, name, contentType, opts) |
bee.uploadFiles(stamp, files, opts) |
client.File.UploadCollectionEntries(ctx, batchID, entries, opts) |
bee.uploadFilesFromDirectory(stamp, dir, opts) |
client.File.UploadCollection(ctx, batchID, dir, opts) |
bee.streamFiles(stamp, files, ...) |
client.File.StreamCollectionEntries(ctx, batchID, entries, opts) (chunks files locally, uploads chunk-by-chunk, saves manifest recursively) |
bee.streamDirectory(stamp, dir, ...) |
client.File.StreamDirectory(ctx, batchID, dir, opts) |
bee.hashDirectory(dir) |
file.HashDirectory(dir) (offline — no upload, returns the manifest reference) — entries variant file.HashCollectionEntries(entries) |
bee.uploadChunk(stamp, data, opts) |
client.File.UploadChunk(ctx, batchID, data, opts) |
bee.downloadData(ref, opts) |
client.File.DownloadData(ctx, ref, opts) |
bee.probeData(ref) |
client.File.ProbeData(ctx, ref) (HEAD /bytes — Content-Length only) |
bee.downloadFile(ref, path, opts) |
client.File.DownloadFile(ctx, ref, opts) |
bee.downloadChunk(ref, opts) |
client.File.DownloadChunk(ctx, ref, opts) |
bee.uploadSOC(stamp, owner, id, sig, data, opts) |
client.File.UploadSOC(ctx, batchID, owner, id, sig, data, opts) |
bee.makeContentAddressedChunk(payload) |
swarm.MakeContentAddressedChunk(payload) (offline CAC) |
bee.makeSingleOwnerChunk(addr, span, payload, id, signer) |
swarm.MakeSingleOwnerChunk(id, payload, signer) (offline SOC) |
bee.calculateSingleOwnerChunkAddress(id, owner) |
swarm.CalculateSingleOwnerChunkAddress(id, owner) |
bee.makeSOCReader(owner) / makeSOCWriter(signer) |
client.File.MakeSOCReader(owner) / client.File.MakeSOCWriter(signer) |
bee.createFeedManifest(stamp, topic, owner) |
client.File.CreateFeedManifest(ctx, batchID, owner, topic) |
bee.makeFeedReader(topic, owner) |
client.File.MakeFeedReader(owner, topic) |
bee.makeFeedWriter(topic, signer) |
client.File.MakeFeedWriter(signer, topic) |
bee.fetchLatestFeedUpdate(owner, topic) |
client.File.FetchLatestFeedUpdate(ctx, owner, topic) |
bee.isReferenceRetrievable(ref) |
client.API.IsRetrievable(ctx, ref) |
bee.isFeedRetrievable(owner, topic, idx) |
client.File.IsFeedRetrievable(ctx, owner, topic, &idx, opts) |
bee.createPostageBatch(amount, depth, opts) |
client.Postage.CreatePostageBatch(ctx, amount, depth, label) |
bee.topUpBatch(id, amount) |
client.Postage.TopUpBatch(ctx, batchID, amount) |
bee.diluteBatch(id, depth) |
client.Postage.DiluteBatch(ctx, batchID, depth) |
bee.getPostageBatch(id) / getAllPostageBatch() |
client.Postage.GetPostageBatch(ctx, batchID) / GetPostageBatches(ctx) |
bee.getPostageBatchBuckets(id) |
client.Postage.GetPostageBatchBuckets(ctx, batchID) |
bee.getGlobalPostageBatches() (and the deprecated getAllGlobalPostageBatch()) |
client.Postage.GetGlobalPostageBatches(ctx) (alias GetAllGlobalPostageBatch) |
bee.buyStorage(size, duration, opts) |
client.BuyStorage(ctx, size, duration, opts) |
bee.getStorageCost(size, duration) |
client.GetStorageCost(ctx, size, duration, opts) |
bee.extendStorage(id, size, duration) |
client.ExtendStorage(ctx, batchID, size, duration, opts) |
bee.extendStorageSize(id, size) |
client.ExtendStorageSize(ctx, batchID, size, opts) |
bee.extendStorageDuration(id, duration) |
client.ExtendStorageDuration(ctx, batchID, duration, opts) |
bee.getExtensionCost(id, size, duration) |
client.GetExtensionCost(ctx, batchID, size, duration, opts) |
bee.getSizeExtensionCost(id, size) |
client.GetSizeExtensionCost(ctx, batchID, size, opts) |
bee.getDurationExtensionCost(id, duration) |
client.GetDurationExtensionCost(ctx, batchID, duration, opts) |
bee.calculateTopUpForBzz(depth, bzz) |
client.CalculateTopUpForBzz(ctx, depth, bzz, opts) |
bee.pin(ref) / unpin(ref) |
client.API.Pin(ctx, ref) / Unpin(ctx, ref) |
bee.getPin(ref) / getAllPins() |
client.API.GetPin(ctx, ref) / ListPins(ctx) |
bee.createTag() / getTag(uid) / retrieveTag(uid) |
client.API.CreateTag(ctx) / GetTag(ctx, uid) (alias RetrieveTag) |
bee.getAllTags(opts) / deleteTag(uid) / updateTag(uid, tag) |
client.API.ListTags(ctx, offset, limit) / DeleteTag(ctx, uid) / UpdateTag(ctx, uid, tag) |
bee.createEnvelope(stamp, ref) |
client.API.PostEnvelope(ctx, batchID, ref) |
bee.getGrantees(ref) / createGrantees(stamp, list) / patchGrantees(stamp, ref, hist, add, rev) |
client.API.GetGrantees(ctx, ref) / CreateGrantees(ctx, batchID, list) / PatchGrantees(ctx, batchID, ref, hist, add, rev) |
bee.reuploadPinnedData(stamp, ref) |
client.API.Reupload(ctx, ref, batchID) |
bee.pssSend(stamp, topic, target, data, recipient) |
client.PSS.PssSend(ctx, topic, target, data, recipient) |
bee.pssSubscribe(topic, handler) |
client.PSS.PssSubscribe(ctx, topic) (returns Subscription{Messages, Errors}) |
bee.pssReceive(topic, timeoutMs) |
client.PSS.PssReceive(ctx, topic, timeout) |
bee.gsocMine(overlay, id, prox) |
swarm.GSOCMine(target, identifier, proximity) |
bee.gsocSend(stamp, signer, id, data) |
client.GSOC.Send(ctx, batchID, signer, id, data, opts) |
bee.gsocSubscribe(addr, id, handler) |
client.GSOC.Subscribe(ctx, owner, id) |
bee.isConnected() / checkConnection() |
client.Debug.IsConnected(ctx) / CheckConnection(ctx) (pings the base URL) |
bee.getHealth() |
client.Debug.GetHealth(ctx) (structured) — Health(ctx) returns just a bool |
bee.getReadiness() |
client.Debug.Readiness(ctx) |
bee.getVersions() |
client.Debug.GetVersions(ctx) |
bee.isSupportedExactVersion() / isSupportedApiVersion() |
client.Debug.IsSupportedExactVersion(ctx) / IsSupportedApiVersion(ctx) |
bee.isGateway() |
client.Debug.IsGateway(ctx) |
bee.getNodeInfo() |
client.Debug.NodeInfo(ctx) |
bee.getStatus() |
client.Debug.Status(ctx) |
bee.getNodeAddresses() |
client.Debug.Addresses(ctx) |
bee.getTopology() |
client.Debug.Topology(ctx) |
bee.getPeers() |
client.Debug.Peers(ctx) |
bee.getChainState() |
client.Debug.ChainState(ctx) |
bee.getReserveState() |
client.Debug.ReserveState(ctx) |
bee.getRedistributionState() |
client.Debug.RedistributionState(ctx) |
bee.getStake() / stake(amount) / depositStake(amount) |
client.Debug.GetStake(ctx) / Stake(ctx, amount) / DepositStake(ctx, amount) |
bee.getWithdrawableStake() / withdrawSurplusStake() |
client.Debug.GetWithdrawableStake(ctx) / WithdrawSurplusStake(ctx) |
bee.migrateStake() |
client.Debug.MigrateStake(ctx) |
bee.getAllBalances() / getPeerBalance(peer) |
client.Debug.GetBalances(ctx) / GetPeerBalance(ctx, peer) |
bee.getPastDueConsumptionBalances() / getPastDueConsumptionPeerBalance(peer) |
client.Debug.GetPastDueConsumptionBalances(ctx) / GetPastDueConsumptionPeerBalance(ctx, peer) |
bee.getSettlements(peer) / getAllSettlements() |
client.Debug.PeerSettlement(ctx, peer) / Settlements(ctx) |
bee.getWalletBalance() |
client.Debug.GetWallet(ctx) (returns BZZ + native balances + chequebook + chainID) |
bee.withdrawBZZToExternalWallet(amount, addr) / withdrawDAIToExternalWallet(amount, addr) |
client.Debug.WithdrawBZZ(ctx, amount, addr) / WithdrawDAI(ctx, amount, addr) (also WithdrawBZZToExternalWallet / WithdrawDAIToExternalWallet aliases) |
bee.getChequebookAddress() / getChequebookBalance() |
(Chequebook field on client.Debug.GetWallet) / client.Debug.GetChequebookBalance(ctx) |
bee.depositBZZToChequebook(amount) / withdrawBZZFromChequebook(amount) |
client.Debug.DepositTokens(ctx, amount) / WithdrawTokens(ctx, amount) (also DepositBZZToChequebook / WithdrawBZZFromChequebook aliases) |
bee.getLastCheques() / getLastChequesForPeer(peer) |
client.Debug.LastCheques(ctx) / GetLastChequesForPeer(ctx, peer) |
bee.getLastCashoutAction(peer) / cashoutLastCheque(peer, gasPrice) |
client.Debug.GetLastCashoutAction(ctx, peer) / CashoutLastCheque(ctx, peer, gasPrice) |
bee.getAllPendingTransactions() / getPendingTransaction(hash) |
client.Debug.GetAllPendingTransactions(ctx) / GetPendingTransaction(ctx, hash) |
bee.rebroadcastPendingTransaction(hash) / cancelPendingTransaction(hash, gasPrice) |
client.Debug.RebroadcastPendingTransaction(ctx, hash) / CancelPendingTransaction(ctx, hash, gasPrice) |
bee.rchash(depth, anchor1, anchor2) |
client.Debug.RCHash(ctx, depth, anchor1, anchor2) |
bee.getWelcomeMessage() / setWelcomeMessage(msg) |
client.Debug.GetWelcomeMessage(ctx) / SetWelcomeMessage(ctx, msg) |
bee.getLoggers() / getLoggersByExpression(exp) / setLoggerVerbosity(exp) |
client.Debug.GetLoggers(ctx) / GetLoggersByExpression(ctx, exp) / SetLoggerVerbosity(ctx, exp) |
Construct a dev-mode client with bee.NewDevClient(url) — it returns
the same surface, but most chain/payment endpoints will return a
*BeeResponseError 404 against a bee dev node.
These hit Bee node endpoints that bee-js does not expose; useful for operators / diagnostic tooling.
| Endpoint | bee-go call |
|---|---|
GET /accounting |
client.Debug.GetAccounting(ctx) — full per-peer accounting (balances, thresholds, surpluses, ghost balance) |
GET /status/peers |
client.Debug.StatusPeers(ctx) — parallel status snapshot of every connected peer |
GET /status/neighborhoods |
client.Debug.StatusNeighborhoods(ctx) — reserve size + proximity per neighborhood |
POST /connect/{multi-address} |
client.Debug.ConnectPeer(ctx, multiaddr) — manual peer dial |
pkg/postage also exposes MarshalStamp(batchID, index, timestamp, signature)
and ConvertEnvelopeToMarshaledStamp(envelope) for callers that need
the on-wire stamp byte layout (e.g. when stamping outside the standard
upload path).
Every endpoint returns either nil or a *swarm.BeeError,
*swarm.BeeArgumentError, or *swarm.BeeResponseError. Inspect with
errors.As:
if rerr, ok := swarm.IsBeeResponseError(err); ok {
fmt.Printf("Bee returned %d %s for %s %s\n",
rerr.Status, rerr.StatusText, rerr.Method, rerr.URL)
fmt.Printf("Body: %s\n", rerr.ResponseBody)
}swarm.CheckResponse(resp) is a one-line helper used internally and
available to callers who construct their own requests.
examples/ contains short runnable programs:
examples/basic-usage— health check + node infoexamples/buy-batch— purchase a postage batchexamples/upload-picture— upload a fileexamples/download-picture— download a fileexamples/status— read chain/reserve/redistribution state
Contributions are welcome — please open an issue first for anything
substantial. Run go test ./... before submitting; the test suite is
self-contained (no live Bee node required).
MIT