Client Methods
This page documents the methods available on the Client type for making RPC calls, managing subscriptions, and handling batch operations.
Core RPC Methods
Call
Performs a JSON-RPC call with the given arguments and unmarshals the result into the provided interface.
Method Signature
func (c *Client) Call(result interface{}, method string, args ...interface{}) errorParameters
result- Pointer to variable where the result will be unmarshaledmethod- The JSON-RPC method name to callargs- Variable number of arguments to pass to the method
Returns
error- Error if the call fails or result unmarshaling fails
Usage Example
package main
import (
"fmt"
"log"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialHTTP("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Call starknet_specVersion method
var version string
err = c.Call(&version, "starknet_specVersion")
if err != nil {
log.Fatal("RPC call failed:", err)
}
fmt.Printf("Starknet Spec Version: %s\n", version)
}Notes
This is a synchronous call without context support. For context-aware calls with timeout and cancellation, use CallContext.
CallContext
Performs a JSON-RPC call with context support for cancellation and timeout.
Method Signature
func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) errorParameters
ctx- Context for request cancellation and timeoutresult- Pointer to variable where the result will be unmarshaledmethod- The JSON-RPC method name to callargs- Variable number of arguments to pass to the method
Returns
error- Error if the call fails, times out, or result unmarshaling fails
Usage Example
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialHTTP("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Create context with 30 second timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Call with context
var blockNumber uint64
err = c.CallContext(ctx, &blockNumber, "starknet_blockNumber")
if err != nil {
log.Fatal("RPC call failed:", err)
}
fmt.Printf("Current Block Number: %d\n", blockNumber)
}Context with Headers
package main
import (
"context"
"fmt"
"log"
"net/http"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialHTTP("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Add custom headers
headers := http.Header{}
headers.Set("X-API-Key", "your-api-key")
ctx := client.NewContextWithHeaders(context.Background(), headers)
// Call with headers
var chainID string
err = c.CallContext(ctx, &chainID, "starknet_chainId")
if err != nil {
log.Fatal("RPC call failed:", err)
}
fmt.Printf("Chain ID: %s\n", chainID)
}Batch Operations
BatchCall
Sends multiple RPC requests in a single batch and waits for the server response. This is more efficient than making individual calls when you need results from multiple methods.
Method Signature
func (c *Client) BatchCall(b []BatchElem) errorParameters
b- Slice of BatchElem containing the requests and results
Returns
error- Error if the batch call fails
BatchElem Structure
type BatchElem struct {
Method string // The JSON-RPC method name
Args []interface{} // Arguments for the method
Result interface{} // Pointer to store the result
Error error // Error for this specific call
}Usage Example
package main
import (
"fmt"
"log"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialHTTP("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Prepare batch requests
var (
specVersion string
chainID string
blockNumber uint64
)
batch := []client.BatchElem{
{
Method: "starknet_specVersion",
Args: []interface{}{},
Result: &specVersion,
},
{
Method: "starknet_chainId",
Args: []interface{}{},
Result: &chainID,
},
{
Method: "starknet_blockNumber",
Args: []interface{}{},
Result: &blockNumber,
},
}
// Execute batch call
err = c.BatchCall(batch)
if err != nil {
log.Fatal("Batch call failed:", err)
}
// Check individual results
for i, elem := range batch {
if elem.Error != nil {
fmt.Printf("Request %d failed: %v\n", i, elem.Error)
continue
}
}
fmt.Printf("Spec Version: %s\n", specVersion)
fmt.Printf("Chain ID: %s\n", chainID)
fmt.Printf("Block Number: %d\n", blockNumber)
}Error Handling
Each element in the batch can fail independently:
err = c.BatchCall(batch)
if err != nil {
// This error means the entire batch failed
log.Fatal("Batch call failed:", err)
}
// Check individual element errors
for i, elem := range batch {
if elem.Error != nil {
log.Printf("Element %d (%s) failed: %v", i, elem.Method, elem.Error)
}
}Performance Benefits
Batch calls reduce:
- Network round trips
- Connection overhead
- Total request time
Example comparison:
// Sequential calls: 3 network round trips
c.CallContext(ctx, &result1, "method1") // ~100ms
c.CallContext(ctx, &result2, "method2") // ~100ms
c.CallContext(ctx, &result3, "method3") // ~100ms
// Total: ~300ms
// Batch call: 1 network round trip
c.BatchCall(batch) // ~100ms
// Total: ~100msSubscription Methods
Subscribe
Creates a subscription to receive notifications for specific events. Requires a WebSocket connection.
Method Signature
func (c *Client) Subscribe(
ctx context.Context,
namespace string,
methodSuffix string,
channel interface{},
args ...interface{},
) (*ClientSubscription, error)Parameters
ctx- Context for subscription lifecycle managementnamespace- The RPC namespace (e.g., "starknet")methodSuffix- The subscription method suffix (e.g., "subscribeNewHeads")channel- Channel to receive notifications (must be a channel type)args- Additional arguments for the subscription
Returns
*ClientSubscription- Subscription handle for managing the subscriptionerror- Error if subscription fails
Usage Example
package main
import (
"context"
"fmt"
"log"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
// Connect via WebSocket
c, err := client.DialWebsocket(context.Background(), "wss://starknet-sepolia.public.blastapi.io/rpc/v0_8/ws", "")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Create channel for block headers
headers := make(chan map[string]interface{})
// Subscribe to new block headers
sub, err := c.Subscribe(
context.Background(),
"starknet",
"subscribeNewHeads",
headers,
)
if err != nil {
log.Fatal("Subscription failed:", err)
}
defer sub.Unsubscribe()
// Process incoming headers
for {
select {
case header := <-headers:
fmt.Printf("New block: %v\n", header)
case err := <-sub.Err():
log.Fatal("Subscription error:", err)
}
}
}Subscription with Context Cancellation
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialWebsocket(context.Background(), "wss://starknet-sepolia.public.blastapi.io/rpc/v0_8/ws", "")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Create context with 5 minute timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
headers := make(chan map[string]interface{})
sub, err := c.Subscribe(ctx, "starknet", "subscribeNewHeads", headers)
if err != nil {
log.Fatal(err)
}
defer sub.Unsubscribe()
for {
select {
case header := <-headers:
fmt.Printf("Block: %v\n", header)
case <-ctx.Done():
fmt.Println("Subscription cancelled")
return
case err := <-sub.Err():
log.Fatal("Error:", err)
}
}
}Handling Reorg Events
package main
import (
"context"
"fmt"
"log"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialWebsocket(context.Background(), "wss://starknet-sepolia.public.blastapi.io/rpc/v0_8/ws", "")
if err != nil {
log.Fatal(err)
}
defer c.Close()
// Channel receives both headers and reorg events
events := make(chan interface{})
sub, err := c.Subscribe(context.Background(), "starknet", "subscribeNewHeads", events)
if err != nil {
log.Fatal(err)
}
defer sub.Unsubscribe()
for event := range events {
switch v := event.(type) {
case map[string]interface{}:
// Normal block header
fmt.Printf("New block: %v\n", v)
case *client.ReorgEvent:
// Chain reorganization detected
fmt.Printf("Reorg detected: old=%v new=%v\n", v.OldChain, v.NewChain)
}
}
}Connection Management
Close
Closes the client connection and aborts any in-flight requests.
Method Signature
func (c *Client) Close()Usage Example
package main
import (
"log"
"github.com/NethermindEth/starknet.go/client"
)
func main() {
c, err := client.DialHTTP("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
// Always close the client when done
defer c.Close()
// Make RPC calls...
}Manual Close with Error Handling
func doWork() error {
c, err := client.DialHTTP(url)
if err != nil {
return err
}
defer c.Close()
// If an error occurs, Close() will still be called
if err := c.CallContext(ctx, &result, method); err != nil {
return err
}
return nil
}ClientSubscription Methods
The ClientSubscription type provides methods for managing active subscriptions.
Unsubscribe
Cancels the subscription and closes the notification channel.
Method Signature
func (sub *ClientSubscription) Unsubscribe()Usage Example
sub, err := c.Subscribe(ctx, namespace, method, channel)
if err != nil {
log.Fatal(err)
}
// Always unsubscribe when done
defer sub.Unsubscribe()
// Process events...Err
Returns a channel that receives the subscription error.
Method Signature
func (sub *ClientSubscription) Err() <-chan errorReturns
<-chan error- Read-only channel that receives errors
Usage Example
sub, err := c.Subscribe(ctx, namespace, method, channel)
if err != nil {
log.Fatal(err)
}
defer sub.Unsubscribe()
for {
select {
case data := <-channel:
// Process data
case err := <-sub.Err():
if err != nil {
log.Fatal("Subscription error:", err)
}
return
}
}Best Practices
Always Use Context
Prefer CallContext over Call for better control:
// Good: Can be cancelled and has timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := c.CallContext(ctx, &result, method)
// Less ideal: No timeout or cancellation
err := c.Call(&result, method)Batch Related Calls
When making multiple independent calls, use BatchCall:
// Good: Single network round trip
batch := []client.BatchElem{
{Method: "method1", Result: &result1},
{Method: "method2", Result: &result2},
{Method: "method3", Result: &result3},
}
c.BatchCall(batch)
// Less efficient: Three network round trips
c.CallContext(ctx, &result1, "method1")
c.CallContext(ctx, &result2, "method2")
c.CallContext(ctx, &result3, "method3")Handle Subscription Errors
Always monitor the error channel:
for {
select {
case data := <-channel:
// Process data
case err := <-sub.Err():
// Handle error, possibly reconnect
if err != nil {
log.Printf("Subscription error: %v", err)
return
}
}
}Clean Up Resources
Always close clients and unsubscribe:
c, err := client.DialHTTP(url)
if err != nil {
return err
}
defer c.Close() // Ensures cleanup
sub, err := c.Subscribe(ctx, ns, method, ch)
if err != nil {
return err
}
defer sub.Unsubscribe() // Ensures cleanupRelated Documentation
- Client Functions - Package-level functions for creating clients
- Types - Type definitions for Client and related types
- WebSocket Example - Complete subscription example
- RPC Methods - High-level Starknet RPC method wrappers

