quicknode-solana-kit
v1.0.4
Published
Unified TypeScript SDK for all QuickNode Solana add-ons — Priority Fees, Jito, Metaplex DAS, Jupiter, Yellowstone
Maintainers
Readme
quicknode-solana-kit
Typed Solana SDK for QuickNode endpoints and QuickNode-powered add-ons.
This package gives you one place to work with:
- standard Solana RPC
- standard Solana WebSocket subscriptions
- QuickNode custom JSON-RPC methods
- QuickNode REST add-ons mounted on the same endpoint
If your current Solana setup looks like this:
import { Connection } from '@solana/web3.js';
const connection = new Connection(
'https://your-endpoint.quiknode.pro/TOKEN/',
'confirmed',
);then quicknode-solana-kit is the layer on top of that.
It still uses a normal Solana Connection, but adds typed helper methods for common QuickNode add-ons and transaction workflows.
npm install quicknode-solana-kitWhat This Package Is
This package is a wrapper around three patterns:
- normal Solana
Connectioncalls from@solana/web3.js - QuickNode custom RPC methods such as
qn_estimatePriorityFees - QuickNode REST endpoints such as
/jupiter/v6/quote
It does not replace Solana RPC. It organizes it.
You get:
kit.connectionfor normal Solana callskit.someMethod()for QuickNode helper methods
Example:
import { QNSolanaKit } from 'quicknode-solana-kit';
const kit = new QNSolanaKit({
endpointUrl: 'https://your-endpoint.quiknode.pro/TOKEN/',
});
const slot = await kit.connection.getSlot();
console.log(slot);Install
npm install quicknode-solana-kitRequirements:
- Node.js 18+
- a QuickNode Solana endpoint
Quick Start
1. Create the kit
import { QNSolanaKit } from 'quicknode-solana-kit';
const kit = new QNSolanaKit({
endpointUrl: 'https://your-endpoint.quiknode.pro/TOKEN/',
commitment: 'confirmed',
timeout: 30_000,
addOns: {
priorityFees: true,
das: true,
metis: false,
yellowstone: false,
liljit: false,
pumpfun: false,
stablecoinBalance: false,
openocean: false,
merkle: false,
blinklabs: false,
iris: false,
goldrush: false,
titan: false,
scorechain: false,
},
});2. Use normal Solana methods
import { PublicKey } from '@solana/web3.js';
const wallet = new PublicKey('E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk');
const balance = await kit.connection.getBalance(wallet);
const slot = await kit.connection.getSlot();
const blockhash = await kit.connection.getLatestBlockhash();
console.log(balance, slot, blockhash.blockhash);3. Use kit helper methods
const tokenAccounts = await kit.getTokenAccounts(wallet.toString());
console.log(tokenAccounts.length);4. Check which add-ons are live
const status = await kit.checkAddOns();
console.log(status.addOns);
console.log(status.canUse);CLI:
npm run checkCan You Still Use Built-In Solana Connection Methods?
Yes.
This is one of the most important points in the whole package.
kit.connection is a real Connection instance from @solana/web3.js.
That means you can still use methods like:
const version = await kit.connection.getVersion();
const slot = await kit.connection.getSlot();
const balance = await kit.connection.getBalance(walletPublicKey);
const blockhash = await kit.connection.getLatestBlockhash();
const tx = await kit.connection.getTransaction(signature, {
maxSupportedTransactionVersion: 0,
});So the mental model is:
kit.connection= normal Solana SDK accesskit.someMethod()= helper wrapper provided by this package
Add-On Model
Some methods work without add-ons.
Some methods require a specific QuickNode add-on.
This package handles add-ons in two ways:
1. Local config guard
You tell the SDK what you believe is enabled:
const kit = new QNSolanaKit({
endpointUrl: process.env.QN_ENDPOINT_URL!,
addOns: {
priorityFees: true,
das: true,
metis: false,
},
});If you explicitly set an add-on to false and call a method that needs it, the SDK throws an AddOnNotEnabledError.
If a value is left undefined, the SDK warns and still attempts the network call.
2. Real endpoint probe
checkAddOns() performs real test calls to your endpoint and tells you what is actually live.
const result = await kit.checkAddOns();
console.log(result.canUse.smartTransactions);
console.log(result.canUse.nftQueries);
console.log(result.canUse.swaps);
console.log(result.canUse.goldRushData);
console.log(result.canUse.riskAssessment);How This SDK Talks To QuickNode
There are three backend styles used in this package.
1. Standard Solana RPC
Example:
await kit.connection.getBalance(pubkey);2. QuickNode Custom JSON-RPC
Example:
await kit.estimatePriorityFees();Internally, that becomes a JSON-RPC request similar to:
{
"jsonrpc": "2.0",
"id": 1,
"method": "qn_estimatePriorityFees",
"params": {
"last_n_blocks": 100,
"api_version": 2
}
}3. QuickNode REST Add-On Route
Example:
await kit.getSwapQuote({
inputMint: TOKENS.SOL,
outputMint: TOKENS.USDC,
amount: BigInt(1_000_000_000),
});Internally, that calls a route like:
https://your-endpoint.quiknode.pro/TOKEN/jupiter/v6/quote?...Full Method Count
The QNSolanaKit class currently exposes 33 methods.
They are:
checkAddOns()sendSmartTransaction()prepareSmartTransaction()estimatePriorityFees()getAssetsByOwner()getAsset()getAssetsByCollection()searchAssets()getAssetProof()getTokenAccounts()watchAccount()watchProgram()watchSlot()getSwapQuote()swap()getPumpFunTokens()getPumpFunToken()getPumpFunTokensByCreator()getPumpFunTokenHolders()getPumpFunTokenTrades()getStablecoinBalance()getOpenOceanQuote()openOceanSwap()sendMerkleProtectedTransaction()sendBlinkLabsTransaction()sendIrisTransaction()getGoldRushBalances()getGoldRushTransactions()getTitanSwapQuote()titanSwap()subscribeTitanQuotes()assessWalletRisk()isWalletSafe()
Also important:
kit.connectionis a property, not a method- but it gives you access to normal Solana
Connectionmethods
Add-On Requirements Table
| Method | What it does | Add-on needed? | Add-on name |
|---|---|---|---|
| checkAddOns() | probes endpoint capabilities | No | none |
| sendSmartTransaction() | sends a tx with fee/compute helpers | No, but better with add-on | priorityFees recommended |
| prepareSmartTransaction() | prepares a tx with fee/compute helpers | No, but better with add-on | priorityFees recommended |
| estimatePriorityFees() | gets live priority fee estimates | Yes | priorityFees |
| getAssetsByOwner() | gets wallet assets | Yes | das |
| getAsset() | gets one digital asset | Yes | das |
| getAssetsByCollection() | gets assets by collection | Yes | das |
| searchAssets() | searches digital assets | Yes | das |
| getAssetProof() | gets compressed NFT proof | Yes | das |
| getTokenAccounts() | gets SPL token accounts | No | none |
| watchAccount() | watches one account | No | none |
| watchProgram() | watches program logs | No | none |
| watchSlot() | watches slot changes | No | none |
| getSwapQuote() | gets Jupiter quote | Yes | metis |
| swap() | performs Jupiter swap | Yes | metis |
| getPumpFunTokens() | gets recent pump.fun tokens | Yes | pumpfun |
| getPumpFunToken() | gets one pump.fun token | Yes | pumpfun |
| getPumpFunTokensByCreator() | gets pump.fun tokens by creator | Yes | pumpfun |
| getPumpFunTokenHolders() | gets token holders | Yes | pumpfun |
| getPumpFunTokenTrades() | gets recent token trades | Yes | pumpfun |
| getStablecoinBalance() | gets stablecoin balances across chains | Yes | stablecoinBalance |
| getOpenOceanQuote() | gets OpenOcean quote | Yes | openocean |
| openOceanSwap() | performs OpenOcean swap | Yes | openocean |
| sendMerkleProtectedTransaction() | sends tx through Merkle | Yes | merkle |
| sendBlinkLabsTransaction() | sends tx through Blink Labs | Yes | blinklabs |
| sendIrisTransaction() | sends tx through Iris | Yes | iris |
| getGoldRushBalances() | gets balances through GoldRush | Yes | goldrush |
| getGoldRushTransactions() | gets tx history through GoldRush | Yes | goldrush |
| getTitanSwapQuote() | gets Titan quote | Yes | titan |
| titanSwap() | performs Titan swap | Yes | titan |
| subscribeTitanQuotes() | subscribes to Titan quote stream | Yes | titan |
| assessWalletRisk() | gets Scorechain risk report | Yes | scorechain |
| isWalletSafe() | returns simple safe/unsafe boolean | Yes | scorechain |
Which Features Need No Add-On?
These work without add-ons:
checkAddOns()sendSmartTransaction()with fallback behaviorprepareSmartTransaction()with fallback behaviorgetTokenAccounts()watchAccount()watchProgram()watchSlot()- all built-in
kit.connection.*methods
Which Add-On Unlocks What?
priorityFees
Unlocks:
estimatePriorityFees()- improved
sendSmartTransaction() - improved
prepareSmartTransaction()
das
Unlocks:
getAssetsByOwner()getAsset()getAssetsByCollection()searchAssets()getAssetProof()
metis
Unlocks:
getSwapQuote()swap()
pumpfun
Unlocks:
getPumpFunTokens()getPumpFunToken()getPumpFunTokensByCreator()getPumpFunTokenHolders()getPumpFunTokenTrades()
stablecoinBalance
Unlocks:
getStablecoinBalance()
openocean
Unlocks:
getOpenOceanQuote()openOceanSwap()
merkle
Unlocks:
sendMerkleProtectedTransaction()
blinklabs
Unlocks:
sendBlinkLabsTransaction()
iris
Unlocks:
sendIrisTransaction()
goldrush
Unlocks:
getGoldRushBalances()getGoldRushTransactions()
titan
Unlocks:
getTitanSwapQuote()titanSwap()subscribeTitanQuotes()
scorechain
Unlocks:
assessWalletRisk()isWalletSafe()
API Reference
checkAddOns()
Checks which add-ons are actually enabled on your endpoint.
Add-on required: none
const result = await kit.checkAddOns();
console.log(result.addOns);
console.log(result.canUse.smartTransactions);
console.log(result.canUse.nftQueries);
console.log(result.canUse.swaps);How it works:
- performs real probe calls to your endpoint
- tests both RPC-based and REST-based add-ons
- returns a structured capability report
sendSmartTransaction({ transaction, signer, options })
Sends a transaction with helper logic for compute units, priority fees, and retry behavior.
Add-on required: none, but priorityFees is strongly recommended
import bs58 from 'bs58';
import {
Keypair,
LAMPORTS_PER_SOL,
SystemProgram,
Transaction,
} from '@solana/web3.js';
const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: signer.publicKey,
toPubkey: signer.publicKey,
lamports: Math.floor(0.001 * LAMPORTS_PER_SOL),
}),
);
const result = await kit.sendSmartTransaction({
transaction: tx,
signer,
options: {
feeLevel: 'recommended',
simulateFirst: true,
maxRetries: 5,
computeUnitBuffer: 10,
skipPreflight: false,
},
});
console.log(result.signature);
console.log(result.slot);
console.log(result.priorityFeeMicroLamports);
console.log(result.computeUnitsUsed);
console.log(result.confirmationMs);What it does internally:
- optionally simulates the transaction
- estimates compute units
- tries to fetch priority fee recommendations
- injects compute budget instructions
- gets a blockhash
- signs the transaction
- sends raw transaction
- confirms it
- retries on failure
Important note:
- if fee estimation fails, it falls back to a default compute unit price
useJitoexists in options, but Jito routing is not currently wired into this method
prepareSmartTransaction({ transaction, payer, options })
Prepares a transaction but does not send it.
Add-on required: none, but priorityFees is strongly recommended
This is useful for wallet-adapter flows.
const prepared = await kit.prepareSmartTransaction({
transaction: myTx,
payer: wallet.publicKey,
options: {
feeLevel: 'high',
computeUnitBuffer: 10,
},
});
console.log(prepared.priorityFeeMicroLamports);
console.log(prepared.computeUnits);
const sig = await wallet.sendTransaction(prepared.transaction, kit.connection);
console.log(sig);How it works:
- gets priority fee if available
- adds compute budget instructions
- fetches a recent blockhash
- sets the fee payer
- returns the prepared transaction
estimatePriorityFees(options?)
Gets live priority fee estimates from QuickNode.
Add-on required: priorityFees
const fees = await kit.estimatePriorityFees({
lastNBlocks: 100,
});
console.log(fees.low);
console.log(fees.medium);
console.log(fees.recommended);
console.log(fees.high);
console.log(fees.extreme);
console.log(fees.networkCongestion);With account filter:
const fees = await kit.estimatePriorityFees({
account: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',
lastNBlocks: 50,
});How it works:
- calls QuickNode custom RPC method
qn_estimatePriorityFees - maps response to fee levels
getAssetsByOwner(options)
Gets digital assets owned by a wallet.
Add-on required: das
const assets = await kit.getAssetsByOwner({
ownerAddress: 'WALLET_ADDRESS',
limit: 10,
page: 1,
});
console.log(assets.total);
for (const item of assets.items) {
console.log(item.id);
console.log(item.content.metadata.name);
console.log(item.ownership.owner);
console.log(item.compression?.compressed);
}How it works:
- calls DAS RPC method
getAssetsByOwner
getAsset(mintAddress)
Gets one digital asset.
Add-on required: das
const asset = await kit.getAsset('ASSET_ID_OR_MINT');
console.log(asset.id);
console.log(asset.content.metadata.name);
console.log(asset.content.metadata.symbol);
console.log(asset.content.metadata.image);How it works:
- calls DAS RPC method
getAsset
getAssetsByCollection(options)
Gets assets by collection.
Add-on required: das
const collectionAssets = await kit.getAssetsByCollection({
collectionMint: 'COLLECTION_MINT',
limit: 20,
page: 1,
});
console.log(collectionAssets.total);How it works:
- calls DAS RPC method
getAssetsByGroup - uses collection grouping
searchAssets(options)
Searches digital assets with filters.
Add-on required: das
By owner:
const result = await kit.searchAssets({
ownerAddress: 'WALLET_ADDRESS',
limit: 25,
});By creator:
const result = await kit.searchAssets({
creatorAddress: 'CREATOR_ADDRESS',
limit: 25,
});By collection:
const result = await kit.searchAssets({
collection: 'COLLECTION_MINT',
limit: 25,
});Compressed NFTs only:
const result = await kit.searchAssets({
tokenType: 'compressedNFT',
compressed: true,
limit: 25,
});How it works:
- builds a DAS search request
- calls DAS RPC method
searchAssets
getAssetProof(assetId)
Gets the Merkle proof for a compressed NFT.
Add-on required: das
const proof = await kit.getAssetProof('ASSET_ID');
console.log(proof.root);
console.log(proof.proof);
console.log(proof.tree_id);How it works:
- calls DAS RPC method
getAssetProof
getTokenAccounts(walletAddress)
Gets SPL token accounts and balances for a wallet.
Add-on required: none
const tokens = await kit.getTokenAccounts('WALLET_ADDRESS');
for (const token of tokens) {
if (token.uiAmount > 0) {
console.log(token.mint, token.uiAmount);
}
}How it works:
- calls normal Solana RPC method
getTokenAccountsByOwner - uses
jsonParsedencoding
watchAccount(address, onUpdate, options?)
Watches an account in real time.
Add-on required: none
const handle = kit.watchAccount('WALLET_ADDRESS', (update) => {
console.log(update.pubkey);
console.log(update.lamports);
console.log(update.owner);
console.log(update.slot);
console.log(update.backend);
});
setTimeout(() => {
console.log(handle.isConnected());
handle.unsubscribe();
}, 15000);How it works:
- uses Solana websocket subscriptions through
Connection - if
yellowstoneis set, the code prefers that route - current implementation falls back to standard websocket behavior
watchProgram(programId, onTx, options?)
Watches program logs in real time.
Add-on required: none
const handle = kit.watchProgram(
'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',
(tx) => {
console.log(tx.signature);
console.log(tx.logs);
console.log(tx.err);
},
);How it works:
- uses
connection.onLogs(...)
watchSlot(onSlot)
Watches slot changes.
Add-on required: none
const handle = kit.watchSlot((slot) => {
console.log(slot);
});
setTimeout(() => handle.unsubscribe(), 10000);How it works:
- uses
connection.onSlotChange(...)
getSwapQuote(options)
Gets a Jupiter quote through the Metis add-on.
Add-on required: metis
import { TOKENS } from 'quicknode-solana-kit';
const quote = await kit.getSwapQuote({
inputMint: TOKENS.SOL,
outputMint: TOKENS.USDC,
amount: BigInt(1_000_000_000),
slippageBps: 50,
});
console.log(quote.inAmount);
console.log(quote.outAmount);
console.log(quote.priceImpactPct);
console.log(quote.routePlan);How it works:
- calls REST route
/jupiter/v6/quote
swap(options)
Performs a Jupiter swap through Metis.
Add-on required: metis
import bs58 from 'bs58';
import { Keypair } from '@solana/web3.js';
import { TOKENS } from 'quicknode-solana-kit';
const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
const result = await kit.swap({
inputMint: TOKENS.SOL,
outputMint: TOKENS.USDC,
amount: BigInt(10_000_000),
userPublicKey: signer.publicKey.toString(),
signer,
slippageBps: 100,
feeLevel: 'recommended',
});
console.log(result.signature);
console.log(result.inputAmount);
console.log(result.outputAmount);
console.log(result.priceImpactPct);How it works:
- gets a quote
- requests a serialized swap transaction
- deserializes the base64 transaction
- signs locally
- sends with normal Solana connection
- confirms the result
getPumpFunTokens(options?)
Gets recent pump.fun tokens.
Add-on required: pumpfun
const tokens = await kit.getPumpFunTokens({
limit: 10,
offset: 0,
includeNsfw: false,
});
for (const token of tokens) {
console.log(token.mint, token.symbol, token.marketCapSol);
}How it works:
- calls REST route
/pump-fun/coins
getPumpFunToken(mint)
Gets a single pump.fun token by mint.
Add-on required: pumpfun
const token = await kit.getPumpFunToken('TOKEN_MINT');
console.log(token.name);
console.log(token.symbol);
console.log(token.creator);
console.log(token.price);How it works:
- calls REST route
/pump-fun/coins/:mint
getPumpFunTokensByCreator(options)
Gets pump.fun tokens by creator wallet.
Add-on required: pumpfun
const created = await kit.getPumpFunTokensByCreator({
creator: 'CREATOR_WALLET',
limit: 20,
offset: 0,
});How it works:
- calls
/pump-fun/coins?creator=...
getPumpFunTokenHolders(mint)
Gets holder distribution for a token.
Add-on required: pumpfun
const holders = await kit.getPumpFunTokenHolders('TOKEN_MINT');
for (const holder of holders.slice(0, 10)) {
console.log(holder.address, holder.balance, holder.percentage);
}How it works:
- calls REST route
/pump-fun/coins/:mint/holders
getPumpFunTokenTrades(mint, options?)
Gets recent trades for a token.
Add-on required: pumpfun
const trades = await kit.getPumpFunTokenTrades('TOKEN_MINT', {
limit: 25,
offset: 0,
});
for (const trade of trades) {
console.log(trade.signature, trade.isBuy, trade.solAmount, trade.tokenAmount);
}How it works:
- calls REST route
/pump-fun/trades/all
getStablecoinBalance(options)
Gets stablecoin balances across multiple chains.
Add-on required: stablecoinBalance
const balances = await kit.getStablecoinBalance({
walletAddress: 'WALLET_ADDRESS',
chains: ['solana', 'ethereum', 'base'],
});
console.log(balances.totalUsdValue);
for (const balance of balances.balances) {
console.log(balance.chain, balance.symbol, balance.balance, balance.usdValue);
}How it works:
- calls custom RPC method
qn_getWalletStablecoinBalances
getOpenOceanQuote(options)
Gets a swap quote from OpenOcean.
Add-on required: openocean
const quote = await kit.getOpenOceanQuote({
inTokenAddress: 'So11111111111111111111111111111111111111112',
outTokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: '1000000000',
slippage: 1,
});
console.log(quote.inAmount);
console.log(quote.outAmount);
console.log(quote.minOutAmount);
console.log(quote.priceImpact);How it works:
- calls REST route
/openocean/v4/solana/quote
openOceanSwap(options)
Performs a swap through OpenOcean.
Add-on required: openocean
import bs58 from 'bs58';
import { Keypair } from '@solana/web3.js';
const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
const result = await kit.openOceanSwap({
inTokenAddress: 'So11111111111111111111111111111111111111112',
outTokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: '10000000',
slippage: 1,
userAddress: signer.publicKey.toString(),
signer,
});
console.log(result.signature);
console.log(result.inAmount);
console.log(result.outAmount);How it works:
- requests serialized transaction from add-on
- decodes base64 transaction
- signs locally
- sends using normal Solana connection
- confirms it
sendMerkleProtectedTransaction(options)
Sends a signed transaction through Merkle for MEV protection.
Add-on required: merkle
const result = await kit.sendMerkleProtectedTransaction({
serializedTransaction: signedTxBase64,
tipLamports: 10_000,
});
console.log(result.signature);
console.log(result.provider);How it works:
- calls custom RPC method
mev_sendTransaction - confirms with normal Solana connection
sendBlinkLabsTransaction(options)
Sends a signed transaction through Blink Labs.
Add-on required: blinklabs
const result = await kit.sendBlinkLabsTransaction({
serializedTransaction: signedTxBase64,
tipLamports: 5_000,
});
console.log(result.signature);
console.log(result.provider);How it works:
- calls custom RPC method
blinklabs_sendTransaction - confirms with normal Solana connection
sendIrisTransaction(options)
Sends a signed transaction through the Iris add-on.
Add-on required: iris
const result = await kit.sendIrisTransaction({
serializedTransaction: signedTxBase64,
skipPreflight: false,
maxRetries: 3,
});
console.log(result.signature);
console.log(result.slot);
console.log(result.confirmationMs);How it works:
- calls custom RPC method
iris_sendTransaction - confirms with normal Solana RPC
getGoldRushBalances(options)
Gets multichain balances through GoldRush.
Add-on required: goldrush
const balances = await kit.getGoldRushBalances({
walletAddress: 'WALLET_ADDRESS',
chain: 'solana-mainnet',
noSpam: true,
quoteCurrency: 'USD',
});
console.log(balances.chain);
console.log(balances.address);
for (const item of balances.items) {
console.log(item.symbol, item.balance, item.usdBalance);
}How it works:
- calls REST route under
/goldrush/v1/
getGoldRushTransactions(options)
Gets multichain transaction history through GoldRush.
Add-on required: goldrush
const txs = await kit.getGoldRushTransactions({
walletAddress: 'WALLET_ADDRESS',
chain: 'solana-mainnet',
pageSize: 25,
pageNumber: 0,
});
for (const tx of txs.items) {
console.log(tx.txHash, tx.successful, tx.value);
}How it works:
- calls REST route under
/goldrush/v1/
getTitanSwapQuote(options)
Gets a swap quote from Titan.
Add-on required: titan
const quote = await kit.getTitanSwapQuote({
inputMint: 'So11111111111111111111111111111111111111112',
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: '1000000000',
slippageBps: 50,
});
console.log(quote.inAmount);
console.log(quote.outAmount);
console.log(quote.routes);How it works:
- calls REST route
/titan/v1/quote
titanSwap(options)
Performs a swap through Titan.
Add-on required: titan
const result = await kit.titanSwap({
inputMint: 'So11111111111111111111111111111111111111112',
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: '10000000',
slippageBps: 50,
userPublicKey: 'WALLET_PUBLIC_KEY',
});
console.log(result.signature);
console.log(result.inAmount);
console.log(result.outAmount);How it works:
- gets a Titan quote
- requests a serialized transaction
- deserializes it
- sends it through normal Solana connection
- confirms it
subscribeTitanQuotes(options, onQuote, onError?)
Subscribes to live quote updates from Titan over WebSocket.
Add-on required: titan
const unsubscribe = kit.subscribeTitanQuotes(
{
inputMint: 'So11111111111111111111111111111111111111112',
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: '1000000000',
slippageBps: 50,
},
(quote) => {
console.log('quote', quote.outAmount);
},
(err) => {
console.error(err);
},
);
setTimeout(() => unsubscribe(), 15000);How it works:
- opens a WebSocket to the Titan stream route on your endpoint
assessWalletRisk(options)
Gets Scorechain risk information for a wallet.
Add-on required: scorechain
const assessment = await kit.assessWalletRisk({
address: 'WALLET_ADDRESS',
network: 'solana',
});
console.log(assessment.address);
console.log(assessment.riskScore);
console.log(assessment.riskLevel);
console.log(assessment.amlStatus);
console.log(assessment.flags);How it works:
- calls REST route
/scorechain/v1/risk
isWalletSafe(address)
Returns a simple safe/unsafe boolean using Scorechain.
Add-on required: scorechain
This returns true only when:
amlStatus === 'clean'riskLevel === 'low'
const safe = await kit.isWalletSafe('WALLET_ADDRESS');
console.log(safe);How it works:
- first calls
assessWalletRisk() - then applies a simple clean + low-risk check
Token Constants
TOKENS
Useful for Jupiter / Metis examples.
import { TOKENS } from 'quicknode-solana-kit';
console.log(TOKENS.SOL);
console.log(TOKENS.USDC);
console.log(TOKENS.USDT);
console.log(TOKENS.BONK);
console.log(TOKENS.JUP);
console.log(TOKENS.RAY);
console.log(TOKENS.WIF);OO_TOKENS
Useful for OpenOcean examples.
import { OO_TOKENS } from 'quicknode-solana-kit';
console.log(OO_TOKENS.SOL);
console.log(OO_TOKENS.USDC);
console.log(OO_TOKENS.USDT);
console.log(OO_TOKENS.BONK);Error Handling
The package exports custom errors:
AddOnNotEnabledErrorTransactionFailedErrorTransactionTimeoutErrorMaxRetriesExceededErrorInvalidEndpointErrorRPCError
Example:
import {
AddOnNotEnabledError,
RPCError,
TransactionFailedError,
MaxRetriesExceededError,
} from 'quicknode-solana-kit';
try {
await kit.sendSmartTransaction({ transaction, signer });
} catch (err) {
if (err instanceof AddOnNotEnabledError) {
console.error('Enable the missing add-on in QuickNode and update kit config.');
} else if (err instanceof TransactionFailedError) {
console.error('On-chain failure:', err.signature, err.reason);
} else if (err instanceof MaxRetriesExceededError) {
console.error('Retries exhausted:', err.maxRetries);
} else if (err instanceof RPCError) {
console.error('RPC error:', err.statusCode, err.message);
} else {
console.error(err);
}
}Included Example Scripts
npm run example:tx
npm run example:nft
npm run example:stream
npm run example:swap
npm run example:allSuggested .env values:
QN_ENDPOINT_URL=
WALLET_PRIVATE_KEY=
WALLET_ADDRESS=
ADDON_PRIORITY_FEES=true
ADDON_DAS=true
ADDON_METIS=true
EXECUTE_SWAP=falseRecommended Learning Order
If you are new to Solana or QuickNode, this order works well:
- create
kit - use
kit.connection.getBalance() - use
kit.getTokenAccounts() - run
kit.checkAddOns() - if
priorityFeesis enabled, trykit.estimatePriorityFees() - if
dasis enabled, trykit.getAssetsByOwner() - if
metisis enabled, trykit.getSwapQuote()
Starter Example
import { PublicKey } from '@solana/web3.js';
import { QNSolanaKit } from 'quicknode-solana-kit';
const kit = new QNSolanaKit({
endpointUrl: process.env.QN_ENDPOINT_URL!,
addOns: {
priorityFees: true,
das: true,
},
});
async function main() {
const wallet = new PublicKey('E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk');
const balance = await kit.connection.getBalance(wallet);
console.log('SOL balance:', balance / 1e9);
const tokenAccounts = await kit.getTokenAccounts(wallet.toString());
console.log('Token accounts:', tokenAccounts.length);
const fees = await kit.estimatePriorityFees();
console.log('Recommended priority fee:', fees.recommended);
const assets = await kit.getAssetsByOwner({
ownerAddress: wallet.toString(),
limit: 5,
});
console.log('Assets:', assets.items.length);
}
main().catch(console.error);Current Limitations
yellowstoneis exposed in config and add-on checks, but account streaming currently falls back to standard Solana WebSocketsliljitis probed bycheckAddOns(), butsendSmartTransaction()does not currently route through Jito bundlessendSmartTransaction()works withoutpriorityFees, but falls back to a default compute unit price- several swap integrations return a serialized transaction that the SDK then signs and sends locally
Beginner Guide
If you want a more beginner-first walkthrough, see:
License
MIT
