Overview
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine, perfect for building scalable network applications. Follow the official installation guide to install Node.js. Verify the installation:
node --version
npm --version
Initiating the Node.js Project for Hyperliquid gRPC
Step 1: Initialize Node.js Project
Create a dedicated directory for your Hyperliquid gRPC project and navigate into it:
mkdir hyperliquid-grpc-nodejs
cd hyperliquid-grpc-nodejs
npm init -y
Step 2: Install Dependencies
Install the necessary Node.js dependencies for gRPC and Protocol Buffers:
# Install gRPC and Protocol Buffers packages
npm install @grpc/grpc-js @grpc/proto-loader
# For TypeScript support (optional)
npm install -D typescript @types/node ts-node
# For development
npm install -D nodemon
Step 3: Create Proto Files
Create the proto directory and add the Hyperliquid streaming protocol definition:
# Create proto directory
mkdir -p proto
Create a new file named proto/streaming.proto and add the following content:
syntax = "proto3";
package hyperliquid;
service Streaming {
// Bi-directional streaming
rpc StreamData (stream SubscribeRequest) returns (stream SubscribeUpdate);
rpc Ping (PingRequest) returns (PingResponse);
}
service BlockStreaming {
// Stream replica_cmds (raw blocks)
rpc StreamBlocks (Timestamp) returns (stream Block);
}
// --- Requests ---
message SubscribeRequest {
oneof request {
StreamSubscribe subscribe = 1;
Ping ping = 3;
}
reserved 2;
}
message StreamSubscribe {
StreamType stream_type = 1;
uint64 start_block = 2;
// Generic filters - field name to allowed values
// Recursively searches each event for matching field/value pairs
// Example: {"coin": ["ETH", "BTC"], "user": ["0x123..."], "type": ["deposit"]}
map<string, FilterValues> filters = 3;
// Optional name for this filter
// Allows multiple independent filters per stream (OR logic)
string filter_name = 4;
}
// Container for filter values
message FilterValues {
repeated string values = 1;
}
message Ping { int64 timestamp = 1; }
// --- Responses ---
message SubscribeUpdate {
oneof update {
StreamResponse data = 1;
Pong pong = 2;
}
}
message StreamResponse {
uint64 block_number = 1;
uint64 timestamp = 2; // Server ingress timestamp
// Raw JSON data from the file (Exact replica of source)
string data = 3;
}
// --- Data Types ---
enum StreamType {
UNKNOWN = 0;
TRADES = 1;
ORDERS = 2;
BOOK_UPDATES = 3;
TWAP = 4;
EVENTS = 5;
BLOCKS = 6;
WRITER_ACTIONS = 7;
}
message Block {
string data_json = 1;
}
message Pong { int64 timestamp = 1; }
message Timestamp { int64 timestamp = 1; }
message PingRequest { int32 count = 1; }
message PingResponse { int32 count = 1; }
Step 4: Create Main Application (JavaScript)
Create your main application file to test the connection:
Create index.js:
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const path = require('path');
// Configuration
const GRPC_ENDPOINT = 'your-grpc-endpoint:port';
const AUTH_TOKEN = 'your-auth-token';
// Load proto file
const packageDefinition = protoLoader.loadSync(
path.join(__dirname, 'proto/streaming.proto'),
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
}
);
const hyperliquidProto = grpc.loadPackageDefinition(packageDefinition).hyperliquid;
// Create gRPC client with TLS
function createClient() {
const credentials = grpc.credentials.createSsl();
const client = new hyperliquidProto.Streaming(
GRPC_ENDPOINT,
credentials,
{
'grpc.max_receive_message_length': 100 * 1024 * 1024, // 100MB
}
);
return client;
}
// Create metadata with auth token
function createMetadata() {
const metadata = new grpc.Metadata();
metadata.add('x-token', AUTH_TOKEN);
return metadata;
}
// Test connectivity with ping
function testPing(client) {
return new Promise((resolve, reject) => {
const metadata = createMetadata();
client.Ping({ count: 1 }, metadata, (error, response) => {
if (error) {
reject(new Error(`Ping failed: ${error.message}`));
return;
}
console.log('✅ Ping successful:', response);
resolve(response);
});
});
}
// Main function
async function main() {
try {
console.log(`Testing connection to: ${GRPC_ENDPOINT}`);
// Create client
const client = createClient();
// Test connectivity
await testPing(client);
console.log('✅ Connection test completed successfully!');
// Close the client
client.close();
} catch (error) {
console.error('❌ Error:', error.message);
process.exit(1);
}
}
// Run the application
main();
Step 5: Create TypeScript Version (Optional)
If you prefer TypeScript, create index.ts:
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import * as path from 'path';
// Configuration
const GRPC_ENDPOINT = 'your-grpc-endpoint:port';
const AUTH_TOKEN = 'your-auth-token';
// Load proto file
const packageDefinition = protoLoader.loadSync(
path.join(__dirname, 'proto/streaming.proto'),
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
}
);
const hyperliquidProto = grpc.loadPackageDefinition(packageDefinition) as any;
interface PingRequest {
count: number;
}
interface PingResponse {
count: number;
}
// Create gRPC client with TLS
function createClient(): any {
const credentials = grpc.credentials.createSsl();
const client = new hyperliquidProto.hyperliquid.Streaming(
GRPC_ENDPOINT,
credentials,
{
'grpc.max_receive_message_length': 100 * 1024 * 1024, // 100MB
}
);
return client;
}
// Create metadata with auth token
function createMetadata(): grpc.Metadata {
const metadata = new grpc.Metadata();
metadata.add('x-token', AUTH_TOKEN);
return metadata;
}
// Test connectivity with ping
function testPing(client: any): Promise<PingResponse> {
return new Promise((resolve, reject) => {
const metadata = createMetadata();
client.Ping({ count: 1 }, metadata, (error: grpc.ServiceError | null, response: PingResponse) => {
if (error) {
reject(new Error(`Ping failed: ${error.message}`));
return;
}
console.log('✅ Ping successful:', response);
resolve(response);
});
});
}
// Main function
async function main(): Promise<void> {
try {
console.log(`Testing connection to: ${GRPC_ENDPOINT}`);
// Create client
const client = createClient();
// Test connectivity
await testPing(client);
console.log('✅ Connection test completed successfully!');
// Close the client
client.close();
} catch (error) {
console.error('❌ Error:', (error as Error).message);
process.exit(1);
}
}
// Run the application
main();
Step 6: Update package.json Scripts
Add helpful scripts to your package.json:
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"ts:start": "ts-node index.ts",
"ts:dev": "nodemon --exec ts-node index.ts",
"build": "tsc"
}
}
Step 7: Create TypeScript Config (if using TypeScript)
If using TypeScript, create tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Step 8: Run the Application
Build and execute your application to test the gRPC connection:
For JavaScript:
npm start
# or for development with auto-reload
npm run dev
For TypeScript:
npm run ts:start
# or for development with auto-reload
npm run ts:dev
Step 9: Verify Setup
Confirm that your setup is working correctly by checking the output:
Testing connection to: docs-demo.hype-mainnet.quiknode.pro:10000
✅ Ping successful: { count: 1 }
✅ Connection test completed successfully!
If everything is set up correctly, you should see:
- Connection established to the gRPC endpoint
- Successful ping response
- No compilation or runtime errors
We ❤️ Feedback!
If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!