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
brew install grpcurlLinux
# 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 --versionWindows
# Using Chocolatey
choco install grpcurl
# Or download from GitHub releases
# https://github.com/fullstorydev/grpcurl/releasesFrom Source
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latestGetting 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
# Clone the Sui APIs repository
git clone https://github.com/MystenLabs/sui-apis.git
cd sui-apis
# Navigate to proto definitions
cd protosThe 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 servicesui/transaction.proto- Transaction servicesui/signature_verification.proto- Signature verification
Optional: Copy Proto Files
# 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:
# .env
export DWELLIR_ENDPOINT="api-sui-mainnet-full.n.dwellir.com:443"
export DWELLIR_API_KEY="your_api_key_here"Load the environment:
source .envAuthentication Header
All Dwellir gRPC calls require the x-api-key header:
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
listService Discovery
List All Available Services
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
listExpected output:
grpc.reflection.v1alpha.ServerReflection
sui.rpc.v2.LedgerService
sui.rpc.v2.MovePackageService
sui.rpc.v2.SignatureVerificationService
sui.rpc.v2.StateService
sui.rpc.v2.TransactionServiceList Methods in a Service
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
list sui.rpc.v2.StateServiceOutput:
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.SimulateTransactionDescribe a Method
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
describe sui.rpc.v2.StateService.GetBalanceCommon API Calls
Get Current Checkpoint
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetCheckpointGet Object by ID
OBJECT_ID="0x5"
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d "{\"object_id\": \"${OBJECT_ID}\"}" \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetObjectGet Balance for Address
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/GetBalanceGet Coin Metadata
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{"coin_type": "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.StateService/GetCoinInfoGet Current Epoch
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetEpochGet Move Package
PACKAGE_ID="0x0000000000000000000000000000000000000000000000000000000000000002"
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d "{\"package_id\": \"${PACKAGE_ID}\"}" \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.MovePackageService/GetPackageAdvanced Usage
Using Field Masks
Request only specific fields to reduce response size:
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{
"read_mask": {
"paths": ["sequence_number", "timestamp_ms", "transactions"]
}
}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetCheckpointFormatted Output with jq
Parse and format JSON responses:
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetEpoch | jq '.epoch.epoch'Save Response to File
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetCheckpoint > checkpoint.jsonUsing Request from File
# 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.jsonPractical Scripts
Monitor New Checkpoints
#!/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
doneCheck Multiple Balances
#!/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
#!/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"
fiCI/CD Integration
GitHub Actions Example
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/GetEpochDocker Container
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
# Test connectivity
nc -zv api-sui-mainnet-full.n.dwellir.com 443
# Check endpoint in environment
echo $DWELLIR_ENDPOINTAuthentication Errors
Problem: UNAUTHENTICATED: Missing or invalid API key
Solution: Verify your API key header
# 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 \
listInvalid Request Format
Problem: INVALID_ARGUMENT: Invalid request
Solution: Describe the method to see expected format
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
describe sui.rpc.v2.LedgerService.GetObjectTLS/SSL Issues
Problem: x509: certificate signed by unknown authority
Solution: Use -insecure flag (not recommended for production)
grpcurl -insecure \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
listBest Practices
1. Use Environment Variables
Never hardcode API keys in scripts:
# 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:
grpcurl \
-max-time 10 \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetCheckpoint3. Log Requests for Debugging
grpcurl -v \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetCheckpoint 2>&1 | tee debug.log4. Use Field Masks
Request only the data you need:
# 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:
# 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:
sui-list
sui-checkpoint
sui-epochRelated Resources
- gRPC Overview - Complete gRPC API introduction
- TypeScript Setup - Build production applications
- Python Setup - Python client setup
- Go Setup - Go client implementation
Need help? Contact support@dwellir.com
Sui gRPC Go
Complete guide to building production Go applications with Sui gRPC API on Dwellir. Includes project setup, type safety, connection pooling, and production patterns.
Python
Complete guide to building Python applications with Sui gRPC API on Dwellir. Includes project setup, authentication, type safety, and production patterns.