Go Client

go-w3up

⚠️

The Go client is under heavily development and is not as fully featured as the JS client.

You can easily integrate Storacha into your Go apps using go-w3up, our Go client for the w3up platform.

In this guide, we'll walk through the following steps:

  1. Installing the client library
  2. Generating a DID
  3. Obtaining proofs
  4. Loading your private key and proofs
  5. Uploading a CAR file

Install

You'll need Go (opens in a new tab) version 1.21.4 or higher.

In addition to the w3up library you're also likely to need elements of go-ucanto - a library for performing UCAN RPC calls. Add the libraries to your project's dependencies:

go get github.com/storacha/go-w3up
go get github.com/storacha/go-ucanto

Generate a DID

Currently the best way to generate a DID is to use the w3up JS CLI:

Install w3 CLI

npm install -g @web3-storage/w3cli

Generate a DID

w3 key create

Output should look something like:

# did:key:z6Mkh9TtUbFJcUHhMmS9dEbqpBbHPbL9oxg1zziWn1CYCNZ2
MgCb+bRGl02JqlWMPUxCyntxlYj0T/zLtR2tn8LFvw6+Yke0BKAP/OUu2tXpd+tniEoOzB3pxqxHZpRhrZl1UYUeraT0=
💡

Save the private key (starting Mg...) to a file private.key.

Obtain proofs

Proofs are delegations to your DID enabling it to perform tasks. Currently the best way to obtain proofs that will allow you to interact with the Storacha API is to use the w3up JS CLI:

Install w3 CLI

npm install -g @web3-storage/w3cli

Generate a DID

Generate a DID and make a note of it (the string starting with did:key:...)

Create a space

w3 space create [NAME]

Delegate capabilities to your DID

w3 delegation create -c 'store/*' -c 'upload/*' [DID] -o proof.ucan
💡

Make a note of the space DID from above. You'll need it later.

Load private key and proofs

To interact with the Storacha API you need your private key to sign UCAN invocations and a proof that your key has been delegated capabilities to perform tasks:

package main
 
import (
  "ioutil"
 
  "github.com/web3-storage/go-ucanto/did"
  "github.com/web3-storage/go-ucanto/principal/ed25519/signer"
  "github.com/web3-storage/go-w3up/delegation"
)
 
// space that the client will interact with
space, _ := did.Parse("did:key:z6MkwDuRThQcyWjqNsK54yKAmzfsiH6BTkASyiucThMtHt1y")
 
// private key to sign UCAN invocations with
priv, _ := ioutil.ReadFile("path/to/private.key")
issuer, _ := signer.Parse(priv)
 
// UCAN proof(s) that the signer can perform tasks in this space (a delegation chain)
prfbytes, _ := ioutil.ReadFile("path/to/proof.ucan")
proof, _ := delegation.ExtractProof(b)

Upload a CAR

Once you have loaded your space DID, your private key and your delegation proofs, you can upload a CAR to Storacha.

package main
 
import (
	"bytes"
	"fmt"
	"net/http"
 
	"github.com/ipfs/go-cid"
	cidlink "github.com/ipld/go-ipld-prime/linking/cid"
	"github.com/multiformats/go-multihash"
	"github.com/web3-storage/go-w3up/capability/storeadd"
	"github.com/web3-storage/go-w3up/client"
)
 
func main() {
  data, _ := ioutil.ReadFile("path/to/my.car")
 
  // generate the CID for the CAR
  mh, _ := multihash.Sum(data, multihash.SHA2_256, -1)
  link := cidlink.Link{Cid: cid.NewCidV1(0x0202, mh)}
 
  rcpt, _ := client.StoreAdd(
    issuer,
    space,
    &storeadd.Caveat{Link: link, Size: len(data)},
    client.WithProofs(proofs),
  )
 
  // "upload" means it needs to be uploaded, "done" means it is already done!
  if rcpt.Out().Ok().Status == "upload" {
    hr, _ := http.NewRequest("PUT", *rcpt.Out().Ok().Url, bytes.NewReader(data))
 
    hdr := map[string][]string{}
    for k, v := range rcpt.Out().Ok().Headers.Values {
      hdr[k] = []string{v}
    }
 
    hr.Header = hdr
    hr.ContentLength = len(data)
    httpClient := http.Client{}
    res, _ := httpClient.Do(hr)
    res.Body.Close()
  }
 
  fmt.Println(link.String())
}
⚠️

Maximum upload size is 4,261,412,864 bytes (around 4GB). To upload CAR files larger than this, please use the sharding utility (opens in a new tab) to split the CAR into multiple shards.

A DAG can be sharded amongst multiple CAR files (see maximum upload size above). To tie together multiple stored CAR files to a content root CID you can register an "upload". An "upload" is a content root CID + a set of CAR shards that it is contained within.

You can register an upload with just one "shard". It is best practice to always register an upload even if there is only 1 shard.

Registering an upload is simple:

rcpt, _ := client.UploadAdd(
  issuer,
  space,
  &uploadadd.Caveat{Root: root, Shards: shards},
  client.WithProofs(proofs),
)