gRPC Quick Start
info
You will need:
- Arkhia gRPC Service URL
The gRPC can be retrieved from the Arkhia Dashboard after you Create a Project.
Don't have an account yet with Arkhia? Signup.
Subscribe to a Topic
- Node.js
- Python
- cURL
- Go
const { Client, TopicMessageQuery } = require("@hashgraph/sdk"); const nodes = { "35.237.100.180:50211" : "0.0.3"} const topicId = `<YOUR_TOPIC_ID>`; // https://explorer.arkhia.io/#/testnet/topics const accountId = `<YOUR_HEDERA_ACCOUNT_ID>`; const privateKey = `<YOUR_HEDERA_PRIVATE_KEY>`; const arkhiaGRPC = '<ARKHIA_GRPC_URL>'; async function createClient() { if (accountId == null || privateKey == null ) { throw new Error("Variables accountId and privateKey must be present"); } const client = Client.forNetwork(nodes).setMirrorNetwork(arkhiaGRPC); client.setOperator(accountId, privateKey); return client; } async function getMessagesFromTopic(topicId) { const client = await createClient(); console.log(`Subscribing to ${arkhiaGRPC}`); //Create the query new TopicMessageQuery() .setTopicId(topicId) .setStartTime(0) .subscribe( client, (message) => console.log(topicId + ": -> " + Buffer.from(message.contents, "utf8").toString()) ); } getMessagesFromTopic(topicId);
import asyncioimport grpcfrom hedera import ( Client, TopicMessageQuery, AccountId, PrivateKey)# ConfigurationTOPIC_ID = "<YOUR_TOPIC_ID>" # https://explorer.arkhia.io/#/testnet/topicsACCOUNT_ID = "<YOUR_HEDERA_ACCOUNT_ID>"PRIVATE_KEY = "<YOUR_HEDERA_PRIVATE_KEY>"ARKHIA_GRPC_URL = "<ARKHIA_GRPC_URL>"async def create_client(): """Create and configure Hedera client with Arkhia gRPC endpoint""" if not ACCOUNT_ID or not PRIVATE_KEY: raise ValueError("Variables ACCOUNT_ID and PRIVATE_KEY must be present") client = Client.for_testnet() client.set_mirror_network([ARKHIA_GRPC_URL]) client.set_operator(AccountId.from_string(ACCOUNT_ID), PrivateKey.from_string(PRIVATE_KEY)) return clientasync def subscribe_to_topic(topic_id): """Subscribe to HCS topic and listen for messages""" client = await create_client() print(f"Subscribing to topic {topic_id} via {ARKHIA_GRPC_URL}") def message_handler(message): contents = message.contents.decode('utf-8') print(f"{topic_id}: -> {contents}") # Create and execute the topic subscription query = TopicMessageQuery().set_topic_id(topic_id).set_start_time(0) try: await query.subscribe(client, message_handler) except Exception as e: print(f"Error subscribing to topic: {e}") finally: client.close()# Alternative using grpcio directlyasync def subscribe_with_grpc(): """Direct gRPC implementation for advanced use cases""" import grpc from concurrent import futures # gRPC channel configuration channel = grpc.aio.insecure_channel(ARKHIA_GRPC_URL) try: # Your gRPC service calls here print(f"Connected to gRPC endpoint: {ARKHIA_GRPC_URL}") # Implement your specific gRPC calls based on Hedera proto definitions except grpc.RpcError as e: print(f"gRPC error: {e}") finally: await channel.close()if __name__ == "__main__": asyncio.run(subscribe_to_topic(TOPIC_ID))
#!/bin/bash# ConfigurationARKHIA_GRPC_URL="<ARKHIA_GRPC_URL>"TOPIC_ID="<YOUR_TOPIC_ID>"API_KEY="<YOUR_API_KEY>"# Note: gRPC over HTTP/2 requires special handling with cURL# This example shows HTTP/2 REST gateway approach# 1. Using grpcurl (recommended gRPC command-line tool)# Install: go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latestecho "Subscribing to topic messages via grpcurl..."grpcurl -plaintext \ -H "authorization: Bearer ${API_KEY}" \ -d '{ "topic_id": "'${TOPIC_ID}'", "start_time": { "seconds": 0 } }' \ ${ARKHIA_GRPC_URL} \ com.hedera.mirror.api.proto.ConsensusService/subscribeTopic# 2. Alternative: HTTP/2 with cURL (if REST gateway available)echo "Alternative HTTP/2 approach..."curl --http2 \ -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${API_KEY}" \ -d '{ "topicId": "'${TOPIC_ID}'", "startTime": "0" }' \ "https://${ARKHIA_GRPC_URL}/api/v1/topics/${TOPIC_ID}/messages/subscribe"# 3. Testing gRPC connectivityecho "Testing gRPC server connectivity..."grpcurl -plaintext ${ARKHIA_GRPC_URL} list# 4. Get topic informationecho "Getting topic information..."curl -X GET \ -H "x-api-key: ${API_KEY}" \ "https://pool.arkhia.io/hedera/mainnet/api/v1/topics/${TOPIC_ID}"
package mainimport ( "context" "fmt" "log" "time" "github.com/hashgraph/hedera-sdk-go/v2" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure")const ( topicID = "<YOUR_TOPIC_ID>" accountID = "<YOUR_HEDERA_ACCOUNT_ID>" privateKey = "<YOUR_HEDERA_PRIVATE_KEY>" arkhiaGRPCURL = "<ARKHIA_GRPC_URL>")func createClient() (*hedera.Client, error) { if accountID == "" || privateKey == "" { return nil, fmt.Errorf("accountID and privateKey must be present") } client := hedera.ClientForTestnet() client.SetMirrorNetwork([]string{arkhiaGRPCURL}) accountIDObj, err := hedera.AccountIDFromString(accountID) if err != nil { return nil, fmt.Errorf("invalid account ID: %v", err) } privateKeyObj, err := hedera.PrivateKeyFromString(privateKey) if err != nil { return nil, fmt.Errorf("invalid private key: %v", err) } client.SetOperator(accountIDObj, privateKeyObj) return &client, nil}func subscribeToTopic(topicID string) error { client, err := createClient() if err != nil { return fmt.Errorf("failed to create client: %v", err) } defer client.Close() fmt.Printf("Subscribing to topic %s via %s\n", topicID, arkhiaGRPCURL) topicIDObj, err := hedera.TopicIDFromString(topicID) if err != nil { return fmt.Errorf("invalid topic ID: %v", err) } // Create subscription _, err = hedera.NewTopicMessageQuery(). SetTopicID(topicIDObj). SetStartTime(time.Unix(0, 0)). Subscribe(*client, func(message hedera.TopicMessage) { fmt.Printf("%s: -> %s\n", topicID, string(message.Contents)) }) if err != nil { return fmt.Errorf("subscription error: %v", err) } // Keep the program running select {}}// Alternative direct gRPC implementationfunc connectDirectGRPC() error { ctx := context.Background() // Create gRPC connection conn, err := grpc.DialContext(ctx, arkhiaGRPCURL, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return fmt.Errorf("failed to connect: %v", err) } defer conn.Close() fmt.Printf("Connected to gRPC endpoint: %s\n", arkhiaGRPCURL) // Implement your specific gRPC calls here using Hedera proto definitions return nil}func main() { if err := subscribeToTopic(topicID); err != nil { log.Fatalf("Error: %v", err) }}