Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

go.sia.tech/siastorage

Package Overview
Dependencies
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

go.sia.tech/siastorage

Go Modules
Version
v0.1.0
Version published
Created
Source

Sia Storage SDK

The official Go SDK for storing and retrieving data on the Sia network.

For guides and additional resources, visit the developer portal. For detailed API documentation, see the Godocs.

Connecting to the Indexer

Before uploading or downloading data, your application must connect to an indexer. First, create a Builder with your application metadata, then walk the user through the approval flow:

builder := siastorage.NewBuilder("https://sia.storage", siastorage.AppMetadata{
	ID:          appID,                          // a persistent, randomly-generated 32-byte app ID
	Name:        "MyApp",                        // display name
	Description: "My first Sia application",     // short description
	LogoURL:     "https://my.app/logo.png",      // logo shown in the indexer UI
	ServiceURL:  "https://my.app",               // your application's homepage
})

// request a connection — the user must visit the returned URL to approve
responseURL, err := builder.RequestConnection(ctx)
if err != nil {
	log.Fatal("failed to request connection:", err)
}
fmt.Println("Approve the connection:", responseURL)

// block until the user approves or rejects
if err := builder.WaitForApproval(ctx); errors.Is(err, siastorage.ErrUserRejected) {
	log.Fatal("user denied the connection")
} else if err != nil {
	log.Fatal("failed to wait for approval:", err)
}

// derive an app key from a BIP-39 seed phrase and register it
mnemonic := siastorage.NewSeedPhrase() // generate once — store securely
client, err := builder.Register(ctx, mnemonic)
if err != nil {
	log.Fatal("failed to register:", err)
}
defer client.Close()

On subsequent launches, skip the approval flow and create the SDK directly with the previously derived app key:

builder := siastorage.NewBuilder("https://sia.storage", siastorage.AppMetadata{ID: appID})
client, err := builder.SDK(appKey)
if err != nil {
	log.Fatal("failed to create SDK:", err)
}
defer client.Close()

Uploading and Downloading Data

Once connected, you can upload and download files using the SDK:

// upload
obj := siastorage.NewEmptyObject()
f, _ := os.Open("path/to/src.dat")
defer f.Close()

if err := client.Upload(ctx, &obj, f); err != nil {
	log.Fatal("upload failed:", err)
}

// pin the object so the indexer tracks it
if err := client.PinObject(ctx, obj); err != nil {
	log.Fatal("pin failed:", err)
}

// download
out, _ := os.Create("path/to/dst.dat")
defer out.Close()

rc, err := client.Download(obj)
if err != nil {
	log.Fatal("download failed:", err)
}
defer rc.Close()

if _, err := io.Copy(out, rc); err != nil {
	log.Fatal("download failed:", err)
}

The Object returned by Upload contains the encryption key and slab metadata required to download the data later. After uploading, call PinObject to persist the object on the indexer. Applications should store the sealed object (via obj.Seal(appKey)) so it can be reopened later.

Packed Uploads

When uploading many small objects, UploadPacked combines them into shared slabs to reduce overhead:

packed, err := client.UploadPacked()
if err != nil {
	log.Fatal("failed to create packed upload:", err)
}
defer packed.Close()

for _, data := range smallObjects {
	if _, err := packed.Add(ctx, bytes.NewReader(data)); err != nil {
		log.Fatal("failed to add object:", err)
	}
}

objects, err := packed.Finalize(ctx)
if err != nil {
	log.Fatal("failed to finalize:", err)
}

// pin and download each object individually
for _, obj := range objects {
	client.PinObject(ctx, obj)
}

Optimizing Packed Uploads

Use Remaining() and Length() to monitor padding and decide when to finalize:

const paddingTarget = 0.05

for len(uploads) > 0 {
	packed, err := client.UploadPacked()
	if err != nil {
		log.Fatal(err)
	}

	for len(uploads) > 0 {
		if _, err := packed.Add(ctx, bytes.NewReader(uploads[0])); err != nil {
			log.Fatal(err)
		}
		uploads = uploads[1:]

		if packed.Length() == 0 {
			continue
		}
		if float64(packed.Remaining())/float64(packed.Length()) <= paddingTarget {
			break
		}
	}

	objects, err := packed.Finalize(ctx)
	if err != nil {
		log.Fatal(err)
	}

	for _, obj := range objects {
		client.PinObject(ctx, obj)
	}
	packed.Close()
}

Limitations

  • PackedUpload is not thread-safe; do not call Add concurrently
  • Empty objects are not supported and will return ErrEmptyObject
  • Once Finalize is called, subsequent Add calls return ErrUploadFinalized

Sharing Objects

Objects can be shared via time-limited URLs:

url, err := client.CreateSharedObjectURL(ctx, obj.ID(), time.Now().Add(24*time.Hour))
if err != nil {
	log.Fatal("failed to create shared URL:", err)
}

// anyone with the URL can download the object
var buf bytes.Buffer
rc, err := client.DownloadSharedObject(ctx, url)
if err != nil {
	log.Fatal("failed to download shared object:", err)
}
defer rc.Close()

if _, err := io.Copy(&buf, rc); err != nil {
	log.Fatal("failed to download shared object:", err)
}

FAQs

Package last updated on 27 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts