github.com/storacha/go-ucanto@v0.7.2/README.md (about) 1 # go-ucanto 2 3 [](https://goreportcard.com/report/github.com/storacha/go-ucanto) 4 5 Ucanto UCAN RPC in Golang. 6 7 ## Install 8 9 ```console 10 go get github.com/storacha/go-ucanto 11 ``` 12 13 ## Usage 14 15 ### Client 16 17 ```go 18 package main 19 20 import ( 21 "..." 22 ) 23 24 // service URL & DID 25 serviceURL, _ := url.Parse("https://up.web3.storage") 26 servicePrincipal, _ := did.Parse("did:web:web3.storage") 27 28 // HTTP transport and CAR encoding 29 channel := http.NewHTTPChannel(serviceURL) 30 conn, _ := client.NewConnection(servicePrincipal, channel) 31 32 // private key to sign UCANs with 33 priv, _ := ioutil.ReadFile("path/to/private.key") 34 signer, _ := ed25519.Parse(priv) 35 36 audience := servicePrincipal 37 38 type StoreAddCaveats struct { 39 Link ipld.Link 40 Size int 41 } 42 43 func (c StoreAddCaveats) ToIPLD() (datamodel.Node, error) { 44 return ipld.WrapWithRecovery(&c, StoreAddType()) 45 } 46 47 func StoreAddType() ipldschema.Type { 48 ts, _ := ipldprime.LoadSchemaBytes([]byte(` 49 type StoreAdd struct { 50 link Link 51 size Int 52 } 53 `)) 54 return ts.TypeByName("StoreAdd") 55 } 56 57 capability := ucan.NewCapability( 58 "store/add", 59 did.Parse("did:key:z6MkwDuRThQcyWjqNsK54yKAmzfsiH6BTkASyiucThMtHt1T").String(), 60 StoreAddCaveats{ 61 // TODO 62 }, 63 ) 64 65 // create invocation(s) to perform a task with granted capabilities 66 inv, _ := invocation.Invoke(signer, audience, capability, delegation.WithProofs(...)) 67 invocations := []invocation.Invocation{inv} 68 69 // send the invocation(s) to the service 70 resp, _ := client.Execute(context.Background(), invocations, conn) 71 72 // define datamodels for ok and error outcome 73 type OkModel struct { 74 Status string 75 } 76 type ErrModel struct { 77 Message string 78 } 79 80 // create new receipt reader, passing the IPLD schema for the result and the 81 // ok and error types 82 reader, _ := receipt.NewReceiptReader[OkModel, ErrModel]([]byte(` 83 type Result union { 84 | Ok "ok" 85 | Err "error" 86 } representation keyed 87 88 type Ok struct { 89 status String 90 } 91 92 type Err struct { 93 message String 94 } 95 `)) 96 97 // get the receipt link for the invocation from the response 98 rcptlnk, _ := resp.Get(invocations[0].Link()) 99 // read the receipt for the invocation from the response 100 rcpt, _ := reader.Read(rcptlnk, res.Blocks()) 101 102 fmt.Println(rcpt.Out().Ok()) 103 ``` 104 105 ### Server 106 107 ```go 108 package main 109 110 import ( 111 "..." 112 ) 113 114 type TestEcho struct { 115 Echo string 116 } 117 118 func (c TestEcho) ToIPLD() (ipld.Node, error) { 119 return ipld.WrapWithRecovery(&c, EchoType()) 120 } 121 122 func EchoType() ipldschema.Type { 123 ts, _ := ipldprime.LoadSchemaBytes([]byte(` 124 type TestEcho struct { 125 echo String 126 } 127 `)) 128 return ts.TypeByName("TestEcho") 129 } 130 131 func createServer(signer principal.Signer) (server.ServerView, error) { 132 // Capability definition(s) 133 testecho := validator.NewCapability( 134 "test/echo", 135 schema.DIDString(), 136 schema.Struct[TestEcho](EchoType(), nil), 137 validator.DefaultDerives, 138 ) 139 140 return server.NewServer( 141 signer, 142 // Handler definitions 143 server.WithServiceMethod( 144 testecho.Can(), 145 server.Provide( 146 testecho, 147 func(ctx context.Context, cap ucan.Capability[TestEcho], inv invocation.Invocation, ictx server.InvocationContext) (TestEcho, receipt.Effects, error) { 148 return TestEcho{Echo: cap.Nb().Echo}, nil, nil 149 }, 150 ), 151 ), 152 ) 153 } 154 155 func main() { 156 signer, _ := ed25519.Generate() 157 server, _ := createServer(signer) 158 159 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 160 res, _ := server.Request(r.Context(), uhttp.NewHTTPRequest(r.Body, r.Header)) 161 162 for key, vals := range res.Headers() { 163 for _, v := range vals { 164 w.Header().Add(key, v) 165 } 166 } 167 168 if res.Status() != 0 { 169 w.WriteHeader(res.Status()) 170 } 171 172 io.Copy(w, res.Body()) 173 }) 174 175 listener, _ := net.Listen("tcp", ":0") 176 177 port := listener.Addr().(*net.TCPAddr).Port 178 fmt.Printf("{\"id\":\"%s\",\"url\":\"http://127.0.0.1:%d\"}\n", signer.DID().String(), port) 179 180 http.Serve(listener, nil) 181 } 182 ``` 183 184 ## API 185 186 [pkg.go.dev Reference](https://pkg.go.dev/github.com/storacha/go-ucanto) 187 188 ## Related 189 190 * [Ucanto in Javascript](https://github.com/storacha/ucanto) 191 192 ## Contributing 193 194 Feel free to join in. All welcome. Please [open an issue](https://github.com/storacha/go-ucanto/issues)! 195 196 ## License 197 198 Dual-licensed under [MIT + Apache 2.0](LICENSE.md)