Kaldera Quickstart

A first Kaldera stream in TypeScript or Rust, with the client requirements and common errors.

This page opens a Kaldera stream that prints every Pump.fun transaction as it happens.

Requirements

  • A Blade Runner or Nexus plan, and your API key from My Account.
  • Node.js 20.18 or later, or a recent Rust toolchain.
export CK_API_KEY="YOUR_API_KEY"

Existing consumers: four upstream changes

Four recent changes affect stream consumers, whoever they stream from: version 1 transactions, silent write-locked accounts, a new stake rewardType, and Token-2022 confidential transfer parsing. See Changes in the data you receive.

A transaction stream

Project setup

mkdir kaldera-quickstart && cd kaldera-quickstart
npm init -y
npm pkg set type=module
npm install @triton-one/yellowstone-grpc@9.0.0 bs58

The subscriber

stream.ts
import Client, {
  CommitmentLevel,
  type SubscribeRequest,
  type SubscribeUpdate,
} from "@triton-one/yellowstone-grpc";
import bs58 from "bs58";

const client = new Client(
  "https://kaldera-newyork.constant-k.com", // or kaldera-frankfurt
  process.env.CK_API_KEY, // sent as the x-token header
  undefined,
);
await client.connect();

const request: SubscribeRequest = {
  commitment: CommitmentLevel.PROCESSED,
  transactions: {
    pumpfun: {
      vote: false,
      failed: false,
      accountInclude: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
      accountExclude: [],
      accountRequired: [],
    },
  },
  // Every map must be present, even when empty
  accounts: {},
  slots: {},
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  blockFooter: {},
  accountsDataSlice: [],
};

const stream = await client.subscribe(request);

stream.on("data", (update: SubscribeUpdate) => {
  const tx = update.transaction;
  if (tx?.transaction) {
    console.log(`slot ${tx.slot}  ${bs58.encode(tx.transaction.signature)}`);
  }
});

stream.on("error", (err) => console.error("stream error:", err));
stream.on("close", () => console.log("stream closed"));

Running it

npx tsx stream.ts

The output holds one line per transaction:

slot 447913193  4t8vS3…Qx9
slot 447913193  2hLmZa…u7K

Command-line test

grpcurl needs the Yellowstone protocol files:

git clone --depth 1 --branch "v16.1.1+solana.4.3.0" https://github.com/rpcpool/yellowstone-grpc.git

grpcurl \
  -import-path yellowstone-grpc/yellowstone-grpc-proto/proto \
  -proto geyser.proto \
  -H "x-token: YOUR_API_KEY" \
  -d '{"slots": {"tip": {}}}' \
  kaldera-newyork.constant-k.com:443 geyser.Geyser/Subscribe

The command prints a stream of slot updates in JSON.

Client requirements

  • connect() comes first. In @triton-one/yellowstone-grpc 7.x and later, subscribe() fails until connect() has resolved.
  • Every map of SubscribeRequest is required by its TypeScript type. accounts, slots, transactions, transactionsStatus, blocks, blocksMeta, entry, blockFooter and accountsDataSlice must all be present, even when empty. From 8.0.0 the client fills missing maps at run time, but tsc still rejects the request.
  • ping updates carry no data. The server sends them to keep the stream open.
  • update.filters names which of your filters matched. See Filters.
  • Handler speed. Work that takes more than a few milliseconds belongs on a queue. On Blade Runner, a slow reader loses the oldest queued updates.
  • Reconnects. Backoff, then resume with fromSlot. See Replay.
  • Unused streams. stream.destroy() closes them. Open streams count toward your plan's stream limit.

Troubleshooting

ErrorCause and fix
Client not connected. Call connect() firstsubscribe() ran before await client.connect().
TypeScript error Property 'blockFooter' is missing in typeAdd blockFooter: {} to SubscribeRequest. Client 8.0.0 added the map.
Cannot convert undefined or null to object (7.x only)A map field is missing from SubscribeRequest. From 8.0.0 the client fills missing maps.
failed to open subscribe stream (TypeScript), unexpected HTTP status code … 204 (grpcurl), Missing or Invalid API Key (Rust)The key is missing or wrong, or your plan does not include Kaldera.
TypeScript error This expression is not constructable on new ClientYour tsconfig.json uses "module": "NodeNext". Switch to "module": "ESNext" with "moduleResolution": "bundler", or run with tsx, which does not type-check. The code runs correctly either way.
Rust panic: Could not automatically determine the process-level CryptoProviderAdd the tonic dependency with the tls-ring feature, as in the Cargo.toml above.
Updates arrive late or the stream falls behindNarrow your filters, turn on compression, process updates off the main loop, and run close to the node.

On this page