Skip to content

gRPC Integration

This guide explains how to integrate with TradeX gRPC services for high-performance internal service communication.

TradeX uses gRPC for internal service-to-service communication, providing type-safe, high-performance APIs.

  • gRPC client library for your language
  • Protocol Buffer compiler (protoc)
  • Service protobuf definitions
  • Market Data Service: Market data queries and streaming
  • Metadata Service: Instrument configuration queries
  • Wallet Service: Balance operations and holds
  • Risk Service: Risk calculations
Terminal window
npm install @grpc/grpc-js @grpc/proto-loader
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const packageDefinition = protoLoader.loadSync(
'path/to/service.proto',
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
}
);
const proto = grpc.loadPackageDefinition(packageDefinition);
const client = new proto.marketdata.MarketDataService(
'marketdata-service:50051',
grpc.credentials.createInsecure()
);
// Unary call
client.GetOrderBook(
{ symbol: 'BTCUSDT-PERP', depth: 20 },
(error, response) => {
if (error) {
console.error('Error:', error);
return;
}
console.log('Order book:', response);
}
);
// Promise-based
const orderBook = await new Promise((resolve, reject) => {
client.GetOrderBook(
{ symbol: 'BTCUSDT-PERP', depth: 20 },
(error, response) => {
if (error) reject(error);
else resolve(response);
}
);
});
const call = client.WatchConfigUpdates({});
call.on('data', (update) => {
console.log('Config update:', update);
});
call.on('error', (error) => {
console.error('Stream error:', error);
});
call.on('end', () => {
console.log('Stream ended');
});
Terminal window
pip install grpcio grpcio-tools
Terminal window
python -m grpc_tools.protoc \
-I./proto \
--python_out=./generated \
--grpc_python_out=./generated \
./proto/service.proto
import grpc
import generated.service_pb2 as service_pb2
import generated.service_pb2_grpc as service_pb2_grpc
channel = grpc.insecure_channel('marketdata-service:50051')
stub = service_pb2_grpc.MarketDataServiceStub(channel)
# Unary call
request = service_pb2.GetOrderBookRequest(
symbol='BTCUSDT-PERP',
depth=20
)
response = stub.GetOrderBook(request)
print('Order book:', response)
# Server streaming
request = service_pb2.WatchConfigUpdatesRequest()
for update in stub.WatchConfigUpdates(request):
print('Config update:', update)
Terminal window
go get google.golang.org/grpc
go get google.golang.org/protobuf
Terminal window
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/service.proto
import (
"google.golang.org/grpc"
pb "path/to/generated/proto"
)
conn, err := grpc.Dial(
"marketdata-service:50051",
grpc.WithInsecure(),
)
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewMarketDataServiceClient(conn)
// Unary call
ctx := context.Background()
req := &pb.GetOrderBookRequest{
Symbol: "BTCUSDT-PERP",
Depth: 20,
}
resp, err := client.GetOrderBook(ctx, req)
if err != nil {
log.Fatalf("Error: %v", err)
}
fmt.Printf("Order book: %v\n", resp)
// Server streaming
stream, err := client.WatchConfigUpdates(ctx, &pb.WatchConfigUpdatesRequest{})
if err != nil {
log.Fatalf("Error: %v", err)
}
for {
update, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("Error: %v", err)
}
fmt.Printf("Config update: %v\n", update)
}
import { status } from '@grpc/grpc-js';
try {
const response = await callRPC();
} catch (error) {
if (error.code === status.NOT_FOUND) {
console.error('Resource not found');
} else if (error.code === status.UNAVAILABLE) {
console.error('Service unavailable');
} else {
console.error('Error:', error);
}
}
async function callWithRetry(client, method, request, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await callRPC(client, method, request);
} catch (error) {
if (error.code === status.UNAVAILABLE && i < maxRetries - 1) {
await sleep(1000 * Math.pow(2, i));
continue;
}
throw error;
}
}
}
const credentials = grpc.credentials.createSsl(
fs.readFileSync('ca.crt'),
fs.readFileSync('client.key'),
fs.readFileSync('client.crt')
);
const client = new proto.Service(
'service:50051',
credentials
);
const metadata = new grpc.Metadata();
metadata.add('authorization', `Bearer ${apiKey}`);
client.GetOrderBook(
request,
metadata,
(error, response) => {
// handle response
}
);
  • Reuse Connections: Create clients once and reuse
  • Connection Pooling: Use connection pools for high throughput
  • Graceful Shutdown: Close connections on shutdown
const deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 5); // 5 second timeout
client.GetOrderBook(
request,
{ deadline },
(error, response) => {
// handle response
}
);
// Track metrics
const metrics = {
requests: 0,
errors: 0,
latency: []
};
const startTime = Date.now();
client.GetOrderBook(request, (error, response) => {
metrics.requests++;
if (error) metrics.errors++;
metrics.latency.push(Date.now() - startTime);
});