TypeScript Example
Complete JavaScript/TypeScript implementation for streaming Solana transactions from NextBlock's TX Stream API, optimized for trading bots and fast transaction detection.
The example is hosted at github.com/nextblock-ag/nextblock-stream-examples
Prerequisites
bun add @grpc/grpc-js @grpc/proto-loader
bun add @solana/addresses @solana/codec-strings @solana/kit
# Generate the TX Stream proto client from the proto specification
# In the example repo, dependencies and the generated .ts files are already available
Example
import * as grpc from "@grpc/grpc-js";
import {
NextStreamNotification,
NextStreamServiceClient,
} from "./protos/stream";
import { NextStreamSubscription } from "./protos/stream";
import {
createKeyPairFromBytes,
getAddressFromPublicKey,
getBase58Decoder,
getBase58Encoder,
getCompiledTransactionMessageDecoder,
getSignatureFromTransaction,
getTransactionDecoder,
getUtf8Encoder,
signBytes,
type Address,
} from "@solana/kit";
/*
the auth message needs to be built clients-side.
it is a pipe-separated string made of:
1. domain that's being connected to (e.g. fra.stream.nextblock.io)
2. the publickey that sent the fee to strmuYvHKeA1qvHqooUpwUk2BFwaAmMbK9WXY9mh2GJ
3. a random nonce
4. the current unix timestamp
it is then signed by the supplied publickey.
*/
function buildAuthMessage(
domain: string,
authenticatedPublicKey: Address
): string {
const nonce = Math.random().toString();
const ts = Math.floor(Date.now());
return `${domain}|${authenticatedPublicKey.toString()}|${nonce}|${ts}`;
}
async function main() {
const domain = "fra.stream.nextblock.io:22221";
const authenticationPrivateKey = await createKeyPairFromBytes(
getBase58Encoder().encode("YOUR_PRIVATE_KEY")
);
const authenticationPublicKey = await getAddressFromPublicKey(
authenticationPrivateKey.publicKey
);
const authenticationMessage = buildAuthMessage(
domain,
authenticationPublicKey
);
const authenticationSignature = await signBytes(
authenticationPrivateKey.privateKey,
getUtf8Encoder().encode(authenticationMessage)
);
const client = new NextStreamServiceClient(
domain,
grpc.credentials.createInsecure(),
{
"grpc.keepalive_time_ms": 5000,
"grpc.keepalive_timeout_ms": 1000,
"grpc.keepalive_permit_without_calls": 0,
}
);
const req: NextStreamSubscription = {
authenticationPublickey: authenticationPublicKey.toString(),
authenticationMessage,
authenticationSignature: getBase58Decoder().decode(
authenticationSignature
),
accounts: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"],
};
const stream = client.subscribeNextStream(req);
stream.on("data", (msg: NextStreamNotification) => {
try {
const packet = msg.packet;
if (!packet) {
return;
}
const txBytes = packet.transaction;
const slot = packet.slot;
const tx = getTransactionDecoder().decode(txBytes);
const message = getCompiledTransactionMessageDecoder().decode(
tx.messageBytes
);
console.log(
`got new sig ${getSignatureFromTransaction(
tx
).toString()} on slot ${slot}`
);
} catch (e) {
console.error("error processing message:", e);
}
});
stream.on("error", (err) => {
console.error("error receiving from sub:", err);
process.exit(1);
});
stream.on("end", () => {
console.error("stream ended");
process.exit(0);
});
}
main();
Usage Examples
# Log signature + slot for all filtered transactions
bun index.ts
Available Endpoints
Choose the endpoint closest to your location:
Frankfurt:
fra.stream.nextblock.io:22221
Amsterdam:
amsterdam.stream.nextblock.io:22221
London:
london.stream.nextblock.io:22221
Singapore:
singapore.stream.nextblock.io:22221
Tokyo:
tokyo.stream.nextblock.io:22221
New York:
ny.stream.nextblock.io:22221
Salt Lake City:
slc.stream.nextblock.io:22221
Best Practices for Trading Bots
Use insecure connections: Better performance with NextBlock's optimized network
Filter efficiently: Only subscribe to programs you need to reduce bandwidth
Handle reconnections: Implement automatic reconnection logic
Process quickly: Avoid blocking the stream receiver
Monitor performance: Track processing latency and throughput
Implement graceful shutdown: Handle interrupt signals properly
Use multiple endpoints: Implement redundancy for critical applications
Last updated