SDK
kubernodes — typed TypeScript client. All methods are thin wrappers around standard JSON-RPC 2.0 — no ABI encoding, no wallet management.
JavaScript / TypeScript
npm install kubernodes
Python
pip install kubernodes
Go
go get github.com/kubernodes/sdk-go
Rust
cargo add kubernodes
Java (Maven)
<dependency> <groupId>com.kubernodes</groupId> <artifactId>kubernodes-sdk</artifactId> <version>0.3.0</version> </dependency>
Ruby
gem install kubernodes
.NET
dotnet add package KuberNodes.Sdk
import { Kuber, CHAINS } from 'kubernodes';
// Recommended — zero-config
const kuber = new Kuber('pk_live_YOUR_KEY');
// With a default chain other than Ethereum
const base = new Kuber('pk_live_YOUR_KEY', CHAINS.BASE.chainId);
// Advanced — full config control
import { createClient } from 'kubernodes';
const kn = createClient({
apiKey: 'pk_live_YOUR_KEY',
chainId: CHAINS.ETHEREUM.chainId, // default chain (1)
baseUrl: 'https://rpc.kubernodes.com', // default
timeout: 10_000, // ms, default 10 000
retries: 3, // on network errors, default 3
debug: false, // log raw RPC to console
});getBlockNumbergetBlockNumber(chainId?: number): Promise<number>
Returns the current block number (latest confirmed block).
const n = await kn.getBlockNumber(); // 21_500_000
getBalancegetBalance(address: string, block?: string | number, chainId?: number): Promise<bigint>
Returns the ETH (or native token) balance in wei for the given address. block defaults to "latest".
const wei = await kn.getBalance("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96044");
// 1482300000000000000n (≈1.48 ETH)getGasPricegetGasPrice(chainId?: number): Promise<bigint>
Returns the current prevailing gas price in wei (legacy). For EIP-1559 chains, prefer eth_maxPriorityFeePerGas.
const gwei = await kn.getGasPrice(); // 25000000000n (25 Gwei)
getTransactionCountgetTransactionCount(address: string, block?: string | number, chainId?: number): Promise<number>
Returns the total number of transactions sent from an address (the nonce for the next transaction).
const nonce = await kn.getTransactionCount("0xabc...");
// 42getBlockgetBlock(block: string | number, fullTransactions?: boolean, chainId?: number): Promise<Block & { transactions: string[] | Transaction[] }>Fetches a block by number or hash. Pass true for fullTransactions to embed full Transaction objects instead of hashes.
const blk = await kn.getBlock("latest");
console.log(blk.number, blk.transactions.length);
// Full transaction objects:
const blkFull = await kn.getBlock("latest", true);
console.log(blkFull.transactions[0].hash);getTransactiongetTransaction(hash: string, chainId?: number): Promise<Transaction | null>
Fetches a transaction by hash. Returns null if not found.
const tx = await kn.getTransaction("0xabc...");
if (tx) console.log(tx.from, tx.value);getTransactionReceiptgetTransactionReceipt(hash: string, chainId?: number): Promise<TransactionReceipt | null>
Returns the receipt once a transaction is mined. Returns null if still pending.
const receipt = await kn.getTransactionReceipt("0xabc...");
if (receipt?.status === "0x1") console.log("confirmed");callcall(tx: { to: string; data?: string; from?: string; value?: string }, block?: string | number, chainId?: number): Promise<string>Executes a read-only call against a contract. Returns the ABI-encoded response as a hex string. Use with ethers.js Interface.decodeFunctionResult() for decoding.
// Read ERC-20 balanceOf
const data = '0x70a08231' + '000000000000000000000000d8dA6BF26964aF9D7eEd9e03E53415D37aA96044';
const result = await kn.call({ to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', data });
// "0x0000000000000000000000000000000000000000000000000000000005f5e100"estimateGasestimateGas(tx: { to?: string; from?: string; data?: string; value?: string }, chainId?: number): Promise<bigint>Estimates the gas required for a transaction. to is optional — omit for contract deployments.
const gas = await kn.estimateGas({ to: "0xabc...", data: "0x..." });
// 21345ngetLogsgetLogs(filter: { fromBlock?: string | number; toBlock?: string | number; address?: string | string[]; topics?: (string | null | string[])[]; blockHash?: string }, chainId?: number): Promise<Log[]>Fetches event logs matching the given filter. Use blockHash to target a specific block (cannot combine with fromBlock/toBlock).
// ERC-20 Transfer events on Base
const logs = await kn.getLogs({
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'],
fromBlock: 'latest',
}, CHAINS.BASE.chainId);simulateTransactionsimulateTransaction(tx: { to?: string; from?: string; data?: string; value?: string }, block?: string | number, chainId?: number): Promise<{ success: boolean; result: string; gasEstimate: bigint }>Runs a transaction in a sandboxed simulation. Returns whether it would succeed, the return data, and an accurate gas estimate. Useful for pre-validating transactions before broadcasting.
const sim = await kn.simulateTransaction({ to: "0xabc...", data: "0x..." });
if (!sim.success) throw new Error("would revert");getTokenBalancesgetTokenBalances(owner: string, tokens: string[], chainId?: number): Promise<{ token: string; balance: bigint }[]>Fetches ERC-20 balances for multiple tokens in a single batched RPC call.
const balances = await kn.getTokenBalances("0xOwner...", [
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
"0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
]);
// [{ token: "0xA0b8...", balance: 1000000n }, { token: "0xdAC1...", balance: 500000n }]sendRawTransactionsendRawTransaction(signedHex: string, chainId?: number): Promise<string>
Broadcasts a signed transaction. Returns the transaction hash. Sign transactions with ethers.js or viem before passing here.
// Sign with ethers and broadcast via KuberNodes
import { ethers } from "ethers";
const wallet = new ethers.Wallet(privateKey);
const signed = await wallet.signTransaction({ to: "0x...", value: ethers.parseEther("0.01"), ... });
const txHash = await kn.sendRawTransaction(signed);waitForTransactionwaitForTransaction(txHash: string, confirmations?: number, timeoutMs?: number, chainId?: number): Promise<TransactionReceipt>
Polls until the transaction is confirmed. Throws if the transaction reverts (status "0x0") or if timeoutMs is exceeded. Default: 1 confirmation, 120 second timeout.
const txHash = await kn.sendRawTransaction(signed);
const receipt = await kn.waitForTransaction(txHash, 3); // 3 confirmations
console.log("confirmed at block", receipt.blockNumber);sendBatchsendBatch<T>(requests: { method: string; params?: unknown[] }[], chainId?: number): Promise<T[]>Sends multiple JSON-RPC requests in a single HTTP round trip. Returns results in the same order as the requests.
const [blockNum, gasPrice] = await kn.sendBatch<[number, string]>([
{ method: "eth_blockNumber" },
{ method: "eth_gasPrice" },
]);sendsend<T>(method: string, params?: unknown[], chainId?: number): Promise<T>
Raw JSON-RPC call. Use for methods not yet exposed as typed helpers.
const feeHistory = await kn.send<{ baseFeePerGas: string[] }>(
"eth_feeHistory",
["0x4", "latest", [25, 75]],
);chainchain(chainId: number): KuberNodes
Returns a new client instance bound to a specific chain. Useful when calling multiple chains in the same flow without repeating the chainId argument.
const eth = kn.chain(1); const base = kn.chain(CHAINS.BASE.chainId); const [ethBlock, baseBlock] = await Promise.all([ eth.getBlockNumber(), base.getBlockNumber(), ]);
export interface Block {
hash: string;
parentHash: string;
number: number;
timestamp: number; // Unix seconds
nonce: string;
gasLimit: bigint;
gasUsed: bigint;
miner: string;
baseFeePerGas?: bigint; // EIP-1559 chains only
transactions: string[] | Transaction[];
uncles: string[];
}
export interface Transaction {
hash: string;
blockHash: string | null;
blockNumber: number | null;
transactionIndex: number | null;
from: string;
to: string | null; // null for contract deployments
value: bigint;
gas: bigint;
gasPrice: bigint;
maxFeePerGas?: bigint; // EIP-1559
maxPriorityFeePerGas?: bigint;
input: string;
nonce: number;
type: string;
chainId?: number;
r: string;
s: string;
v: string;
}
export interface TransactionReceipt {
transactionHash: string;
blockHash: string;
blockNumber: number;
transactionIndex: number;
from: string;
to: string | null;
contractAddress: string | null; // non-null for deployments
gasUsed: bigint;
cumulativeGasUsed: bigint;
effectiveGasPrice: bigint;
logs: Log[];
logsBloom: string;
status: '0x0' | '0x1'; // 0x0 = reverted, 0x1 = success
type: string;
}
export interface Log {
address: string;
topics: string[];
data: string;
blockNumber: number;
blockHash: string;
transactionHash: string;
transactionIndex: number;
logIndex: number;
removed: boolean;
}import { Kuber, CHAINS } from 'kubernodes';
const kuber = new Kuber(process.env.KUBERNODES_API_KEY!);
// Chain-scoped instances
const eth = kuber.chain(CHAINS.ETHEREUM.chainId);
const base = kuber.chain(CHAINS.BASE.chainId);
const arb = kuber.chain(CHAINS.ARB_ONE.chainId);
// Parallel reads across chains
const [ethBlock, baseBlock, arbBlock] = await Promise.all([
eth.getBlockNumber(),
base.getBlockNumber(),
arb.getBlockNumber(),
]);
// Per-call override — no new instance needed
const polygon = await kuber.getBalance("0x...", "latest", CHAINS.POLYGON.chainId);