Docs

Using grpcurl with Sui gRPC

Complete guide to using grpcurl for testing and debugging Sui gRPC API calls with Dwellir. Perfect for quick API exploration and CI/CD integration.

grpcurl is a command-line tool for interacting with gRPC servers, similar to how curl works with REST APIs. It's invaluable for quick API testing, debugging, and scripting without writing code.

Why Use grpcurl?

  • Rapid prototyping - Test API calls instantly without writing client code
  • Debugging - Inspect request/response structures and troubleshoot issues
  • CI/CD integration - Automate gRPC endpoint testing in pipelines
  • Service discovery - Explore available methods and message structures
  • Shell scripting - Build automation scripts with gRPC calls

Installation

macOS

Bash
brew install grpcurl

Linux

Bash
# Download latest release
VERSION=1.8.9
wget https://github.com/fullstorydev/grpcurl/releases/download/v${VERSION}/grpcurl_${VERSION}_linux_x86_64.tar.gz

# Extract and install
tar -xzf grpcurl_${VERSION}_linux_x86_64.tar.gz
sudo mv grpcurl /usr/local/bin/
chmod +x /usr/local/bin/grpcurl

# Verify installation
grpcurl --version

Windows

powershell
# Using Chocolatey
choco install grpcurl

# Or download from GitHub releases
# https://github.com/fullstorydev/grpcurl/releases

From Source

Bash
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

Getting the Proto Files

grpcurl can work with gRPC reflection (no proto files needed), but having the proto definitions locally is useful for understanding the API structure and generating code.

Clone Sui APIs Repository

Bash
# Clone the Sui APIs repository
git clone https://github.com/MystenLabs/sui-apis.git
cd sui-apis

# Navigate to proto definitions
cd protos

The proto files are located in protos/:

  • sui/ledger.proto - Ledger service (checkpoints, objects, transactions)
  • sui/state.proto - State service (balances, objects)
  • sui/move_package.proto - Package service
  • sui/transaction.proto - Transaction service
  • sui/signature_verification.proto - Signature verification

Optional: Copy Proto Files

Bash
# Create a protos directory in your project
mkdir -p ~/sui-grpc/protos

# Copy proto files
cp -r sui ~/sui-grpc/protos/

grpcurl works without proto files using server reflection, which is enabled on Dwellir endpoints. You only need the proto files if you want to inspect the schemas locally or generate client code.

Dwellir Connection Setup

Environment Variables

Create a .env file for your Dwellir credentials:

Bash
# .env
export DWELLIR_ENDPOINT="api-sui-mainnet-full.n.dwellir.com:443"
export DWELLIR_API_KEY="your_api_key_here"

Load the environment:

Bash
source .env

Authentication Header

All Dwellir gRPC calls require the x-api-key header:

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  list

Service Discovery

List All Available Services

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  list

Expected output:

Text
grpc.reflection.v1alpha.ServerReflection
sui.rpc.v2.LedgerService
sui.rpc.v2.MovePackageService
sui.rpc.v2.SignatureVerificationService
sui.rpc.v2.StateService
sui.rpc.v2.TransactionService

List Methods in a Service

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  list sui.rpc.v2.StateService

Output:

Text
sui.rpc.v2.StateService.GetBalance
sui.rpc.v2.StateService.GetCoinInfo
sui.rpc.v2.StateService.ListBalances
sui.rpc.v2.StateService.ListDynamicFields
sui.rpc.v2.StateService.ListOwnedObjects
sui.rpc.v2.StateService.SimulateTransaction

Describe a Method

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  describe sui.rpc.v2.StateService.GetBalance

Common API Calls

Get Current Checkpoint

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{}' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetCheckpoint

Get Object by ID

Bash
OBJECT_ID="0x5"

grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d "{\"object_id\": \"${OBJECT_ID}\"}" \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetObject

Get Balance for Address

Bash
ADDRESS="0x742d35cc6634c0532925a3b844bc9e7eb503c114a04bd3e02c7681a09e58b01d"
COIN_TYPE="0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"

grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d "{\"owner\": \"${ADDRESS}\", \"coin_type\": \"${COIN_TYPE}\"}" \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.StateService/GetBalance

Get Coin Metadata

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{"coin_type": "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"}' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.StateService/GetCoinInfo

Get Current Epoch

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{}' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetEpoch

Get Move Package

Bash
PACKAGE_ID="0x0000000000000000000000000000000000000000000000000000000000000002"

grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d "{\"package_id\": \"${PACKAGE_ID}\"}" \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.MovePackageService/GetPackage

Advanced Usage

Using Field Masks

Request only specific fields to reduce response size:

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{
    "read_mask": {
      "paths": ["sequence_number", "timestamp_ms", "transactions"]
    }
  }' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetCheckpoint

Formatted Output with jq

Parse and format JSON responses:

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{}' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetEpoch | jq '.epoch.epoch'

Save Response to File

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{}' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetCheckpoint > checkpoint.json

Using Request from File

Bash
# Create request file
cat > request.json <<EOF
{
  "owner": "0x742d35cc6634c0532925a3b844bc9e7eb503c114a04bd3e02c7681a09e58b01d",
  "coin_type": "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
}
EOF

# Execute request
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d @ \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.StateService/GetBalance < request.json

Practical Scripts

Monitor New Checkpoints

Bash
#!/bin/bash
# monitor-checkpoints.sh

ENDPOINT="api-sui-mainnet-full.n.dwellir.com:443"
API_KEY="your_api_key_here"

while true; do
  CHECKPOINT=$(grpcurl \
    -H "x-api-key: ${API_KEY}" \
    -d '{"read_mask": {"paths": ["sequence_number", "timestamp_ms"]}}' \
    ${ENDPOINT} \
    sui.rpc.v2.LedgerService/GetCheckpoint | jq -r '.checkpoint.sequenceNumber')

  echo "[$(date)] Current checkpoint: ${CHECKPOINT}"

  sleep 2
done

Check Multiple Balances

Bash
#!/bin/bash
# check-balances.sh

ENDPOINT="api-sui-mainnet-full.n.dwellir.com:443"
API_KEY="your_api_key_here"
ADDRESS="$1"

if [ -z "$ADDRESS" ]; then
  echo "Usage: $0 <sui_address>"
  exit 1
fi

echo "Fetching balances for: ${ADDRESS}"

# Get all balances
grpcurl \
  -H "x-api-key: ${API_KEY}" \
  -d "{\"owner\": \"${ADDRESS}\"}" \
  ${ENDPOINT} \
  sui.rpc.v2.StateService/ListBalances | \
  jq -r '.balances[] | "\(.coinType): \(.balance)"'

Validate Package Deployment

Bash
#!/bin/bash
# validate-package.sh

ENDPOINT="api-sui-mainnet-full.n.dwellir.com:443"
API_KEY="your_api_key_here"
PACKAGE_ID="$1"

if [ -z "$PACKAGE_ID" ]; then
  echo "Usage: $0 <package_id>"
  exit 1
fi

echo "Validating package: ${PACKAGE_ID}"

# Get package info
RESPONSE=$(grpcurl \
  -H "x-api-key: ${API_KEY}" \
  -d "{\"package_id\": \"${PACKAGE_ID}\"}" \
  ${ENDPOINT} \
  sui.rpc.v2.MovePackageService/GetPackage 2>&1)

if echo "$RESPONSE" | grep -q "NOT_FOUND"; then
  echo "❌ Package not found"
  exit 1
else
  echo "✓ Package exists"
  MODULE_COUNT=$(echo "$RESPONSE" | jq '.package.modules | length')
  echo "✓ Contains ${MODULE_COUNT} modules"
fi

CI/CD Integration

GitHub Actions Example

YAML
name: Test Sui gRPC Endpoint

on:
  schedule:
    - cron: '*/15 * * * *'  # Every 15 minutes
  workflow_dispatch:

jobs:
  test-grpc:
    runs-on: ubuntu-latest
    steps:
      - name: Install grpcurl
        run: |
          curl -sSL "https://github.com/fullstorydev/grpcurl/releases/download/v1.8.9/grpcurl_1.8.9_linux_x86_64.tar.gz" | tar -xz
          sudo mv grpcurl /usr/local/bin/

      - name: Test GetCheckpoint
        env:
          API_KEY: ${{ secrets.DWELLIR_API_KEY }}
        run: |
          grpcurl \
            -H "x-api-key: ${API_KEY}" \
            -d '{}' \
            api-sui-mainnet-full.n.dwellir.com:443 \
            sui.rpc.v2.LedgerService/GetCheckpoint

      - name: Test GetEpoch
        env:
          API_KEY: ${{ secrets.DWELLIR_API_KEY }}
        run: |
          grpcurl \
            -H "x-api-key: ${API_KEY}" \
            -d '{}' \
            api-sui-mainnet-full.n.dwellir.com:443 \
            sui.rpc.v2.LedgerService/GetEpoch

Docker Container

dockerfile
FROM alpine:latest

RUN apk add --no-cache curl jq bash

# Install grpcurl
RUN curl -sSL "https://github.com/fullstorydev/grpcurl/releases/download/v1.8.9/grpcurl_1.8.9_linux_x86_64.tar.gz" | tar -xz && \
    mv grpcurl /usr/local/bin/ && \
    chmod +x /usr/local/bin/grpcurl

# Copy scripts
COPY scripts/ /scripts/
RUN chmod +x /scripts/*.sh

CMD ["/bin/bash"]

Troubleshooting

Connection Issues

Problem: Failed to dial target host

Solution: Verify endpoint and port

Bash
# Test connectivity
nc -zv api-sui-mainnet-full.n.dwellir.com 443

# Check endpoint in environment
echo $DWELLIR_ENDPOINT

Authentication Errors

Problem: UNAUTHENTICATED: Missing or invalid API key

Solution: Verify your API key header

Bash
# Check if API key is set
echo $DWELLIR_API_KEY

# Test with explicit key
grpcurl \
  -H "x-api-key: your_actual_api_key" \
  api-sui-mainnet-full.n.dwellir.com:443 \
  list

Invalid Request Format

Problem: INVALID_ARGUMENT: Invalid request

Solution: Describe the method to see expected format

Bash
grpcurl \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  describe sui.rpc.v2.LedgerService.GetObject

TLS/SSL Issues

Problem: x509: certificate signed by unknown authority

Solution: Use -insecure flag (not recommended for production)

Bash
grpcurl -insecure \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  list

Best Practices

1. Use Environment Variables

Never hardcode API keys in scripts:

Bash
# Good
grpcurl -H "x-api-key: ${DWELLIR_API_KEY}" ...

# Bad - API key exposed in history
grpcurl -H "x-api-key: sk-abc123..." ...

2. Add Timeouts

Prevent hanging requests:

Bash
grpcurl \
  -max-time 10 \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetCheckpoint

3. Log Requests for Debugging

Bash
grpcurl -v \
  -H "x-api-key: ${DWELLIR_API_KEY}" \
  -d '{}' \
  ${DWELLIR_ENDPOINT} \
  sui.rpc.v2.LedgerService/GetCheckpoint 2>&1 | tee debug.log

4. Use Field Masks

Request only the data you need:

Bash
# Efficient - only get sequence number
grpcurl -d '{"read_mask": {"paths": ["sequence_number"]}}' ...

# Inefficient - gets entire checkpoint
grpcurl -d '{}' ...

Useful Aliases

Add to your ~/.bashrc or ~/.zshrc:

Bash
# Sui gRPC aliases
export DWELLIR_ENDPOINT="api-sui-mainnet-full.n.dwellir.com:443"
export DWELLIR_API_KEY="your_api_key_here"

alias sui-grpc='grpcurl -H "x-api-key: ${DWELLIR_API_KEY}" ${DWELLIR_ENDPOINT}'
alias sui-list='sui-grpc list'
alias sui-checkpoint='sui-grpc -d '"'"'{}'"'"' sui.rpc.v2.LedgerService/GetCheckpoint | jq'
alias sui-epoch='sui-grpc -d '"'"'{}'"'"' sui.rpc.v2.LedgerService/GetEpoch | jq'

Usage:

Bash
sui-list
sui-checkpoint
sui-epoch

Need help? Contact support@dwellir.com