gRPC Guide

dRPC gRPC Guide

dRPC serves each supported chain's native gRPC API at grpc.drpc.live:443. Use the chain's own protobuf definitions unchanged and add two metadata values to every call: x-drpc-key and x-drpc-chain.

Endpoint and required metadata#

Connect over TLS to grpc.drpc.live:443 and send both values below as gRPC metadata on every call. That is the only dRPC-specific part: requests and responses are the chain's own protobuf messages.

Metadata keyValueExample
x-drpc-key (x-token)Your dRPC API keyAk3...9xQ
x-drpc-chainThe chain's dRPC short name (see Supported chains)sui

x-token is an alias for x-drpc-key, both carry your dRPC API key

The chain goes in metadata rather than the URL because gRPC uses the request path for the method name, and service names like cosmos.bank.v1beta1.Query are shared by many chains. Metadata keys are case-insensitive.

Quick test with grpcurl#

grpcurl (opens in a new tab) works without proto files, because the endpoint supports gRPC server reflection. Pass the two metadata values with -H.

export DRPC_KEY=<your dRPC key>
 
# List the services dRPC routes
grpcurl -H "x-drpc-key: $DRPC_KEY" -H "x-drpc-chain: sui" \
  grpc.drpc.live:443 list
 
# Inspect one service
grpcurl -H "x-drpc-key: $DRPC_KEY" -H "x-drpc-chain: sui" \
  grpc.drpc.live:443 describe sui.rpc.v2.LedgerService
 
# Call a method on Sui
grpcurl -H "x-drpc-key: $DRPC_KEY" -H "x-drpc-chain: sui" -d '{}' \
  grpc.drpc.live:443 sui.rpc.v2.LedgerService/GetServiceInfo
 
# Same endpoint, a different chain: only x-drpc-chain changes
grpcurl -H "x-drpc-key: $DRPC_KEY" -H "x-drpc-chain: celestia" -d '{}' \
  grpc.drpc.live:443 cosmos.base.tendermint.v1beta1.Service/GetLatestBlock

list returns the services for every supported chain, not only the one in x-drpc-chain. Call the services your chain actually implements.

Go example#

Set the metadata once on the connection with grpc.WithPerRPCCredentials, and every call from every generated client carries it. The rest is the chain's standard Go client. The example below calls Sui.

package main
 
import (
	"context"
	"crypto/tls"
	"fmt"
	"log"
	"os"
	"time"
 
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
 
	suirpc "example.com/myapp/gen/sui/rpc/v2"
)
 
// drpcAuth attaches the two dRPC metadata values to every call on the connection.
type drpcAuth struct {
	key   string
	chain string
}
 
func (a drpcAuth) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
	return map[string]string{
		"x-drpc-key":   a.key,
		"x-drpc-chain": a.chain,
	}, nil
}
 
func (drpcAuth) RequireTransportSecurity() bool { return true }
 
func main() {
	conn, err := grpc.NewClient("grpc.drpc.live:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
		grpc.WithPerRPCCredentials(drpcAuth{key: os.Getenv("DRPC_KEY"), chain: "sui"}),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
 
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
 
	info, err := suirpc.NewLedgerServiceClient(conn).GetServiceInfo(ctx, &suirpc.GetServiceInfoRequest{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("chain:", info.GetChain(), "checkpoint:", info.GetCheckpointHeight())
}

To use another chain, change chain and swap in that chain's client. Cosmos SDK chains, for example, can use the clients from the Cosmos SDK Go module. If you only need the metadata on some calls, add it per call with metadata.AppendToOutgoingContext(ctx, "x-drpc-key", key, "x-drpc-chain", "sui").

Generating the Sui stubs. Sui publishes its protos in MystenLabs/sui-apis (opens in a new tab) without Go package options, so set one when you generate. With buf (opens in a new tab), protoc-gen-go and protoc-gen-go-grpc installed:

# buf.gen.yaml
version: v2
managed:
  enabled: true
  override:
    - file_option: go_package
      path: sui/rpc/v2
      value: example.com/myapp/gen/sui/rpc/v2;suirpc
plugins:
  - local: protoc-gen-go
    out: gen
    opt:
      - paths=source_relative
      - Mgoogle/protobuf/timestamp.proto=google.golang.org/protobuf/types/known/timestamppb
  - local: protoc-gen-go-grpc
    out: gen
    opt:
      - paths=source_relative
      - Mgoogle/protobuf/timestamp.proto=google.golang.org/protobuf/types/known/timestamppb
buf generate https://github.com/MystenLabs/sui-apis.git --path proto/sui/rpc/v2 --template buf.gen.yaml

Supported chains#

The value of x-drpc-chain is the chain's dRPC short name. Protos come from each chain's own project.

Chainx-drpc-chainProtosSample method
Sui MainnetsuiMystenLabs/sui-apis (opens in a new tab) (sui.rpc.v2)sui.rpc.v2.LedgerService/GetServiceInfo
Sui Testnetsui-testnetMystenLabs/sui-apis (opens in a new tab) (sui.rpc.v2)sui.rpc.v2.LedgerService/GetServiceInfo
Celestia Mainnetcelestiacosmos/cosmos-sdk (opens in a new tab) query and tx servicescosmos.base.tendermint.v1beta1.Service/GetLatestBlock
Celestia Mochacelestia-mochacosmos/cosmos-sdk (opens in a new tab) query and tx servicescosmos.base.tendermint.v1beta1.Service/GetLatestBlock

Errors#

Errors use standard gRPC status codes:

StatusWhen
UNAUTHENTICATEDx-drpc-key is missing, invalid or deactivated
INVALID_ARGUMENTx-drpc-chain is missing or unknown, or the request is malformed
UNIMPLEMENTEDThe method is not supported for that chain, or it is server-streaming
PERMISSION_DENIEDThe key's settings block this chain, IP, origin or method
RESOURCE_EXHAUSTEDRate limit, balance or daily limit exceeded, or the message is too large
DEADLINE_EXCEEDEDThe request timed out
UNAVAILABLENo provider could serve the request right now; retry
Any other codeReturned by the node itself and passed through unchanged, for example NOT_FOUND