quicknode-solana-kit 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +1236 -250
  2. package/dist/addons.d.ts.map +1 -1
  3. package/dist/addons.js +190 -0
  4. package/dist/addons.js.map +1 -1
  5. package/dist/goldrush/index.d.ts +10 -0
  6. package/dist/goldrush/index.d.ts.map +1 -0
  7. package/dist/goldrush/index.js +37 -0
  8. package/dist/goldrush/index.js.map +1 -0
  9. package/dist/index.d.ts +33 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +92 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/iris/index.d.ts +3 -0
  14. package/dist/iris/index.d.ts.map +1 -0
  15. package/dist/iris/index.js +29 -0
  16. package/dist/iris/index.js.map +1 -0
  17. package/dist/mev/index.d.ts +4 -0
  18. package/dist/mev/index.d.ts.map +1 -0
  19. package/dist/mev/index.js +52 -0
  20. package/dist/mev/index.js.map +1 -0
  21. package/dist/openocean/index.d.ts +13 -0
  22. package/dist/openocean/index.d.ts.map +1 -0
  23. package/dist/openocean/index.js +63 -0
  24. package/dist/openocean/index.js.map +1 -0
  25. package/dist/pumpfun/index.d.ts +7 -0
  26. package/dist/pumpfun/index.d.ts.map +1 -0
  27. package/dist/pumpfun/index.js +54 -0
  28. package/dist/pumpfun/index.js.map +1 -0
  29. package/dist/scorechain/index.d.ts +4 -0
  30. package/dist/scorechain/index.d.ts.map +1 -0
  31. package/dist/scorechain/index.js +26 -0
  32. package/dist/scorechain/index.js.map +1 -0
  33. package/dist/stablecoin/index.d.ts +3 -0
  34. package/dist/stablecoin/index.d.ts.map +1 -0
  35. package/dist/stablecoin/index.js +16 -0
  36. package/dist/stablecoin/index.js.map +1 -0
  37. package/dist/titan/index.d.ts +5 -0
  38. package/dist/titan/index.d.ts.map +1 -0
  39. package/dist/titan/index.js +119 -0
  40. package/dist/titan/index.js.map +1 -0
  41. package/dist/types/index.d.ts +234 -0
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/dist/utils/addon-guard.d.ts.map +1 -1
  44. package/dist/utils/addon-guard.js +47 -0
  45. package/dist/utils/addon-guard.js.map +1 -1
  46. package/package.json +1 -1
package/README.md CHANGED
@@ -1,458 +1,1444 @@
1
1
  # quicknode-solana-kit
2
2
 
3
- **The unified TypeScript SDK for every QuickNode Solana add-on.**
3
+ Typed Solana SDK for QuickNode endpoints and QuickNode-powered add-ons.
4
4
 
5
- One install. One config. Priority fees, Jito bundles, NFT queries, Jupiter swaps, and live streaming — all typed, all in one place.
5
+ This package gives you one place to work with:
6
+
7
+ - standard Solana RPC
8
+ - standard Solana WebSocket subscriptions
9
+ - QuickNode custom JSON-RPC methods
10
+ - QuickNode REST add-ons mounted on the same endpoint
11
+
12
+ If your current Solana setup looks like this:
13
+
14
+ ```ts
15
+ import { Connection } from '@solana/web3.js';
16
+
17
+ const connection = new Connection(
18
+ 'https://your-endpoint.quiknode.pro/TOKEN/',
19
+ 'confirmed',
20
+ );
21
+ ```
22
+
23
+ then `quicknode-solana-kit` is the layer on top of that.
24
+
25
+ It still uses a normal Solana `Connection`, but adds typed helper methods for common QuickNode add-ons and transaction workflows.
6
26
 
7
27
  ```bash
8
28
  npm install quicknode-solana-kit
9
29
  ```
10
30
 
11
- ---
31
+ ## What This Package Is
32
+
33
+ This package is a wrapper around three patterns:
34
+
35
+ 1. normal Solana `Connection` calls from `@solana/web3.js`
36
+ 2. QuickNode custom RPC methods such as `qn_estimatePriorityFees`
37
+ 3. QuickNode REST endpoints such as `/jupiter/v6/quote`
38
+
39
+ It does not replace Solana RPC. It organizes it.
12
40
 
13
- ## What Is This?
41
+ You get:
14
42
 
15
- This is an **npm package for Solana developers**.
43
+ - `kit.connection` for normal Solana calls
44
+ - `kit.someMethod()` for QuickNode helper methods
16
45
 
17
- Every developer building on Solana using QuickNode has to wire up each add-on manually — read separate docs pages, figure out separate API shapes, write hundreds of lines of boilerplate glue code. This SDK replaces all of that.
46
+ Example:
18
47
 
19
- **Without this SDK:**
20
48
  ```ts
21
- // ~200 lines of manual code every time:
22
- // - call qn_estimatePriorityFees, parse it
23
- // - figure out which level to pick
24
- // - build SetComputeUnitLimit instruction
25
- // - build SetComputeUnitPrice instruction
26
- // - remove existing compute budget ixs to avoid duplicates
27
- // - simulate to estimate compute units
28
- // - handle retry when blockhash expires
29
- // - confirm and return useful data
49
+ import { QNSolanaKit } from 'quicknode-solana-kit';
50
+
51
+ const kit = new QNSolanaKit({
52
+ endpointUrl: 'https://your-endpoint.quiknode.pro/TOKEN/',
53
+ });
54
+
55
+ const slot = await kit.connection.getSlot();
56
+ console.log(slot);
30
57
  ```
31
58
 
32
- **With this SDK:**
59
+ ## Install
60
+
61
+ ```bash
62
+ npm install quicknode-solana-kit
63
+ ```
64
+
65
+ Requirements:
66
+
67
+ - Node.js 18+
68
+ - a QuickNode Solana endpoint
69
+
70
+ ## Quick Start
71
+
72
+ ### 1. Create the kit
73
+
33
74
  ```ts
34
- const result = await kit.sendSmartTransaction({ transaction, signer });
35
- // That's it. Everything above is handled.
75
+ import { QNSolanaKit } from 'quicknode-solana-kit';
76
+
77
+ const kit = new QNSolanaKit({
78
+ endpointUrl: 'https://your-endpoint.quiknode.pro/TOKEN/',
79
+ commitment: 'confirmed',
80
+ timeout: 30_000,
81
+ addOns: {
82
+ priorityFees: true,
83
+ das: true,
84
+ metis: false,
85
+ yellowstone: false,
86
+ liljit: false,
87
+ pumpfun: false,
88
+ stablecoinBalance: false,
89
+ openocean: false,
90
+ merkle: false,
91
+ blinklabs: false,
92
+ iris: false,
93
+ goldrush: false,
94
+ titan: false,
95
+ scorechain: false,
96
+ },
97
+ });
36
98
  ```
37
99
 
38
- ---
100
+ ### 2. Use normal Solana methods
39
101
 
40
- ## Requirements
102
+ ```ts
103
+ import { PublicKey } from '@solana/web3.js';
41
104
 
42
- - Node.js 18+
43
- - A QuickNode Solana endpoint → **free at [dashboard.quicknode.com](https://dashboard.quicknode.com)**
105
+ const wallet = new PublicKey('E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk');
44
106
 
45
- ---
107
+ const balance = await kit.connection.getBalance(wallet);
108
+ const slot = await kit.connection.getSlot();
109
+ const blockhash = await kit.connection.getLatestBlockhash();
46
110
 
47
- ## Quickstart
111
+ console.log(balance, slot, blockhash.blockhash);
112
+ ```
48
113
 
49
- ### 1. Install
114
+ ### 3. Use kit helper methods
50
115
 
51
- ```bash
52
- npm install quicknode-solana-kit
116
+ ```ts
117
+ const tokenAccounts = await kit.getTokenAccounts(wallet.toString());
118
+ console.log(tokenAccounts.length);
53
119
  ```
54
120
 
55
- ### 2. Get a QuickNode endpoint
121
+ ### 4. Check which add-ons are live
56
122
 
57
- Go to [dashboard.quicknode.com](https://dashboard.quicknode.com) → Create Endpoint → Solana.
58
- Copy the endpoint URL. It looks like:
123
+ ```ts
124
+ const status = await kit.checkAddOns();
125
+ console.log(status.addOns);
126
+ console.log(status.canUse);
59
127
  ```
60
- https://your-name.solana-mainnet.quiknode.pro/YOUR_TOKEN/
128
+
129
+ CLI:
130
+
131
+ ```bash
132
+ npm run check
61
133
  ```
62
134
 
63
- ### 3. (Optional) Enable free add-ons
135
+ ## Can You Still Use Built-In Solana `Connection` Methods?
136
+
137
+ Yes.
64
138
 
65
- In the QuickNode dashboard your endpoint Add-ons tab:
66
- - Enable **Priority Fee API** (free) → unlocks `estimatePriorityFees()` + auto-fees in `sendSmartTransaction()`
67
- - Enable **Metaplex DAS API** (free) → unlocks all NFT query methods
139
+ This is one of the most important points in the whole package.
68
140
 
69
- ### 4. Create the kit
141
+ `kit.connection` is a real `Connection` instance from `@solana/web3.js`.
142
+
143
+ That means you can still use methods like:
70
144
 
71
145
  ```ts
72
- import { QNSolanaKit } from '@quicknode/solana-kit';
146
+ const version = await kit.connection.getVersion();
147
+ const slot = await kit.connection.getSlot();
148
+ const balance = await kit.connection.getBalance(walletPublicKey);
149
+ const blockhash = await kit.connection.getLatestBlockhash();
150
+ const tx = await kit.connection.getTransaction(signature, {
151
+ maxSupportedTransactionVersion: 0,
152
+ });
153
+ ```
73
154
 
74
- const kit = new QNSolanaKit({
75
- endpointUrl: 'https://your-name.solana-mainnet.quiknode.pro/TOKEN/',
155
+ So the mental model is:
156
+
157
+ - `kit.connection` = normal Solana SDK access
158
+ - `kit.someMethod()` = helper wrapper provided by this package
159
+
160
+ ## Add-On Model
161
+
162
+ Some methods work without add-ons.
163
+
164
+ Some methods require a specific QuickNode add-on.
165
+
166
+ This package handles add-ons in two ways:
167
+
168
+ ### 1. Local config guard
169
+
170
+ You tell the SDK what you believe is enabled:
76
171
 
77
- // Tell the SDK which add-ons you've enabled.
78
- // The SDK works without any — it just shows helpful messages
79
- // when you call a method that needs an add-on you haven't enabled.
172
+ ```ts
173
+ const kit = new QNSolanaKit({
174
+ endpointUrl: process.env.QN_ENDPOINT_URL!,
80
175
  addOns: {
81
- priorityFees: true, // FREE — Priority Fee API
82
- das: true, // FREE — Metaplex DAS API
83
- metis: false, // PAID — Metis (Jupiter Swap)
84
- liljit: false, // PAID — Lil' JIT (Jito bundles)
85
- yellowstone: false, // PAID — Yellowstone gRPC
176
+ priorityFees: true,
177
+ das: true,
178
+ metis: false,
86
179
  },
87
180
  });
88
181
  ```
89
182
 
90
- ### 5. Check what's available
183
+ If you explicitly set an add-on to `false` and call a method that needs it, the SDK throws an `AddOnNotEnabledError`.
91
184
 
92
- ```bash
93
- # Probes your endpoint and shows exactly which add-ons are active
94
- npm run check
185
+ If a value is left `undefined`, the SDK warns and still attempts the network call.
186
+
187
+ ### 2. Real endpoint probe
188
+
189
+ `checkAddOns()` performs real test calls to your endpoint and tells you what is actually live.
190
+
191
+ ```ts
192
+ const result = await kit.checkAddOns();
193
+
194
+ console.log(result.canUse.smartTransactions);
195
+ console.log(result.canUse.nftQueries);
196
+ console.log(result.canUse.swaps);
197
+ console.log(result.canUse.goldRushData);
198
+ console.log(result.canUse.riskAssessment);
95
199
  ```
96
200
 
97
- Output:
201
+ ## How This SDK Talks To QuickNode
202
+
203
+ There are three backend styles used in this package.
204
+
205
+ ### 1. Standard Solana RPC
206
+
207
+ Example:
208
+
209
+ ```ts
210
+ await kit.connection.getBalance(pubkey);
98
211
  ```
99
- @quicknode/solana-kit — Add-on Status
100
- ──────────────────────────────────────────────────────
101
- Endpoint: https://your-name.solana-mainnet.quiknode.pro...
102
212
 
103
- Priority Fee API [FREE]
104
- enabled — Dynamic priority fee estimation for faster tx inclusion
213
+ ### 2. QuickNode Custom JSON-RPC
105
214
 
106
- ✓ Metaplex DAS API [FREE]
107
- enabled — Query NFTs, compressed NFTs, token metadata
215
+ Example:
108
216
 
109
- ✗ Metis — Jupiter V6 Swap API [PAID]
110
- not enabled — Best-price token swaps via Jupiter aggregator
111
- Enable: https://marketplace.quicknode.com/add-ons/metis-jupiter-v6-swap-api
217
+ ```ts
218
+ await kit.estimatePriorityFees();
219
+ ```
112
220
 
113
- Features Available:
114
- ✓ Smart Transactions (auto fees + retry)
115
- ✓ NFT / Digital Asset Queries
116
- ✗ Jupiter Token Swaps
117
- ✗ Yellowstone gRPC Streaming
118
- ✗ Jito Bundle (MEV protection)
119
- ✓ WebSocket Streaming (slot/account/logs)
221
+ Internally, that becomes a JSON-RPC request similar to:
222
+
223
+ ```json
224
+ {
225
+ "jsonrpc": "2.0",
226
+ "id": 1,
227
+ "method": "qn_estimatePriorityFees",
228
+ "params": {
229
+ "last_n_blocks": 100,
230
+ "api_version": 2
231
+ }
232
+ }
120
233
  ```
121
234
 
122
- ---
235
+ ### 3. QuickNode REST Add-On Route
236
+
237
+ Example:
238
+
239
+ ```ts
240
+ await kit.getSwapQuote({
241
+ inputMint: TOKENS.SOL,
242
+ outputMint: TOKENS.USDC,
243
+ amount: BigInt(1_000_000_000),
244
+ });
245
+ ```
246
+
247
+ Internally, that calls a route like:
248
+
249
+ ```txt
250
+ https://your-endpoint.quiknode.pro/TOKEN/jupiter/v6/quote?...
251
+ ```
252
+
253
+ ## Full Method Count
254
+
255
+ The `QNSolanaKit` class currently exposes **33 methods**.
256
+
257
+ They are:
258
+
259
+ 1. `checkAddOns()`
260
+ 2. `sendSmartTransaction()`
261
+ 3. `prepareSmartTransaction()`
262
+ 4. `estimatePriorityFees()`
263
+ 5. `getAssetsByOwner()`
264
+ 6. `getAsset()`
265
+ 7. `getAssetsByCollection()`
266
+ 8. `searchAssets()`
267
+ 9. `getAssetProof()`
268
+ 10. `getTokenAccounts()`
269
+ 11. `watchAccount()`
270
+ 12. `watchProgram()`
271
+ 13. `watchSlot()`
272
+ 14. `getSwapQuote()`
273
+ 15. `swap()`
274
+ 16. `getPumpFunTokens()`
275
+ 17. `getPumpFunToken()`
276
+ 18. `getPumpFunTokensByCreator()`
277
+ 19. `getPumpFunTokenHolders()`
278
+ 20. `getPumpFunTokenTrades()`
279
+ 21. `getStablecoinBalance()`
280
+ 22. `getOpenOceanQuote()`
281
+ 23. `openOceanSwap()`
282
+ 24. `sendMerkleProtectedTransaction()`
283
+ 25. `sendBlinkLabsTransaction()`
284
+ 26. `sendIrisTransaction()`
285
+ 27. `getGoldRushBalances()`
286
+ 28. `getGoldRushTransactions()`
287
+ 29. `getTitanSwapQuote()`
288
+ 30. `titanSwap()`
289
+ 31. `subscribeTitanQuotes()`
290
+ 32. `assessWalletRisk()`
291
+ 33. `isWalletSafe()`
292
+
293
+ Also important:
294
+
295
+ - `kit.connection` is a property, not a method
296
+ - but it gives you access to normal Solana `Connection` methods
297
+
298
+ ## Add-On Requirements Table
299
+
300
+ | Method | What it does | Add-on needed? | Add-on name |
301
+ |---|---|---|---|
302
+ | `checkAddOns()` | probes endpoint capabilities | No | none |
303
+ | `sendSmartTransaction()` | sends a tx with fee/compute helpers | No, but better with add-on | `priorityFees` recommended |
304
+ | `prepareSmartTransaction()` | prepares a tx with fee/compute helpers | No, but better with add-on | `priorityFees` recommended |
305
+ | `estimatePriorityFees()` | gets live priority fee estimates | Yes | `priorityFees` |
306
+ | `getAssetsByOwner()` | gets wallet assets | Yes | `das` |
307
+ | `getAsset()` | gets one digital asset | Yes | `das` |
308
+ | `getAssetsByCollection()` | gets assets by collection | Yes | `das` |
309
+ | `searchAssets()` | searches digital assets | Yes | `das` |
310
+ | `getAssetProof()` | gets compressed NFT proof | Yes | `das` |
311
+ | `getTokenAccounts()` | gets SPL token accounts | No | none |
312
+ | `watchAccount()` | watches one account | No | none |
313
+ | `watchProgram()` | watches program logs | No | none |
314
+ | `watchSlot()` | watches slot changes | No | none |
315
+ | `getSwapQuote()` | gets Jupiter quote | Yes | `metis` |
316
+ | `swap()` | performs Jupiter swap | Yes | `metis` |
317
+ | `getPumpFunTokens()` | gets recent pump.fun tokens | Yes | `pumpfun` |
318
+ | `getPumpFunToken()` | gets one pump.fun token | Yes | `pumpfun` |
319
+ | `getPumpFunTokensByCreator()` | gets pump.fun tokens by creator | Yes | `pumpfun` |
320
+ | `getPumpFunTokenHolders()` | gets token holders | Yes | `pumpfun` |
321
+ | `getPumpFunTokenTrades()` | gets recent token trades | Yes | `pumpfun` |
322
+ | `getStablecoinBalance()` | gets stablecoin balances across chains | Yes | `stablecoinBalance` |
323
+ | `getOpenOceanQuote()` | gets OpenOcean quote | Yes | `openocean` |
324
+ | `openOceanSwap()` | performs OpenOcean swap | Yes | `openocean` |
325
+ | `sendMerkleProtectedTransaction()` | sends tx through Merkle | Yes | `merkle` |
326
+ | `sendBlinkLabsTransaction()` | sends tx through Blink Labs | Yes | `blinklabs` |
327
+ | `sendIrisTransaction()` | sends tx through Iris | Yes | `iris` |
328
+ | `getGoldRushBalances()` | gets balances through GoldRush | Yes | `goldrush` |
329
+ | `getGoldRushTransactions()` | gets tx history through GoldRush | Yes | `goldrush` |
330
+ | `getTitanSwapQuote()` | gets Titan quote | Yes | `titan` |
331
+ | `titanSwap()` | performs Titan swap | Yes | `titan` |
332
+ | `subscribeTitanQuotes()` | subscribes to Titan quote stream | Yes | `titan` |
333
+ | `assessWalletRisk()` | gets Scorechain risk report | Yes | `scorechain` |
334
+ | `isWalletSafe()` | returns simple safe/unsafe boolean | Yes | `scorechain` |
335
+
336
+ ## Which Features Need No Add-On?
337
+
338
+ These work without add-ons:
339
+
340
+ - `checkAddOns()`
341
+ - `sendSmartTransaction()` with fallback behavior
342
+ - `prepareSmartTransaction()` with fallback behavior
343
+ - `getTokenAccounts()`
344
+ - `watchAccount()`
345
+ - `watchProgram()`
346
+ - `watchSlot()`
347
+ - all built-in `kit.connection.*` methods
348
+
349
+ ## Which Add-On Unlocks What?
350
+
351
+ ### `priorityFees`
352
+
353
+ Unlocks:
354
+
355
+ - `estimatePriorityFees()`
356
+ - improved `sendSmartTransaction()`
357
+ - improved `prepareSmartTransaction()`
358
+
359
+ ### `das`
360
+
361
+ Unlocks:
362
+
363
+ - `getAssetsByOwner()`
364
+ - `getAsset()`
365
+ - `getAssetsByCollection()`
366
+ - `searchAssets()`
367
+ - `getAssetProof()`
368
+
369
+ ### `metis`
370
+
371
+ Unlocks:
372
+
373
+ - `getSwapQuote()`
374
+ - `swap()`
375
+
376
+ ### `pumpfun`
377
+
378
+ Unlocks:
379
+
380
+ - `getPumpFunTokens()`
381
+ - `getPumpFunToken()`
382
+ - `getPumpFunTokensByCreator()`
383
+ - `getPumpFunTokenHolders()`
384
+ - `getPumpFunTokenTrades()`
385
+
386
+ ### `stablecoinBalance`
387
+
388
+ Unlocks:
389
+
390
+ - `getStablecoinBalance()`
391
+
392
+ ### `openocean`
393
+
394
+ Unlocks:
395
+
396
+ - `getOpenOceanQuote()`
397
+ - `openOceanSwap()`
398
+
399
+ ### `merkle`
400
+
401
+ Unlocks:
123
402
 
124
- ## Add-on Tiers
403
+ - `sendMerkleProtectedTransaction()`
125
404
 
126
- | Add-on | Tier | What it unlocks |
127
- |---|---|---|
128
- | Priority Fee API | **FREE** | `estimatePriorityFees()`, auto-fees in `sendSmartTransaction()` |
129
- | Metaplex DAS API | **FREE** | `getAssetsByOwner()`, `getAsset()`, `searchAssets()`, `getAssetProof()` |
130
- | Metis (Jupiter Swap) | **PAID** | `swap()`, `getSwapQuote()` |
131
- | Lil' JIT (Jito) | **PAID** | `sendSmartTransaction({ options: { useJito: true } })` |
132
- | Yellowstone gRPC | **PAID** | `watchAccount()` uses gRPC instead of WebSocket |
405
+ ### `blinklabs`
133
406
 
134
- **Everything except swaps and Jito works on free tier.**
135
- WebSocket streaming (`watchAccount`, `watchProgram`, `watchSlot`) works out of the box with no add-ons.
407
+ Unlocks:
136
408
 
137
- ---
409
+ - `sendBlinkLabsTransaction()`
410
+
411
+ ### `iris`
412
+
413
+ Unlocks:
414
+
415
+ - `sendIrisTransaction()`
416
+
417
+ ### `goldrush`
418
+
419
+ Unlocks:
420
+
421
+ - `getGoldRushBalances()`
422
+ - `getGoldRushTransactions()`
423
+
424
+ ### `titan`
425
+
426
+ Unlocks:
427
+
428
+ - `getTitanSwapQuote()`
429
+ - `titanSwap()`
430
+ - `subscribeTitanQuotes()`
431
+
432
+ ### `scorechain`
433
+
434
+ Unlocks:
435
+
436
+ - `assessWalletRisk()`
437
+ - `isWalletSafe()`
138
438
 
139
439
  ## API Reference
140
440
 
141
- ### `kit.sendSmartTransaction(params)`
441
+ ### `checkAddOns()`
442
+
443
+ Checks which add-ons are actually enabled on your endpoint.
142
444
 
143
- Send a transaction with automatic priority fees, compute unit optimization, and retry.
445
+ Add-on required: none
144
446
 
145
447
  ```ts
448
+ const result = await kit.checkAddOns();
449
+
450
+ console.log(result.addOns);
451
+ console.log(result.canUse.smartTransactions);
452
+ console.log(result.canUse.nftQueries);
453
+ console.log(result.canUse.swaps);
454
+ ```
455
+
456
+ How it works:
457
+
458
+ - performs real probe calls to your endpoint
459
+ - tests both RPC-based and REST-based add-ons
460
+ - returns a structured capability report
461
+
462
+ ### `sendSmartTransaction({ transaction, signer, options })`
463
+
464
+ Sends a transaction with helper logic for compute units, priority fees, and retry behavior.
465
+
466
+ Add-on required: none, but `priorityFees` is strongly recommended
467
+
468
+ ```ts
469
+ import bs58 from 'bs58';
470
+ import {
471
+ Keypair,
472
+ LAMPORTS_PER_SOL,
473
+ SystemProgram,
474
+ Transaction,
475
+ } from '@solana/web3.js';
476
+
477
+ const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
478
+
479
+ const tx = new Transaction().add(
480
+ SystemProgram.transfer({
481
+ fromPubkey: signer.publicKey,
482
+ toPubkey: signer.publicKey,
483
+ lamports: Math.floor(0.001 * LAMPORTS_PER_SOL),
484
+ }),
485
+ );
486
+
146
487
  const result = await kit.sendSmartTransaction({
147
- transaction: myTx, // your @solana/web3.js Transaction
148
- signer: keypair, // Keypair that signs + pays fees
488
+ transaction: tx,
489
+ signer,
149
490
  options: {
150
- feeLevel: 'recommended', // 'low'|'medium'|'recommended'|'high'|'extreme'
151
- useJito: false, // true = Jito bundle (requires liljit add-on)
152
- maxRetries: 5, // retries on blockhash expiry
153
- simulateFirst: true, // simulate to right-size compute units
491
+ feeLevel: 'recommended',
492
+ simulateFirst: true,
493
+ maxRetries: 5,
494
+ computeUnitBuffer: 10,
495
+ skipPreflight: false,
154
496
  },
155
497
  });
156
498
 
157
- console.log(result.signature); // 'abc123...'
158
- console.log(result.slot); // 320481923
159
- console.log(result.priorityFeeMicroLamports); // 5000
160
- console.log(result.computeUnitsUsed); // 12500
161
- console.log(result.confirmationMs); // 843
499
+ console.log(result.signature);
500
+ console.log(result.slot);
501
+ console.log(result.priorityFeeMicroLamports);
502
+ console.log(result.computeUnitsUsed);
503
+ console.log(result.confirmationMs);
162
504
  ```
163
505
 
164
- ---
506
+ What it does internally:
507
+
508
+ 1. optionally simulates the transaction
509
+ 2. estimates compute units
510
+ 3. tries to fetch priority fee recommendations
511
+ 4. injects compute budget instructions
512
+ 5. gets a blockhash
513
+ 6. signs the transaction
514
+ 7. sends raw transaction
515
+ 8. confirms it
516
+ 9. retries on failure
517
+
518
+ Important note:
519
+
520
+ - if fee estimation fails, it falls back to a default compute unit price
521
+ - `useJito` exists in options, but Jito routing is not currently wired into this method
165
522
 
166
- ### `kit.prepareSmartTransaction(params)`
523
+ ### `prepareSmartTransaction({ transaction, payer, options })`
167
524
 
168
- Same as `sendSmartTransaction` but returns the prepared transaction without sending.
169
- **Use this with wallet adapters** (Phantom, Backpack, etc.) where you don't hold the key.
525
+ Prepares a transaction but does not send it.
526
+
527
+ Add-on required: none, but `priorityFees` is strongly recommended
528
+
529
+ This is useful for wallet-adapter flows.
170
530
 
171
531
  ```ts
172
- const { transaction } = await kit.prepareSmartTransaction({
532
+ const prepared = await kit.prepareSmartTransaction({
173
533
  transaction: myTx,
174
- payer: wallet.publicKey,
175
- options: { feeLevel: 'high' },
534
+ payer: wallet.publicKey,
535
+ options: {
536
+ feeLevel: 'high',
537
+ computeUnitBuffer: 10,
538
+ },
176
539
  });
177
540
 
178
- // Pass to wallet adapter:
179
- const sig = await wallet.sendTransaction(transaction, kit.connection);
541
+ console.log(prepared.priorityFeeMicroLamports);
542
+ console.log(prepared.computeUnits);
543
+
544
+ const sig = await wallet.sendTransaction(prepared.transaction, kit.connection);
545
+ console.log(sig);
180
546
  ```
181
547
 
182
- ---
548
+ How it works:
549
+
550
+ - gets priority fee if available
551
+ - adds compute budget instructions
552
+ - fetches a recent blockhash
553
+ - sets the fee payer
554
+ - returns the prepared transaction
555
+
556
+ ### `estimatePriorityFees(options?)`
183
557
 
184
- ### `kit.estimatePriorityFees(options?)`
558
+ Gets live priority fee estimates from QuickNode.
185
559
 
186
- Get current priority fees for all levels.
560
+ Add-on required: `priorityFees`
187
561
 
188
562
  ```ts
189
563
  const fees = await kit.estimatePriorityFees({
190
- account: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4', // optional filter
191
- lastNBlocks: 100,
564
+ lastNBlocks: 100,
192
565
  });
193
566
 
194
- fees.low // 500 µlamports/CU
195
- fees.medium // 1200 µlamports/CU
196
- fees.recommended // 3000 µlamports/CU
197
- fees.high // 8000 µlamports/CU
198
- fees.extreme // 25000 µlamports/CU
199
- fees.networkCongestion // 0.42 (0=quiet, 1=congested)
567
+ console.log(fees.low);
568
+ console.log(fees.medium);
569
+ console.log(fees.recommended);
570
+ console.log(fees.high);
571
+ console.log(fees.extreme);
572
+ console.log(fees.networkCongestion);
573
+ ```
574
+
575
+ With account filter:
576
+
577
+ ```ts
578
+ const fees = await kit.estimatePriorityFees({
579
+ account: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',
580
+ lastNBlocks: 50,
581
+ });
200
582
  ```
201
583
 
202
- ---
584
+ How it works:
203
585
 
204
- ### `kit.getAssetsByOwner(options)`
586
+ - calls QuickNode custom RPC method `qn_estimatePriorityFees`
587
+ - maps response to fee levels
205
588
 
206
- Get all NFTs, cNFTs, and tokens owned by a wallet.
589
+ ### `getAssetsByOwner(options)`
590
+
591
+ Gets digital assets owned by a wallet.
592
+
593
+ Add-on required: `das`
207
594
 
208
595
  ```ts
209
- const { items, total } = await kit.getAssetsByOwner({
210
- ownerAddress: 'WalletAddress',
211
- limit: 50,
212
- sortBy: 'created',
213
- sortDirection: 'desc',
596
+ const assets = await kit.getAssetsByOwner({
597
+ ownerAddress: 'WALLET_ADDRESS',
598
+ limit: 10,
599
+ page: 1,
214
600
  });
215
601
 
216
- items.forEach(asset => {
217
- console.log(asset.content.metadata.name);
218
- console.log(asset.ownership.owner);
219
- console.log(asset.compression?.compressed); // true = cNFT
220
- });
602
+ console.log(assets.total);
603
+
604
+ for (const item of assets.items) {
605
+ console.log(item.id);
606
+ console.log(item.content.metadata.name);
607
+ console.log(item.ownership.owner);
608
+ console.log(item.compression?.compressed);
609
+ }
221
610
  ```
222
611
 
223
- ---
612
+ How it works:
613
+
614
+ - calls DAS RPC method `getAssetsByOwner`
615
+
616
+ ### `getAsset(mintAddress)`
224
617
 
225
- ### `kit.getAsset(mintAddress)`
618
+ Gets one digital asset.
226
619
 
227
- Get a single digital asset by mint address.
620
+ Add-on required: `das`
228
621
 
229
622
  ```ts
230
- const asset = await kit.getAsset('NFTMintAddress');
623
+ const asset = await kit.getAsset('ASSET_ID_OR_MINT');
624
+
625
+ console.log(asset.id);
231
626
  console.log(asset.content.metadata.name);
627
+ console.log(asset.content.metadata.symbol);
232
628
  console.log(asset.content.metadata.image);
233
- console.log(asset.royalty?.basis_points);
234
629
  ```
235
630
 
236
- ---
631
+ How it works:
632
+
633
+ - calls DAS RPC method `getAsset`
634
+
635
+ ### `getAssetsByCollection(options)`
237
636
 
238
- ### `kit.searchAssets(options)`
637
+ Gets assets by collection.
239
638
 
240
- Search with filters: owner, creator, collection, token type.
639
+ Add-on required: `das`
241
640
 
242
641
  ```ts
243
- const { items } = await kit.searchAssets({
244
- ownerAddress: 'WalletAddress',
245
- tokenType: 'compressedNFT', // only cNFTs
246
- limit: 100,
642
+ const collectionAssets = await kit.getAssetsByCollection({
643
+ collectionMint: 'COLLECTION_MINT',
644
+ limit: 20,
645
+ page: 1,
247
646
  });
647
+
648
+ console.log(collectionAssets.total);
248
649
  ```
249
650
 
250
- ---
651
+ How it works:
652
+
653
+ - calls DAS RPC method `getAssetsByGroup`
654
+ - uses collection grouping
655
+
656
+ ### `searchAssets(options)`
251
657
 
252
- ### `kit.getAssetProof(assetId)`
658
+ Searches digital assets with filters.
253
659
 
254
- Get the Merkle proof for a compressed NFT. Required for cNFT transfers via Bubblegum.
660
+ Add-on required: `das`
661
+
662
+ By owner:
255
663
 
256
664
  ```ts
257
- const proof = await kit.getAssetProof('cNFTAssetId');
258
- // proof.root + proof.proof → use with mpl-bubblegum transfer instruction
665
+ const result = await kit.searchAssets({
666
+ ownerAddress: 'WALLET_ADDRESS',
667
+ limit: 25,
668
+ });
669
+ ```
670
+
671
+ By creator:
672
+
673
+ ```ts
674
+ const result = await kit.searchAssets({
675
+ creatorAddress: 'CREATOR_ADDRESS',
676
+ limit: 25,
677
+ });
259
678
  ```
260
679
 
261
- ---
680
+ By collection:
262
681
 
263
- ### `kit.getTokenAccounts(walletAddress)`
682
+ ```ts
683
+ const result = await kit.searchAssets({
684
+ collection: 'COLLECTION_MINT',
685
+ limit: 25,
686
+ });
687
+ ```
264
688
 
265
- Get all SPL token accounts and balances for a wallet.
689
+ Compressed NFTs only:
266
690
 
267
691
  ```ts
268
- const tokens = await kit.getTokenAccounts('WalletAddress');
269
- tokens
270
- .filter(t => t.uiAmount > 0)
271
- .forEach(t => console.log(`${t.mint}: ${t.uiAmount}`));
692
+ const result = await kit.searchAssets({
693
+ tokenType: 'compressedNFT',
694
+ compressed: true,
695
+ limit: 25,
696
+ });
272
697
  ```
273
698
 
274
- ---
699
+ How it works:
275
700
 
276
- ### `kit.watchAccount(address, callback, options?)`
701
+ - builds a DAS search request
702
+ - calls DAS RPC method `searchAssets`
277
703
 
278
- Watch an account for real-time updates. Auto-uses Yellowstone if enabled, WebSocket otherwise.
704
+ ### `getAssetProof(assetId)`
705
+
706
+ Gets the Merkle proof for a compressed NFT.
707
+
708
+ Add-on required: `das`
279
709
 
280
710
  ```ts
281
- const handle = kit.watchAccount('WalletAddress', (update) => {
282
- console.log('SOL balance:', update.lamports / 1e9);
283
- console.log('Backend:', update.backend); // 'yellowstone' or 'websocket'
284
- });
711
+ const proof = await kit.getAssetProof('ASSET_ID');
285
712
 
286
- // Stop watching:
287
- handle.unsubscribe();
288
- handle.isConnected(); // boolean
713
+ console.log(proof.root);
714
+ console.log(proof.proof);
715
+ console.log(proof.tree_id);
289
716
  ```
290
717
 
291
- ---
718
+ How it works:
292
719
 
293
- ### `kit.watchProgram(programId, callback, options?)`
720
+ - calls DAS RPC method `getAssetProof`
294
721
 
295
- Watch all transactions for a program in real time.
722
+ ### `getTokenAccounts(walletAddress)`
723
+
724
+ Gets SPL token accounts and balances for a wallet.
725
+
726
+ Add-on required: none
296
727
 
297
728
  ```ts
298
- const JUPITER = 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4';
729
+ const tokens = await kit.getTokenAccounts('WALLET_ADDRESS');
730
+
731
+ for (const token of tokens) {
732
+ if (token.uiAmount > 0) {
733
+ console.log(token.mint, token.uiAmount);
734
+ }
735
+ }
736
+ ```
737
+
738
+ How it works:
299
739
 
300
- const handle = kit.watchProgram(JUPITER, (tx) => {
301
- if (!tx.err) console.log('Swap:', tx.signature);
740
+ - calls normal Solana RPC method `getTokenAccountsByOwner`
741
+ - uses `jsonParsed` encoding
742
+
743
+ ### `watchAccount(address, onUpdate, options?)`
744
+
745
+ Watches an account in real time.
746
+
747
+ Add-on required: none
748
+
749
+ ```ts
750
+ const handle = kit.watchAccount('WALLET_ADDRESS', (update) => {
751
+ console.log(update.pubkey);
752
+ console.log(update.lamports);
753
+ console.log(update.owner);
754
+ console.log(update.slot);
755
+ console.log(update.backend);
302
756
  });
757
+
758
+ setTimeout(() => {
759
+ console.log(handle.isConnected());
760
+ handle.unsubscribe();
761
+ }, 15000);
303
762
  ```
304
763
 
305
- ---
764
+ How it works:
306
765
 
307
- ### `kit.watchSlot(callback)`
766
+ - uses Solana websocket subscriptions through `Connection`
767
+ - if `yellowstone` is set, the code prefers that route
768
+ - current implementation falls back to standard websocket behavior
308
769
 
309
- Subscribe to slot updates (~every 400ms). Free tier, no add-ons needed.
770
+ ### `watchProgram(programId, onTx, options?)`
771
+
772
+ Watches program logs in real time.
773
+
774
+ Add-on required: none
775
+
776
+ ```ts
777
+ const handle = kit.watchProgram(
778
+ 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',
779
+ (tx) => {
780
+ console.log(tx.signature);
781
+ console.log(tx.logs);
782
+ console.log(tx.err);
783
+ },
784
+ );
785
+ ```
786
+
787
+ How it works:
788
+
789
+ - uses `connection.onLogs(...)`
790
+
791
+ ### `watchSlot(onSlot)`
792
+
793
+ Watches slot changes.
794
+
795
+ Add-on required: none
310
796
 
311
797
  ```ts
312
798
  const handle = kit.watchSlot((slot) => {
313
- process.stdout.write(`\r Slot: ${slot.toLocaleString()}`);
799
+ console.log(slot);
314
800
  });
801
+
802
+ setTimeout(() => handle.unsubscribe(), 10000);
315
803
  ```
316
804
 
317
- ---
805
+ How it works:
806
+
807
+ - uses `connection.onSlotChange(...)`
318
808
 
319
- ### `kit.getSwapQuote(options)` — PAID (Metis)
809
+ ### `getSwapQuote(options)`
320
810
 
321
- Get a Jupiter swap quote without executing.
811
+ Gets a Jupiter quote through the Metis add-on.
812
+
813
+ Add-on required: `metis`
322
814
 
323
815
  ```ts
324
- import { TOKENS } from '@quicknode/solana-kit';
816
+ import { TOKENS } from 'quicknode-solana-kit';
325
817
 
326
818
  const quote = await kit.getSwapQuote({
327
- inputMint: TOKENS.SOL,
819
+ inputMint: TOKENS.SOL,
328
820
  outputMint: TOKENS.USDC,
329
- amount: BigInt(1_000_000_000), // 1 SOL
821
+ amount: BigInt(1_000_000_000),
822
+ slippageBps: 50,
330
823
  });
331
824
 
332
- console.log(`1 SOL → ${Number(quote.outAmount) / 1e6} USDC`);
333
- console.log(`Price impact: ${quote.priceImpactPct}%`);
825
+ console.log(quote.inAmount);
826
+ console.log(quote.outAmount);
827
+ console.log(quote.priceImpactPct);
828
+ console.log(quote.routePlan);
334
829
  ```
335
830
 
336
- ---
831
+ How it works:
832
+
833
+ - calls REST route `/jupiter/v6/quote`
337
834
 
338
- ### `kit.swap(options)` — PAID (Metis)
835
+ ### `swap(options)`
339
836
 
340
- Execute a token swap in one call.
837
+ Performs a Jupiter swap through Metis.
838
+
839
+ Add-on required: `metis`
341
840
 
342
841
  ```ts
842
+ import bs58 from 'bs58';
843
+ import { Keypair } from '@solana/web3.js';
844
+ import { TOKENS } from 'quicknode-solana-kit';
845
+
846
+ const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
847
+
343
848
  const result = await kit.swap({
344
- inputMint: TOKENS.SOL,
345
- outputMint: TOKENS.USDC,
346
- amount: BigInt(100_000_000), // 0.1 SOL
347
- userPublicKey: keypair.publicKey.toString(),
348
- signer: keypair,
349
- slippageBps: 50, // 0.5%
350
- feeLevel: 'recommended',
849
+ inputMint: TOKENS.SOL,
850
+ outputMint: TOKENS.USDC,
851
+ amount: BigInt(10_000_000),
852
+ userPublicKey: signer.publicKey.toString(),
853
+ signer,
854
+ slippageBps: 100,
855
+ feeLevel: 'recommended',
351
856
  });
352
857
 
353
- console.log('Swapped!', result.signature);
858
+ console.log(result.signature);
859
+ console.log(result.inputAmount);
860
+ console.log(result.outputAmount);
861
+ console.log(result.priceImpactPct);
354
862
  ```
355
863
 
356
- Token shortcuts: `TOKENS.SOL`, `TOKENS.USDC`, `TOKENS.USDT`, `TOKENS.BONK`, `TOKENS.JUP`, `TOKENS.RAY`, `TOKENS.WIF`
864
+ How it works:
865
+
866
+ 1. gets a quote
867
+ 2. requests a serialized swap transaction
868
+ 3. deserializes the base64 transaction
869
+ 4. signs locally
870
+ 5. sends with normal Solana connection
871
+ 6. confirms the result
357
872
 
358
- ---
873
+ ### `getPumpFunTokens(options?)`
359
874
 
360
- ### `kit.checkAddOns()`
875
+ Gets recent pump.fun tokens.
361
876
 
362
- Probe your endpoint to see which add-ons are live.
877
+ Add-on required: `pumpfun`
363
878
 
364
879
  ```ts
365
- const status = await kit.checkAddOns();
366
- console.log(status.canUse.smartTransactions); // true/false
367
- console.log(status.canUse.nftQueries); // true/false
368
- console.log(status.addOns); // per-add-on detail
880
+ const tokens = await kit.getPumpFunTokens({
881
+ limit: 10,
882
+ offset: 0,
883
+ includeNsfw: false,
884
+ });
885
+
886
+ for (const token of tokens) {
887
+ console.log(token.mint, token.symbol, token.marketCapSol);
888
+ }
889
+ ```
890
+
891
+ How it works:
892
+
893
+ - calls REST route `/pump-fun/coins`
894
+
895
+ ### `getPumpFunToken(mint)`
896
+
897
+ Gets a single pump.fun token by mint.
898
+
899
+ Add-on required: `pumpfun`
900
+
901
+ ```ts
902
+ const token = await kit.getPumpFunToken('TOKEN_MINT');
903
+
904
+ console.log(token.name);
905
+ console.log(token.symbol);
906
+ console.log(token.creator);
907
+ console.log(token.price);
908
+ ```
909
+
910
+ How it works:
911
+
912
+ - calls REST route `/pump-fun/coins/:mint`
913
+
914
+ ### `getPumpFunTokensByCreator(options)`
915
+
916
+ Gets pump.fun tokens by creator wallet.
917
+
918
+ Add-on required: `pumpfun`
919
+
920
+ ```ts
921
+ const created = await kit.getPumpFunTokensByCreator({
922
+ creator: 'CREATOR_WALLET',
923
+ limit: 20,
924
+ offset: 0,
925
+ });
926
+ ```
927
+
928
+ How it works:
929
+
930
+ - calls `/pump-fun/coins?creator=...`
931
+
932
+ ### `getPumpFunTokenHolders(mint)`
933
+
934
+ Gets holder distribution for a token.
935
+
936
+ Add-on required: `pumpfun`
937
+
938
+ ```ts
939
+ const holders = await kit.getPumpFunTokenHolders('TOKEN_MINT');
940
+
941
+ for (const holder of holders.slice(0, 10)) {
942
+ console.log(holder.address, holder.balance, holder.percentage);
943
+ }
944
+ ```
945
+
946
+ How it works:
947
+
948
+ - calls REST route `/pump-fun/coins/:mint/holders`
949
+
950
+ ### `getPumpFunTokenTrades(mint, options?)`
951
+
952
+ Gets recent trades for a token.
953
+
954
+ Add-on required: `pumpfun`
955
+
956
+ ```ts
957
+ const trades = await kit.getPumpFunTokenTrades('TOKEN_MINT', {
958
+ limit: 25,
959
+ offset: 0,
960
+ });
961
+
962
+ for (const trade of trades) {
963
+ console.log(trade.signature, trade.isBuy, trade.solAmount, trade.tokenAmount);
964
+ }
369
965
  ```
370
966
 
371
- ---
967
+ How it works:
968
+
969
+ - calls REST route `/pump-fun/trades/all`
970
+
971
+ ### `getStablecoinBalance(options)`
972
+
973
+ Gets stablecoin balances across multiple chains.
974
+
975
+ Add-on required: `stablecoinBalance`
976
+
977
+ ```ts
978
+ const balances = await kit.getStablecoinBalance({
979
+ walletAddress: 'WALLET_ADDRESS',
980
+ chains: ['solana', 'ethereum', 'base'],
981
+ });
982
+
983
+ console.log(balances.totalUsdValue);
984
+
985
+ for (const balance of balances.balances) {
986
+ console.log(balance.chain, balance.symbol, balance.balance, balance.usdValue);
987
+ }
988
+ ```
989
+
990
+ How it works:
991
+
992
+ - calls custom RPC method `qn_getWalletStablecoinBalances`
993
+
994
+ ### `getOpenOceanQuote(options)`
995
+
996
+ Gets a swap quote from OpenOcean.
997
+
998
+ Add-on required: `openocean`
999
+
1000
+ ```ts
1001
+ const quote = await kit.getOpenOceanQuote({
1002
+ inTokenAddress: 'So11111111111111111111111111111111111111112',
1003
+ outTokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1004
+ amount: '1000000000',
1005
+ slippage: 1,
1006
+ });
1007
+
1008
+ console.log(quote.inAmount);
1009
+ console.log(quote.outAmount);
1010
+ console.log(quote.minOutAmount);
1011
+ console.log(quote.priceImpact);
1012
+ ```
1013
+
1014
+ How it works:
1015
+
1016
+ - calls REST route `/openocean/v4/solana/quote`
1017
+
1018
+ ### `openOceanSwap(options)`
1019
+
1020
+ Performs a swap through OpenOcean.
1021
+
1022
+ Add-on required: `openocean`
1023
+
1024
+ ```ts
1025
+ import bs58 from 'bs58';
1026
+ import { Keypair } from '@solana/web3.js';
1027
+
1028
+ const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
1029
+
1030
+ const result = await kit.openOceanSwap({
1031
+ inTokenAddress: 'So11111111111111111111111111111111111111112',
1032
+ outTokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1033
+ amount: '10000000',
1034
+ slippage: 1,
1035
+ userAddress: signer.publicKey.toString(),
1036
+ signer,
1037
+ });
1038
+
1039
+ console.log(result.signature);
1040
+ console.log(result.inAmount);
1041
+ console.log(result.outAmount);
1042
+ ```
1043
+
1044
+ How it works:
1045
+
1046
+ 1. requests serialized transaction from add-on
1047
+ 2. decodes base64 transaction
1048
+ 3. signs locally
1049
+ 4. sends using normal Solana connection
1050
+ 5. confirms it
1051
+
1052
+ ### `sendMerkleProtectedTransaction(options)`
1053
+
1054
+ Sends a signed transaction through Merkle for MEV protection.
1055
+
1056
+ Add-on required: `merkle`
1057
+
1058
+ ```ts
1059
+ const result = await kit.sendMerkleProtectedTransaction({
1060
+ serializedTransaction: signedTxBase64,
1061
+ tipLamports: 10_000,
1062
+ });
1063
+
1064
+ console.log(result.signature);
1065
+ console.log(result.provider);
1066
+ ```
1067
+
1068
+ How it works:
1069
+
1070
+ - calls custom RPC method `mev_sendTransaction`
1071
+ - confirms with normal Solana connection
1072
+
1073
+ ### `sendBlinkLabsTransaction(options)`
1074
+
1075
+ Sends a signed transaction through Blink Labs.
1076
+
1077
+ Add-on required: `blinklabs`
1078
+
1079
+ ```ts
1080
+ const result = await kit.sendBlinkLabsTransaction({
1081
+ serializedTransaction: signedTxBase64,
1082
+ tipLamports: 5_000,
1083
+ });
1084
+
1085
+ console.log(result.signature);
1086
+ console.log(result.provider);
1087
+ ```
1088
+
1089
+ How it works:
1090
+
1091
+ - calls custom RPC method `blinklabs_sendTransaction`
1092
+ - confirms with normal Solana connection
1093
+
1094
+ ### `sendIrisTransaction(options)`
1095
+
1096
+ Sends a signed transaction through the Iris add-on.
1097
+
1098
+ Add-on required: `iris`
1099
+
1100
+ ```ts
1101
+ const result = await kit.sendIrisTransaction({
1102
+ serializedTransaction: signedTxBase64,
1103
+ skipPreflight: false,
1104
+ maxRetries: 3,
1105
+ });
1106
+
1107
+ console.log(result.signature);
1108
+ console.log(result.slot);
1109
+ console.log(result.confirmationMs);
1110
+ ```
1111
+
1112
+ How it works:
1113
+
1114
+ - calls custom RPC method `iris_sendTransaction`
1115
+ - confirms with normal Solana RPC
1116
+
1117
+ ### `getGoldRushBalances(options)`
1118
+
1119
+ Gets multichain balances through GoldRush.
1120
+
1121
+ Add-on required: `goldrush`
1122
+
1123
+ ```ts
1124
+ const balances = await kit.getGoldRushBalances({
1125
+ walletAddress: 'WALLET_ADDRESS',
1126
+ chain: 'solana-mainnet',
1127
+ noSpam: true,
1128
+ quoteCurrency: 'USD',
1129
+ });
1130
+
1131
+ console.log(balances.chain);
1132
+ console.log(balances.address);
1133
+
1134
+ for (const item of balances.items) {
1135
+ console.log(item.symbol, item.balance, item.usdBalance);
1136
+ }
1137
+ ```
1138
+
1139
+ How it works:
1140
+
1141
+ - calls REST route under `/goldrush/v1/`
1142
+
1143
+ ### `getGoldRushTransactions(options)`
1144
+
1145
+ Gets multichain transaction history through GoldRush.
1146
+
1147
+ Add-on required: `goldrush`
1148
+
1149
+ ```ts
1150
+ const txs = await kit.getGoldRushTransactions({
1151
+ walletAddress: 'WALLET_ADDRESS',
1152
+ chain: 'solana-mainnet',
1153
+ pageSize: 25,
1154
+ pageNumber: 0,
1155
+ });
1156
+
1157
+ for (const tx of txs.items) {
1158
+ console.log(tx.txHash, tx.successful, tx.value);
1159
+ }
1160
+ ```
1161
+
1162
+ How it works:
1163
+
1164
+ - calls REST route under `/goldrush/v1/`
1165
+
1166
+ ### `getTitanSwapQuote(options)`
1167
+
1168
+ Gets a swap quote from Titan.
1169
+
1170
+ Add-on required: `titan`
1171
+
1172
+ ```ts
1173
+ const quote = await kit.getTitanSwapQuote({
1174
+ inputMint: 'So11111111111111111111111111111111111111112',
1175
+ outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1176
+ amount: '1000000000',
1177
+ slippageBps: 50,
1178
+ });
1179
+
1180
+ console.log(quote.inAmount);
1181
+ console.log(quote.outAmount);
1182
+ console.log(quote.routes);
1183
+ ```
1184
+
1185
+ How it works:
1186
+
1187
+ - calls REST route `/titan/v1/quote`
1188
+
1189
+ ### `titanSwap(options)`
1190
+
1191
+ Performs a swap through Titan.
1192
+
1193
+ Add-on required: `titan`
1194
+
1195
+ ```ts
1196
+ const result = await kit.titanSwap({
1197
+ inputMint: 'So11111111111111111111111111111111111111112',
1198
+ outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1199
+ amount: '10000000',
1200
+ slippageBps: 50,
1201
+ userPublicKey: 'WALLET_PUBLIC_KEY',
1202
+ });
1203
+
1204
+ console.log(result.signature);
1205
+ console.log(result.inAmount);
1206
+ console.log(result.outAmount);
1207
+ ```
1208
+
1209
+ How it works:
1210
+
1211
+ 1. gets a Titan quote
1212
+ 2. requests a serialized transaction
1213
+ 3. deserializes it
1214
+ 4. sends it through normal Solana connection
1215
+ 5. confirms it
1216
+
1217
+ ### `subscribeTitanQuotes(options, onQuote, onError?)`
1218
+
1219
+ Subscribes to live quote updates from Titan over WebSocket.
1220
+
1221
+ Add-on required: `titan`
1222
+
1223
+ ```ts
1224
+ const unsubscribe = kit.subscribeTitanQuotes(
1225
+ {
1226
+ inputMint: 'So11111111111111111111111111111111111111112',
1227
+ outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1228
+ amount: '1000000000',
1229
+ slippageBps: 50,
1230
+ },
1231
+ (quote) => {
1232
+ console.log('quote', quote.outAmount);
1233
+ },
1234
+ (err) => {
1235
+ console.error(err);
1236
+ },
1237
+ );
1238
+
1239
+ setTimeout(() => unsubscribe(), 15000);
1240
+ ```
1241
+
1242
+ How it works:
1243
+
1244
+ - opens a WebSocket to the Titan stream route on your endpoint
1245
+
1246
+ ### `assessWalletRisk(options)`
1247
+
1248
+ Gets Scorechain risk information for a wallet.
1249
+
1250
+ Add-on required: `scorechain`
1251
+
1252
+ ```ts
1253
+ const assessment = await kit.assessWalletRisk({
1254
+ address: 'WALLET_ADDRESS',
1255
+ network: 'solana',
1256
+ });
1257
+
1258
+ console.log(assessment.address);
1259
+ console.log(assessment.riskScore);
1260
+ console.log(assessment.riskLevel);
1261
+ console.log(assessment.amlStatus);
1262
+ console.log(assessment.flags);
1263
+ ```
1264
+
1265
+ How it works:
1266
+
1267
+ - calls REST route `/scorechain/v1/risk`
1268
+
1269
+ ### `isWalletSafe(address)`
1270
+
1271
+ Returns a simple safe/unsafe boolean using Scorechain.
1272
+
1273
+ Add-on required: `scorechain`
1274
+
1275
+ This returns `true` only when:
1276
+
1277
+ - `amlStatus === 'clean'`
1278
+ - `riskLevel === 'low'`
1279
+
1280
+ ```ts
1281
+ const safe = await kit.isWalletSafe('WALLET_ADDRESS');
1282
+ console.log(safe);
1283
+ ```
1284
+
1285
+ How it works:
1286
+
1287
+ - first calls `assessWalletRisk()`
1288
+ - then applies a simple clean + low-risk check
1289
+
1290
+ ## Token Constants
1291
+
1292
+ ### `TOKENS`
1293
+
1294
+ Useful for Jupiter / Metis examples.
1295
+
1296
+ ```ts
1297
+ import { TOKENS } from 'quicknode-solana-kit';
1298
+
1299
+ console.log(TOKENS.SOL);
1300
+ console.log(TOKENS.USDC);
1301
+ console.log(TOKENS.USDT);
1302
+ console.log(TOKENS.BONK);
1303
+ console.log(TOKENS.JUP);
1304
+ console.log(TOKENS.RAY);
1305
+ console.log(TOKENS.WIF);
1306
+ ```
1307
+
1308
+ ### `OO_TOKENS`
1309
+
1310
+ Useful for OpenOcean examples.
1311
+
1312
+ ```ts
1313
+ import { OO_TOKENS } from 'quicknode-solana-kit';
1314
+
1315
+ console.log(OO_TOKENS.SOL);
1316
+ console.log(OO_TOKENS.USDC);
1317
+ console.log(OO_TOKENS.USDT);
1318
+ console.log(OO_TOKENS.BONK);
1319
+ ```
372
1320
 
373
1321
  ## Error Handling
374
1322
 
375
- Every error is typed and tells you exactly what went wrong and how to fix it.
1323
+ The package exports custom errors:
1324
+
1325
+ - `AddOnNotEnabledError`
1326
+ - `TransactionFailedError`
1327
+ - `TransactionTimeoutError`
1328
+ - `MaxRetriesExceededError`
1329
+ - `InvalidEndpointError`
1330
+ - `RPCError`
1331
+
1332
+ Example:
376
1333
 
377
1334
  ```ts
378
1335
  import {
379
1336
  AddOnNotEnabledError,
1337
+ RPCError,
380
1338
  TransactionFailedError,
381
- TransactionTimeoutError,
382
1339
  MaxRetriesExceededError,
383
- RPCError,
384
- } from '@quicknode/solana-kit';
1340
+ } from 'quicknode-solana-kit';
385
1341
 
386
1342
  try {
387
1343
  await kit.sendSmartTransaction({ transaction, signer });
388
1344
  } catch (err) {
389
1345
  if (err instanceof AddOnNotEnabledError) {
390
- // Clear message with link to enable the add-on in the dashboard
391
- console.error(err.message);
1346
+ console.error('Enable the missing add-on in QuickNode and update kit config.');
392
1347
  } else if (err instanceof TransactionFailedError) {
393
- // On-chain failure check logs
394
- console.error('Failed on-chain:', err.reason);
395
- console.error('Explorer:', `https://explorer.solana.com/tx/${err.signature}`);
396
- } else if (err instanceof TransactionTimeoutError) {
397
- console.error('Timed out. Try a higher feeLevel.');
1348
+ console.error('On-chain failure:', err.signature, err.reason);
398
1349
  } else if (err instanceof MaxRetriesExceededError) {
399
- console.error(`Failed after ${err.maxRetries} retries.`);
1350
+ console.error('Retries exhausted:', err.maxRetries);
400
1351
  } else if (err instanceof RPCError) {
401
- console.error(`RPC ${err.statusCode}:`, err.message);
1352
+ console.error('RPC error:', err.statusCode, err.message);
1353
+ } else {
1354
+ console.error(err);
402
1355
  }
403
1356
  }
404
1357
  ```
405
1358
 
406
- ---
1359
+ ## Included Example Scripts
407
1360
 
408
- ## Tree-Shaking
1361
+ ```bash
1362
+ npm run example:tx
1363
+ npm run example:nft
1364
+ npm run example:stream
1365
+ npm run example:swap
1366
+ npm run example:all
1367
+ ```
409
1368
 
410
- Import only what you need for smaller bundles:
1369
+ Suggested `.env` values:
411
1370
 
412
- ```ts
413
- // Individual function imports (fully tree-shakeable)
414
- import { estimatePriorityFees } from '@quicknode/solana-kit';
415
- import { getAssetsByOwner } from '@quicknode/solana-kit';
416
- import { watchAccount } from '@quicknode/solana-kit';
417
- import { swap, TOKENS } from '@quicknode/solana-kit';
1371
+ ```bash
1372
+ QN_ENDPOINT_URL=
1373
+ WALLET_PRIVATE_KEY=
1374
+ WALLET_ADDRESS=
1375
+ ADDON_PRIORITY_FEES=true
1376
+ ADDON_DAS=true
1377
+ ADDON_METIS=true
1378
+ EXECUTE_SWAP=false
418
1379
  ```
419
1380
 
420
- ---
1381
+ ## Recommended Learning Order
421
1382
 
422
- ## Running the Examples
1383
+ If you are new to Solana or QuickNode, this order works well:
423
1384
 
424
- ```bash
425
- # Clone and install
426
- git clone https://github.com/quiknode-labs/qn-solana-kit
427
- cd qn-solana-kit
428
- npm install
1385
+ 1. create `kit`
1386
+ 2. use `kit.connection.getBalance()`
1387
+ 3. use `kit.getTokenAccounts()`
1388
+ 4. run `kit.checkAddOns()`
1389
+ 5. if `priorityFees` is enabled, try `kit.estimatePriorityFees()`
1390
+ 6. if `das` is enabled, try `kit.getAssetsByOwner()`
1391
+ 7. if `metis` is enabled, try `kit.getSwapQuote()`
429
1392
 
430
- # Setup environment
431
- cp .env.example .env
432
- # Fill in QN_ENDPOINT_URL (required)
433
- # Fill in WALLET_ADDRESS and WALLET_PRIVATE_KEY for tx/swap examples
1393
+ ## Starter Example
434
1394
 
435
- # Check which add-ons are active on your endpoint
436
- npm run check
1395
+ ```ts
1396
+ import { PublicKey } from '@solana/web3.js';
1397
+ import { QNSolanaKit } from 'quicknode-solana-kit';
1398
+
1399
+ const kit = new QNSolanaKit({
1400
+ endpointUrl: process.env.QN_ENDPOINT_URL!,
1401
+ addOns: {
1402
+ priorityFees: true,
1403
+ das: true,
1404
+ },
1405
+ });
437
1406
 
438
- # Run individual examples
439
- npm run example:tx # Smart transaction (needs Priority Fee API add-on)
440
- npm run example:nft # NFT queries (needs DAS API add-on)
441
- npm run example:stream # Live streaming (works on free tier)
442
- npm run example:swap # Jupiter swap quote (needs Metis add-on)
1407
+ async function main() {
1408
+ const wallet = new PublicKey('E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk');
443
1409
 
444
- # Run all
445
- npm run example:all
1410
+ const balance = await kit.connection.getBalance(wallet);
1411
+ console.log('SOL balance:', balance / 1e9);
1412
+
1413
+ const tokenAccounts = await kit.getTokenAccounts(wallet.toString());
1414
+ console.log('Token accounts:', tokenAccounts.length);
1415
+
1416
+ const fees = await kit.estimatePriorityFees();
1417
+ console.log('Recommended priority fee:', fees.recommended);
1418
+
1419
+ const assets = await kit.getAssetsByOwner({
1420
+ ownerAddress: wallet.toString(),
1421
+ limit: 5,
1422
+ });
1423
+ console.log('Assets:', assets.items.length);
1424
+ }
1425
+
1426
+ main().catch(console.error);
446
1427
  ```
447
1428
 
1429
+ ## Current Limitations
1430
+
1431
+ - `yellowstone` is exposed in config and add-on checks, but account streaming currently falls back to standard Solana WebSockets
1432
+ - `liljit` is probed by `checkAddOns()`, but `sendSmartTransaction()` does not currently route through Jito bundles
1433
+ - `sendSmartTransaction()` works without `priorityFees`, but falls back to a default compute unit price
1434
+ - several swap integrations return a serialized transaction that the SDK then signs and sends locally
1435
+
1436
+ ## Beginner Guide
1437
+
1438
+ If you want a more beginner-first walkthrough, see:
448
1439
 
449
- ## Links
1440
+ - [readmetounderstand.md](/home/rachit/Videos/QuickNode-Starter-Kit/qn-solana-kit-v2/readmetounderstand.md)
450
1441
 
451
- - QuickNode Dashboard: https://dashboard.quicknode.com
452
- - Add-ons Marketplace: https://marketplace.quicknode.com
453
- - Priority Fee API: https://www.quicknode.com/docs/solana/qn_estimatePriorityFees
454
- - Metaplex DAS API: https://www.quicknode.com/docs/solana/getAsset
455
- - Metis (Jupiter): https://marketplace.quicknode.com/add-ons/metis-jupiter-v6-swap-api
456
- - Yellowstone gRPC: https://marketplace.quicknode.com/add-ons/yellowstone-grpc
1442
+ ## License
457
1443
 
458
- ---
1444
+ MIT