Using grpcurl with Sui gRPC
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 grpcurl
Linux#
# 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#
# Using Chocolatey
choco install grpcurl
# Or download from GitHub releases
# https://github.com/fullstorydev/grpcurl/releases
From Source#
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#
# 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 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 .env
Authentication Header#
All Dwellir gRPC calls require the x-api-key header:
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
list
Service Discovery#
List All Available Services#
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
list
Expected output:
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#
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
list sui.rpc.v2.StateService
Output:
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#
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
${DWELLIR_ENDPOINT} \
describe sui.rpc.v2.StateService.GetBalance
Common API Calls#
Get Current Checkpoint#
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetCheckpoint
Get 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/GetObject
Get 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/GetBalance
Get Coin Metadata#
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{"coin_type": "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.StateService/GetCoinInfo
Get Current Epoch#
grpcurl \
-H "x-api-key: ${DWELLIR_API_KEY}" \
-d '{}' \
${DWELLIR_ENDPOINT} \
sui.rpc.v2.LedgerService/GetEpoch
Get Move Package#
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:
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:
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.json
Using 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.json
Practical 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
done
Check 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"
fi
CI/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/GetEpoch
Docker 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_ENDPOINT
Authentication 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 \
list
Invalid 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.GetObject
TLS/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} \
list
Best 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/GetCheckpoint
3. 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.log
4. 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-epoch
Related 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