quicknode-solana-kit 1.0.3 → 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 (2) hide show
  1. package/README.md +722 -432
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,49 +2,59 @@
2
2
 
3
3
  Typed Solana SDK for QuickNode endpoints and QuickNode-powered add-ons.
4
4
 
5
- This package gives you one client for:
5
+ This package gives you one place to work with:
6
6
 
7
- - normal Solana RPC via `@solana/web3.js`
8
- - QuickNode custom RPC methods
9
- - QuickNode-mounted REST add-ons
10
- - real-time subscriptions through Solana WebSockets
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
11
 
12
- If all you know today is:
12
+ If your current Solana setup looks like this:
13
13
 
14
14
  ```ts
15
15
  import { Connection } from '@solana/web3.js';
16
16
 
17
- const connection = new Connection('https://your-endpoint.quiknode.pro/TOKEN/', 'confirmed');
17
+ const connection = new Connection(
18
+ 'https://your-endpoint.quiknode.pro/TOKEN/',
19
+ 'confirmed',
20
+ );
18
21
  ```
19
22
 
20
- this package is the next layer on top of that.
23
+ then `quicknode-solana-kit` is the layer on top of that.
21
24
 
22
- It still uses a normal Solana `Connection`, but wraps common QuickNode features into a single typed API.
25
+ It still uses a normal Solana `Connection`, but adds typed helper methods for common QuickNode add-ons and transaction workflows.
23
26
 
24
27
  ```bash
25
28
  npm install quicknode-solana-kit
26
29
  ```
27
30
 
28
- ## What This Package Actually Does
31
+ ## What This Package Is
29
32
 
30
- `quicknode-solana-kit` is not a replacement for Solana RPC.
33
+ This package is a wrapper around three patterns:
31
34
 
32
- It is a wrapper around three patterns:
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`
33
38
 
34
- 1. Standard Solana RPC and WebSocket calls through `@solana/web3.js`
35
- 2. QuickNode custom JSON-RPC methods like `qn_estimatePriorityFees`
36
- 3. REST-style add-ons mounted on your QuickNode endpoint like `/jupiter/v6/quote`
39
+ It does not replace Solana RPC. It organizes it.
37
40
 
38
- The package creates a normal Solana `Connection` internally, then adds methods like:
41
+ You get:
39
42
 
40
- - `sendSmartTransaction()`
41
- - `estimatePriorityFees()`
42
- - `getAssetsByOwner()`
43
- - `getSwapQuote()`
44
- - `getPumpFunTokens()`
45
- - `sendMerkleProtectedTransaction()`
46
- - `getGoldRushBalances()`
47
- - `assessWalletRisk()`
43
+ - `kit.connection` for normal Solana calls
44
+ - `kit.someMethod()` for QuickNode helper methods
45
+
46
+ Example:
47
+
48
+ ```ts
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);
57
+ ```
48
58
 
49
59
  ## Install
50
60
 
@@ -52,28 +62,20 @@ The package creates a normal Solana `Connection` internally, then adds methods l
52
62
  npm install quicknode-solana-kit
53
63
  ```
54
64
 
55
- Peer/runtime requirements:
65
+ Requirements:
56
66
 
57
67
  - Node.js 18+
58
68
  - a QuickNode Solana endpoint
59
69
 
60
70
  ## Quick Start
61
71
 
62
- ### 1. Create a QuickNode Solana endpoint
63
-
64
- Example endpoint:
65
-
66
- ```txt
67
- https://your-name.solana-mainnet.quiknode.pro/YOUR_TOKEN/
68
- ```
69
-
70
- ### 2. Create the client
72
+ ### 1. Create the kit
71
73
 
72
74
  ```ts
73
75
  import { QNSolanaKit } from 'quicknode-solana-kit';
74
76
 
75
77
  const kit = new QNSolanaKit({
76
- endpointUrl: 'https://your-name.solana-mainnet.quiknode.pro/YOUR_TOKEN/',
78
+ endpointUrl: 'https://your-endpoint.quiknode.pro/TOKEN/',
77
79
  commitment: 'confirmed',
78
80
  timeout: 30_000,
79
81
  addOns: {
@@ -95,14 +97,28 @@ const kit = new QNSolanaKit({
95
97
  });
96
98
  ```
97
99
 
98
- ### 3. Use the built-in Solana connection
100
+ ### 2. Use normal Solana methods
99
101
 
100
102
  ```ts
103
+ import { PublicKey } from '@solana/web3.js';
104
+
105
+ const wallet = new PublicKey('E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk');
106
+
107
+ const balance = await kit.connection.getBalance(wallet);
108
+ const slot = await kit.connection.getSlot();
101
109
  const blockhash = await kit.connection.getLatestBlockhash();
102
- console.log(blockhash.blockhash);
110
+
111
+ console.log(balance, slot, blockhash.blockhash);
103
112
  ```
104
113
 
105
- ### 4. Probe your endpoint
114
+ ### 3. Use kit helper methods
115
+
116
+ ```ts
117
+ const tokenAccounts = await kit.getTokenAccounts(wallet.toString());
118
+ console.log(tokenAccounts.length);
119
+ ```
120
+
121
+ ### 4. Check which add-ons are live
106
122
 
107
123
  ```ts
108
124
  const status = await kit.checkAddOns();
@@ -110,19 +126,48 @@ console.log(status.addOns);
110
126
  console.log(status.canUse);
111
127
  ```
112
128
 
113
- You can also run the CLI:
129
+ CLI:
114
130
 
115
131
  ```bash
116
132
  npm run check
117
133
  ```
118
134
 
119
- ## How Add-Ons Work
135
+ ## Can You Still Use Built-In Solana `Connection` Methods?
136
+
137
+ Yes.
138
+
139
+ This is one of the most important points in the whole package.
140
+
141
+ `kit.connection` is a real `Connection` instance from `@solana/web3.js`.
142
+
143
+ That means you can still use methods like:
144
+
145
+ ```ts
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
+ ```
154
+
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.
120
165
 
121
- This package uses add-ons in two ways:
166
+ This package handles add-ons in two ways:
122
167
 
123
168
  ### 1. Local config guard
124
169
 
125
- You declare what you think is enabled:
170
+ You tell the SDK what you believe is enabled:
126
171
 
127
172
  ```ts
128
173
  const kit = new QNSolanaKit({
@@ -135,15 +180,13 @@ const kit = new QNSolanaKit({
135
180
  });
136
181
  ```
137
182
 
138
- If you explicitly set an add-on to `false` and call a method that requires it, the SDK throws an `AddOnNotEnabledError`.
183
+ If you explicitly set an add-on to `false` and call a method that needs it, the SDK throws an `AddOnNotEnabledError`.
139
184
 
140
- If you leave a value `undefined`, the SDK warns and still tries the network call.
185
+ If a value is left `undefined`, the SDK warns and still attempts the network call.
141
186
 
142
- ### 2. Real endpoint capability
187
+ ### 2. Real endpoint probe
143
188
 
144
- The actual source of truth is your endpoint.
145
-
146
- `checkAddOns()` probes the endpoint by making sample RPC or REST calls and returns what is live.
189
+ `checkAddOns()` performs real test calls to your endpoint and tells you what is actually live.
147
190
 
148
191
  ```ts
149
192
  const result = await kit.checkAddOns();
@@ -151,188 +194,276 @@ const result = await kit.checkAddOns();
151
194
  console.log(result.canUse.smartTransactions);
152
195
  console.log(result.canUse.nftQueries);
153
196
  console.log(result.canUse.swaps);
154
- console.log(result.canUse.openOceanSwaps);
155
197
  console.log(result.canUse.goldRushData);
198
+ console.log(result.canUse.riskAssessment);
156
199
  ```
157
200
 
158
- ## Add-On Map
201
+ ## How This SDK Talks To QuickNode
159
202
 
160
- Here is how each add-on is implemented inside the package.
203
+ There are three backend styles used in this package.
161
204
 
162
- | Add-on key | What it unlocks | Transport used by SDK | Example endpoint shape |
163
- |---|---|---|---|
164
- | `priorityFees` | live fee estimation and smart tx fee selection | JSON-RPC | `qn_estimatePriorityFees` |
165
- | `das` | NFT / digital asset queries | JSON-RPC | `getAssetsByOwner` |
166
- | `metis` | Jupiter quote and swap | REST | `/jupiter/v6/quote` |
167
- | `yellowstone` | account streaming preference | currently falls back to WebSocket | no active gRPC client yet |
168
- | `liljit` | intended Jito support | checked by probe, not fully wired into smart tx flow yet | `sendBundle` |
169
- | `pumpfun` | pump.fun market data | REST | `/pump-fun/coins` |
170
- | `stablecoinBalance` | stablecoin balances across chains | JSON-RPC | `qn_getWalletStablecoinBalances` |
171
- | `openocean` | OpenOcean quote and swap | REST | `/openocean/v4/solana/quote` |
172
- | `merkle` | MEV-protected tx submission | JSON-RPC | `mev_sendTransaction` |
173
- | `blinklabs` | alternate protected tx submission | JSON-RPC | `blinklabs_sendTransaction` |
174
- | `iris` | low-latency tx sender | JSON-RPC | `iris_sendTransaction` |
175
- | `goldrush` | multichain balances and tx history | REST | `/goldrush/v1/...` |
176
- | `titan` | swap quote, swap, quote stream | REST + WebSocket | `/titan/v1/quote` |
177
- | `scorechain` | wallet risk checks | REST | `/scorechain/v1/risk` |
178
-
179
- ## Common Pattern
180
-
181
- Most features follow one of these flows.
182
-
183
- ### Standard Solana RPC
205
+ ### 1. Standard Solana RPC
206
+
207
+ Example:
184
208
 
185
209
  ```ts
186
- const accounts = await kit.connection.getTokenAccountsByOwner(
187
- wallet,
188
- { programId: TOKEN_PROGRAM_ID },
189
- );
210
+ await kit.connection.getBalance(pubkey);
190
211
  ```
191
212
 
192
- ### QuickNode custom RPC
213
+ ### 2. QuickNode Custom JSON-RPC
193
214
 
194
- The SDK hides the raw method call:
215
+ Example:
195
216
 
196
217
  ```ts
197
- const fees = await kit.estimatePriorityFees();
218
+ await kit.estimatePriorityFees();
198
219
  ```
199
220
 
200
- instead of:
221
+ Internally, that becomes a JSON-RPC request similar to:
201
222
 
202
- ```ts
203
- await fetch(endpoint, {
204
- method: 'POST',
205
- headers: { 'Content-Type': 'application/json' },
206
- body: JSON.stringify({
207
- jsonrpc: '2.0',
208
- id: 1,
209
- method: 'qn_estimatePriorityFees',
210
- params: { last_n_blocks: 100, api_version: 2 },
211
- }),
212
- });
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
+ }
213
233
  ```
214
234
 
215
- ### REST add-on mounted on the same endpoint
235
+ ### 3. QuickNode REST Add-On Route
216
236
 
217
- The SDK also hides path-building:
237
+ Example:
218
238
 
219
239
  ```ts
220
- const quote = await kit.getSwapQuote({
240
+ await kit.getSwapQuote({
221
241
  inputMint: TOKENS.SOL,
222
242
  outputMint: TOKENS.USDC,
223
243
  amount: BigInt(1_000_000_000),
224
244
  });
225
245
  ```
226
246
 
227
- instead of manually calling:
247
+ Internally, that calls a route like:
228
248
 
229
249
  ```txt
230
250
  https://your-endpoint.quiknode.pro/TOKEN/jupiter/v6/quote?...
231
251
  ```
232
252
 
233
- ## Client Configuration
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:
234
354
 
235
- ```ts
236
- import { QNSolanaKit } from 'quicknode-solana-kit';
355
+ - `estimatePriorityFees()`
356
+ - improved `sendSmartTransaction()`
357
+ - improved `prepareSmartTransaction()`
237
358
 
238
- const kit = new QNSolanaKit({
239
- endpointUrl: process.env.QN_ENDPOINT_URL!,
240
- commitment: 'confirmed',
241
- timeout: 30_000,
242
- addOns: {
243
- priorityFees: true,
244
- das: true,
245
- },
246
- });
247
- ```
359
+ ### `das`
248
360
 
249
- ### Config fields
361
+ Unlocks:
250
362
 
251
- ```ts
252
- interface QNConfig {
253
- endpointUrl: string;
254
- commitment?: 'processed' | 'confirmed' | 'finalized';
255
- timeout?: number;
256
- addOns?: {
257
- priorityFees?: boolean;
258
- liljit?: boolean;
259
- das?: boolean;
260
- metis?: boolean;
261
- yellowstone?: boolean;
262
- pumpfun?: boolean;
263
- stablecoinBalance?: boolean;
264
- openocean?: boolean;
265
- merkle?: boolean;
266
- blinklabs?: boolean;
267
- iris?: boolean;
268
- goldrush?: boolean;
269
- titan?: boolean;
270
- scorechain?: boolean;
271
- };
272
- }
273
- ```
363
+ - `getAssetsByOwner()`
364
+ - `getAsset()`
365
+ - `getAssetsByCollection()`
366
+ - `searchAssets()`
367
+ - `getAssetProof()`
274
368
 
275
- ## API Reference
369
+ ### `metis`
276
370
 
277
- ### Diagnostics
371
+ Unlocks:
278
372
 
279
- #### `kit.checkAddOns()`
373
+ - `getSwapQuote()`
374
+ - `swap()`
280
375
 
281
- Probes your endpoint and returns add-on availability.
376
+ ### `pumpfun`
282
377
 
283
- ```ts
284
- const status = await kit.checkAddOns();
378
+ Unlocks:
285
379
 
286
- for (const addon of status.addOns) {
287
- console.log(addon.name, addon.enabled, addon.tier);
288
- }
380
+ - `getPumpFunTokens()`
381
+ - `getPumpFunToken()`
382
+ - `getPumpFunTokensByCreator()`
383
+ - `getPumpFunTokenHolders()`
384
+ - `getPumpFunTokenTrades()`
289
385
 
290
- console.log(status.canUse.smartTransactions);
291
- console.log(status.canUse.nftQueries);
292
- console.log(status.canUse.swaps);
293
- console.log(status.canUse.pumpFun);
294
- console.log(status.canUse.goldRushData);
295
- console.log(status.canUse.riskAssessment);
296
- ```
386
+ ### `stablecoinBalance`
297
387
 
298
- ### Transactions
388
+ Unlocks:
299
389
 
300
- #### `kit.estimatePriorityFees(options?)`
390
+ - `getStablecoinBalance()`
301
391
 
302
- Requires: `priorityFees`
392
+ ### `openocean`
303
393
 
304
- Gets live priority fee estimates from QuickNode.
394
+ Unlocks:
305
395
 
306
- ```ts
307
- const fees = await kit.estimatePriorityFees();
396
+ - `getOpenOceanQuote()`
397
+ - `openOceanSwap()`
308
398
 
309
- console.log(fees.low);
310
- console.log(fees.medium);
311
- console.log(fees.recommended);
312
- console.log(fees.high);
313
- console.log(fees.extreme);
314
- console.log(fees.networkCongestion);
315
- ```
399
+ ### `merkle`
400
+
401
+ Unlocks:
402
+
403
+ - `sendMerkleProtectedTransaction()`
404
+
405
+ ### `blinklabs`
406
+
407
+ Unlocks:
408
+
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()`
438
+
439
+ ## API Reference
316
440
 
317
- With an account filter:
441
+ ### `checkAddOns()`
442
+
443
+ Checks which add-ons are actually enabled on your endpoint.
444
+
445
+ Add-on required: none
318
446
 
319
447
  ```ts
320
- const fees = await kit.estimatePriorityFees({
321
- account: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',
322
- lastNBlocks: 50,
323
- });
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);
324
454
  ```
325
455
 
326
- #### `kit.sendSmartTransaction({ transaction, signer, options })`
456
+ How it works:
327
457
 
328
- Uses:
458
+ - performs real probe calls to your endpoint
459
+ - tests both RPC-based and REST-based add-ons
460
+ - returns a structured capability report
329
461
 
330
- - Solana simulation to estimate compute units
331
- - QuickNode Priority Fee API when available
332
- - compute budget instruction injection
333
- - retry loop with backoff
462
+ ### `sendSmartTransaction({ transaction, signer, options })`
334
463
 
335
- Requires: no add-on strictly required, but `priorityFees` makes it much better
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
336
467
 
337
468
  ```ts
338
469
  import bs58 from 'bs58';
@@ -342,16 +473,10 @@ import {
342
473
  SystemProgram,
343
474
  Transaction,
344
475
  } from '@solana/web3.js';
345
- import { QNSolanaKit } from 'quicknode-solana-kit';
346
-
347
- const kit = new QNSolanaKit({
348
- endpointUrl: process.env.QN_ENDPOINT_URL!,
349
- addOns: { priorityFees: true },
350
- });
351
476
 
352
477
  const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
353
478
 
354
- const transaction = new Transaction().add(
479
+ const tx = new Transaction().add(
355
480
  SystemProgram.transfer({
356
481
  fromPubkey: signer.publicKey,
357
482
  toPubkey: signer.publicKey,
@@ -360,7 +485,7 @@ const transaction = new Transaction().add(
360
485
  );
361
486
 
362
487
  const result = await kit.sendSmartTransaction({
363
- transaction,
488
+ transaction: tx,
364
489
  signer,
365
490
  options: {
366
491
  feeLevel: 'recommended',
@@ -378,15 +503,34 @@ console.log(result.computeUnitsUsed);
378
503
  console.log(result.confirmationMs);
379
504
  ```
380
505
 
381
- #### `kit.prepareSmartTransaction({ transaction, payer, options })`
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:
382
519
 
383
- Prepares a transaction with compute budget instructions and recent blockhash, but does not send it.
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
384
522
 
385
- This is useful for wallet adapters.
523
+ ### `prepareSmartTransaction({ transaction, payer, options })`
524
+
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.
386
530
 
387
531
  ```ts
388
532
  const prepared = await kit.prepareSmartTransaction({
389
- transaction: myTransaction,
533
+ transaction: myTx,
390
534
  payer: wallet.publicKey,
391
535
  options: {
392
536
  feeLevel: 'high',
@@ -397,56 +541,102 @@ const prepared = await kit.prepareSmartTransaction({
397
541
  console.log(prepared.priorityFeeMicroLamports);
398
542
  console.log(prepared.computeUnits);
399
543
 
400
- const signature = await wallet.sendTransaction(prepared.transaction, kit.connection);
401
- console.log(signature);
544
+ const sig = await wallet.sendTransaction(prepared.transaction, kit.connection);
545
+ console.log(sig);
402
546
  ```
403
547
 
404
- ### Digital Assets and Tokens
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?)`
557
+
558
+ Gets live priority fee estimates from QuickNode.
559
+
560
+ Add-on required: `priorityFees`
561
+
562
+ ```ts
563
+ const fees = await kit.estimatePriorityFees({
564
+ lastNBlocks: 100,
565
+ });
405
566
 
406
- #### `kit.getAssetsByOwner(options)`
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
+ ```
407
574
 
408
- Requires: `das`
575
+ With account filter:
576
+
577
+ ```ts
578
+ const fees = await kit.estimatePriorityFees({
579
+ account: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',
580
+ lastNBlocks: 50,
581
+ });
582
+ ```
583
+
584
+ How it works:
585
+
586
+ - calls QuickNode custom RPC method `qn_estimatePriorityFees`
587
+ - maps response to fee levels
588
+
589
+ ### `getAssetsByOwner(options)`
409
590
 
410
591
  Gets digital assets owned by a wallet.
411
592
 
593
+ Add-on required: `das`
594
+
412
595
  ```ts
413
- const result = await kit.getAssetsByOwner({
414
- ownerAddress: 'E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk',
596
+ const assets = await kit.getAssetsByOwner({
597
+ ownerAddress: 'WALLET_ADDRESS',
415
598
  limit: 10,
416
599
  page: 1,
417
600
  });
418
601
 
419
- console.log(result.total);
602
+ console.log(assets.total);
420
603
 
421
- for (const asset of result.items) {
422
- console.log(asset.id);
423
- console.log(asset.content.metadata.name);
424
- console.log(asset.ownership.owner);
425
- console.log(asset.compression?.compressed);
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);
426
609
  }
427
610
  ```
428
611
 
429
- #### `kit.getAsset(mintAddress)`
612
+ How it works:
613
+
614
+ - calls DAS RPC method `getAssetsByOwner`
430
615
 
431
- Requires: `das`
616
+ ### `getAsset(mintAddress)`
432
617
 
433
- Gets one asset by id or mint address.
618
+ Gets one digital asset.
619
+
620
+ Add-on required: `das`
434
621
 
435
622
  ```ts
436
- const asset = await kit.getAsset('NFT_MINT_OR_ASSET_ID');
623
+ const asset = await kit.getAsset('ASSET_ID_OR_MINT');
437
624
 
438
625
  console.log(asset.id);
439
626
  console.log(asset.content.metadata.name);
440
627
  console.log(asset.content.metadata.symbol);
441
628
  console.log(asset.content.metadata.image);
442
- console.log(asset.royalty?.basis_points);
443
629
  ```
444
630
 
445
- #### `kit.getAssetsByCollection(options)`
631
+ How it works:
632
+
633
+ - calls DAS RPC method `getAsset`
634
+
635
+ ### `getAssetsByCollection(options)`
446
636
 
447
- Requires: `das`
637
+ Gets assets by collection.
448
638
 
449
- Gets assets by collection mint.
639
+ Add-on required: `das`
450
640
 
451
641
  ```ts
452
642
  const collectionAssets = await kit.getAssetsByCollection({
@@ -456,31 +646,32 @@ const collectionAssets = await kit.getAssetsByCollection({
456
646
  });
457
647
 
458
648
  console.log(collectionAssets.total);
459
- console.log(collectionAssets.items.map(item => item.content.metadata.name));
460
649
  ```
461
650
 
462
- #### `kit.searchAssets(options)`
651
+ How it works:
652
+
653
+ - calls DAS RPC method `getAssetsByGroup`
654
+ - uses collection grouping
655
+
656
+ ### `searchAssets(options)`
463
657
 
464
- Requires: `das`
658
+ Searches digital assets with filters.
465
659
 
466
- Searches by owner, creator, collection, token type, or compressed status.
660
+ Add-on required: `das`
661
+
662
+ By owner:
467
663
 
468
664
  ```ts
469
- const compressed = await kit.searchAssets({
665
+ const result = await kit.searchAssets({
470
666
  ownerAddress: 'WALLET_ADDRESS',
471
- tokenType: 'compressedNFT',
472
- compressed: true,
473
- limit: 50,
474
- page: 1,
667
+ limit: 25,
475
668
  });
476
-
477
- console.log(compressed.items.length);
478
669
  ```
479
670
 
480
671
  By creator:
481
672
 
482
673
  ```ts
483
- const created = await kit.searchAssets({
674
+ const result = await kit.searchAssets({
484
675
  creatorAddress: 'CREATOR_ADDRESS',
485
676
  limit: 25,
486
677
  });
@@ -489,17 +680,32 @@ const created = await kit.searchAssets({
489
680
  By collection:
490
681
 
491
682
  ```ts
492
- const byCollection = await kit.searchAssets({
683
+ const result = await kit.searchAssets({
493
684
  collection: 'COLLECTION_MINT',
494
685
  limit: 25,
495
686
  });
496
687
  ```
497
688
 
498
- #### `kit.getAssetProof(assetId)`
689
+ Compressed NFTs only:
690
+
691
+ ```ts
692
+ const result = await kit.searchAssets({
693
+ tokenType: 'compressedNFT',
694
+ compressed: true,
695
+ limit: 25,
696
+ });
697
+ ```
698
+
699
+ How it works:
700
+
701
+ - builds a DAS search request
702
+ - calls DAS RPC method `searchAssets`
703
+
704
+ ### `getAssetProof(assetId)`
499
705
 
500
- Requires: `das`
706
+ Gets the Merkle proof for a compressed NFT.
501
707
 
502
- Gets the Merkle proof for a compressed asset.
708
+ Add-on required: `das`
503
709
 
504
710
  ```ts
505
711
  const proof = await kit.getAssetProof('ASSET_ID');
@@ -509,55 +715,63 @@ console.log(proof.proof);
509
715
  console.log(proof.tree_id);
510
716
  ```
511
717
 
512
- #### `kit.getTokenAccounts(walletAddress)`
718
+ How it works:
513
719
 
514
- No add-on required.
720
+ - calls DAS RPC method `getAssetProof`
515
721
 
516
- Gets parsed SPL token accounts using standard Solana RPC.
722
+ ### `getTokenAccounts(walletAddress)`
723
+
724
+ Gets SPL token accounts and balances for a wallet.
725
+
726
+ Add-on required: none
517
727
 
518
728
  ```ts
519
- const tokenAccounts = await kit.getTokenAccounts('WALLET_ADDRESS');
729
+ const tokens = await kit.getTokenAccounts('WALLET_ADDRESS');
520
730
 
521
- for (const token of tokenAccounts) {
731
+ for (const token of tokens) {
522
732
  if (token.uiAmount > 0) {
523
733
  console.log(token.mint, token.uiAmount);
524
734
  }
525
735
  }
526
736
  ```
527
737
 
528
- ### Streaming
738
+ How it works:
529
739
 
530
- #### `kit.watchAccount(address, onUpdate, options?)`
740
+ - calls normal Solana RPC method `getTokenAccountsByOwner`
741
+ - uses `jsonParsed` encoding
531
742
 
532
- No paid add-on required for basic usage.
743
+ ### `watchAccount(address, onUpdate, options?)`
533
744
 
534
- If `yellowstone` is enabled in config, the package prefers that path, but the current implementation falls back to standard WebSocket subscriptions.
745
+ Watches an account in real time.
746
+
747
+ Add-on required: none
535
748
 
536
749
  ```ts
537
- const handle = kit.watchAccount(
538
- 'E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk',
539
- (update) => {
540
- console.log(update.pubkey);
541
- console.log(update.lamports);
542
- console.log(update.owner);
543
- console.log(update.slot);
544
- console.log(update.backend);
545
- },
546
- {
547
- backend: 'auto',
548
- commitment: 'confirmed',
549
- },
550
- );
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);
756
+ });
551
757
 
552
758
  setTimeout(() => {
553
759
  console.log(handle.isConnected());
554
760
  handle.unsubscribe();
555
- }, 15_000);
761
+ }, 15000);
556
762
  ```
557
763
 
558
- #### `kit.watchProgram(programId, onTx, options?)`
764
+ How it works:
765
+
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
769
+
770
+ ### `watchProgram(programId, onTx, options?)`
559
771
 
560
- Watches program logs through Solana WebSockets.
772
+ Watches program logs in real time.
773
+
774
+ Add-on required: none
561
775
 
562
776
  ```ts
563
777
  const handle = kit.watchProgram(
@@ -567,34 +781,36 @@ const handle = kit.watchProgram(
567
781
  console.log(tx.logs);
568
782
  console.log(tx.err);
569
783
  },
570
- { commitment: 'confirmed' },
571
784
  );
572
785
  ```
573
786
 
574
- #### `kit.watchSlot(onSlot)`
787
+ How it works:
788
+
789
+ - uses `connection.onLogs(...)`
790
+
791
+ ### `watchSlot(onSlot)`
575
792
 
576
793
  Watches slot changes.
577
794
 
795
+ Add-on required: none
796
+
578
797
  ```ts
579
798
  const handle = kit.watchSlot((slot) => {
580
- console.log('slot', slot);
799
+ console.log(slot);
581
800
  });
582
801
 
583
- setTimeout(() => handle.unsubscribe(), 10_000);
802
+ setTimeout(() => handle.unsubscribe(), 10000);
584
803
  ```
585
804
 
586
- ### Jupiter / Metis
805
+ How it works:
587
806
 
588
- Requires: `metis`
807
+ - uses `connection.onSlotChange(...)`
589
808
 
590
- The SDK builds URLs under your endpoint like:
809
+ ### `getSwapQuote(options)`
591
810
 
592
- ```txt
593
- https://your-endpoint.quiknode.pro/TOKEN/jupiter/v6/quote
594
- https://your-endpoint.quiknode.pro/TOKEN/jupiter/v6/swap
595
- ```
811
+ Gets a Jupiter quote through the Metis add-on.
596
812
 
597
- #### `kit.getSwapQuote(options)`
813
+ Add-on required: `metis`
598
814
 
599
815
  ```ts
600
816
  import { TOKENS } from 'quicknode-solana-kit';
@@ -612,75 +828,53 @@ console.log(quote.priceImpactPct);
612
828
  console.log(quote.routePlan);
613
829
  ```
614
830
 
615
- #### `kit.swap(options)`
831
+ How it works:
616
832
 
617
- The SDK flow is:
833
+ - calls REST route `/jupiter/v6/quote`
618
834
 
619
- 1. fetch quote
620
- 2. request serialized swap transaction
621
- 3. deserialize transaction
622
- 4. sign locally
623
- 5. send with normal Solana connection
624
- 6. confirm
835
+ ### `swap(options)`
836
+
837
+ Performs a Jupiter swap through Metis.
838
+
839
+ Add-on required: `metis`
625
840
 
626
841
  ```ts
627
842
  import bs58 from 'bs58';
628
843
  import { Keypair } from '@solana/web3.js';
629
- import { QNSolanaKit, TOKENS } from 'quicknode-solana-kit';
844
+ import { TOKENS } from 'quicknode-solana-kit';
630
845
 
631
846
  const signer = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_PRIVATE_KEY!));
632
847
 
633
- const kit = new QNSolanaKit({
634
- endpointUrl: process.env.QN_ENDPOINT_URL!,
635
- addOns: { metis: true },
636
- });
637
-
638
- const swapResult = await kit.swap({
848
+ const result = await kit.swap({
639
849
  inputMint: TOKENS.SOL,
640
850
  outputMint: TOKENS.USDC,
641
- amount: BigInt(100_000_000),
851
+ amount: BigInt(10_000_000),
642
852
  userPublicKey: signer.publicKey.toString(),
643
853
  signer,
644
- slippageBps: 50,
854
+ slippageBps: 100,
645
855
  feeLevel: 'recommended',
646
856
  });
647
857
 
648
- console.log(swapResult.signature);
649
- console.log(swapResult.inputAmount);
650
- console.log(swapResult.outputAmount);
651
- console.log(swapResult.priceImpactPct);
652
- ```
653
-
654
- #### `TOKENS`
655
-
656
- Token shortcuts:
657
-
658
- ```ts
659
- import { TOKENS } from 'quicknode-solana-kit';
660
-
661
- console.log(TOKENS.SOL);
662
- console.log(TOKENS.USDC);
663
- console.log(TOKENS.USDT);
664
- console.log(TOKENS.BONK);
665
- console.log(TOKENS.JUP);
666
- console.log(TOKENS.RAY);
667
- console.log(TOKENS.WIF);
858
+ console.log(result.signature);
859
+ console.log(result.inputAmount);
860
+ console.log(result.outputAmount);
861
+ console.log(result.priceImpactPct);
668
862
  ```
669
863
 
670
- ### Pump.fun
864
+ How it works:
671
865
 
672
- Requires: `pumpfun`
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
673
872
 
674
- The SDK uses REST paths under your endpoint:
873
+ ### `getPumpFunTokens(options?)`
675
874
 
676
- ```txt
677
- /pump-fun/coins
678
- /pump-fun/coins/:mint
679
- /pump-fun/coins/:mint/holders
680
- /pump-fun/trades/all
681
- ```
875
+ Gets recent pump.fun tokens.
682
876
 
683
- #### `kit.getPumpFunTokens(options?)`
877
+ Add-on required: `pumpfun`
684
878
 
685
879
  ```ts
686
880
  const tokens = await kit.getPumpFunTokens({
@@ -694,7 +888,15 @@ for (const token of tokens) {
694
888
  }
695
889
  ```
696
890
 
697
- #### `kit.getPumpFunToken(mint)`
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`
698
900
 
699
901
  ```ts
700
902
  const token = await kit.getPumpFunToken('TOKEN_MINT');
@@ -703,10 +905,17 @@ console.log(token.name);
703
905
  console.log(token.symbol);
704
906
  console.log(token.creator);
705
907
  console.log(token.price);
706
- console.log(token.bondingCurve.complete);
707
908
  ```
708
909
 
709
- #### `kit.getPumpFunTokensByCreator(options)`
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`
710
919
 
711
920
  ```ts
712
921
  const created = await kit.getPumpFunTokensByCreator({
@@ -716,7 +925,15 @@ const created = await kit.getPumpFunTokensByCreator({
716
925
  });
717
926
  ```
718
927
 
719
- #### `kit.getPumpFunTokenHolders(mint)`
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`
720
937
 
721
938
  ```ts
722
939
  const holders = await kit.getPumpFunTokenHolders('TOKEN_MINT');
@@ -726,7 +943,15 @@ for (const holder of holders.slice(0, 10)) {
726
943
  }
727
944
  ```
728
945
 
729
- #### `kit.getPumpFunTokenTrades(mint, options?)`
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`
730
955
 
731
956
  ```ts
732
957
  const trades = await kit.getPumpFunTokenTrades('TOKEN_MINT', {
@@ -739,13 +964,15 @@ for (const trade of trades) {
739
964
  }
740
965
  ```
741
966
 
742
- ### Stablecoin Balance API
967
+ How it works:
743
968
 
744
- Requires: `stablecoinBalance`
969
+ - calls REST route `/pump-fun/trades/all`
745
970
 
746
- Uses QuickNode custom RPC method `qn_getWalletStablecoinBalances`.
971
+ ### `getStablecoinBalance(options)`
747
972
 
748
- #### `kit.getStablecoinBalance(options)`
973
+ Gets stablecoin balances across multiple chains.
974
+
975
+ Add-on required: `stablecoinBalance`
749
976
 
750
977
  ```ts
751
978
  const balances = await kit.getStablecoinBalance({
@@ -753,7 +980,6 @@ const balances = await kit.getStablecoinBalance({
753
980
  chains: ['solana', 'ethereum', 'base'],
754
981
  });
755
982
 
756
- console.log(balances.walletAddress);
757
983
  console.log(balances.totalUsdValue);
758
984
 
759
985
  for (const balance of balances.balances) {
@@ -761,18 +987,15 @@ for (const balance of balances.balances) {
761
987
  }
762
988
  ```
763
989
 
764
- ### OpenOcean
990
+ How it works:
765
991
 
766
- Requires: `openocean`
992
+ - calls custom RPC method `qn_getWalletStablecoinBalances`
767
993
 
768
- The SDK uses REST paths under:
994
+ ### `getOpenOceanQuote(options)`
769
995
 
770
- ```txt
771
- /openocean/v4/solana/quote
772
- /openocean/v4/solana/swap_quote
773
- ```
996
+ Gets a swap quote from OpenOcean.
774
997
 
775
- #### `kit.getOpenOceanQuote(options)`
998
+ Add-on required: `openocean`
776
999
 
777
1000
  ```ts
778
1001
  const quote = await kit.getOpenOceanQuote({
@@ -788,9 +1011,15 @@ console.log(quote.minOutAmount);
788
1011
  console.log(quote.priceImpact);
789
1012
  ```
790
1013
 
791
- #### `kit.openOceanSwap(options)`
1014
+ How it works:
792
1015
 
793
- Like the Metis integration, this fetches a serialized transaction, signs locally, sends, then confirms.
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`
794
1023
 
795
1024
  ```ts
796
1025
  import bs58 from 'bs58';
@@ -812,24 +1041,19 @@ console.log(result.inAmount);
812
1041
  console.log(result.outAmount);
813
1042
  ```
814
1043
 
815
- #### `OO_TOKENS`
816
-
817
- ```ts
818
- import { OO_TOKENS } from 'quicknode-solana-kit';
819
-
820
- console.log(OO_TOKENS.SOL);
821
- console.log(OO_TOKENS.USDC);
822
- console.log(OO_TOKENS.USDT);
823
- console.log(OO_TOKENS.BONK);
824
- ```
1044
+ How it works:
825
1045
 
826
- ### MEV Protection
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
827
1051
 
828
- These methods accept a base64-encoded signed transaction and submit it through the add-on provider, then confirm using a normal Solana connection.
1052
+ ### `sendMerkleProtectedTransaction(options)`
829
1053
 
830
- #### `kit.sendMerkleProtectedTransaction(options)`
1054
+ Sends a signed transaction through Merkle for MEV protection.
831
1055
 
832
- Requires: `merkle`
1056
+ Add-on required: `merkle`
833
1057
 
834
1058
  ```ts
835
1059
  const result = await kit.sendMerkleProtectedTransaction({
@@ -839,12 +1063,18 @@ const result = await kit.sendMerkleProtectedTransaction({
839
1063
 
840
1064
  console.log(result.signature);
841
1065
  console.log(result.provider);
842
- console.log(result.confirmationMs);
843
1066
  ```
844
1067
 
845
- #### `kit.sendBlinkLabsTransaction(options)`
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.
846
1076
 
847
- Requires: `blinklabs`
1077
+ Add-on required: `blinklabs`
848
1078
 
849
1079
  ```ts
850
1080
  const result = await kit.sendBlinkLabsTransaction({
@@ -854,16 +1084,18 @@ const result = await kit.sendBlinkLabsTransaction({
854
1084
 
855
1085
  console.log(result.signature);
856
1086
  console.log(result.provider);
857
- console.log(result.confirmationMs);
858
1087
  ```
859
1088
 
860
- ### Iris Transaction Sender
1089
+ How it works:
1090
+
1091
+ - calls custom RPC method `blinklabs_sendTransaction`
1092
+ - confirms with normal Solana connection
861
1093
 
862
- Requires: `iris`
1094
+ ### `sendIrisTransaction(options)`
863
1095
 
864
- Uses QuickNode custom RPC method `iris_sendTransaction`.
1096
+ Sends a signed transaction through the Iris add-on.
865
1097
 
866
- #### `kit.sendIrisTransaction(options)`
1098
+ Add-on required: `iris`
867
1099
 
868
1100
  ```ts
869
1101
  const result = await kit.sendIrisTransaction({
@@ -877,13 +1109,16 @@ console.log(result.slot);
877
1109
  console.log(result.confirmationMs);
878
1110
  ```
879
1111
 
880
- ### GoldRush
1112
+ How it works:
1113
+
1114
+ - calls custom RPC method `iris_sendTransaction`
1115
+ - confirms with normal Solana RPC
881
1116
 
882
- Requires: `goldrush`
1117
+ ### `getGoldRushBalances(options)`
883
1118
 
884
- Uses REST paths under `/goldrush/v1`.
1119
+ Gets multichain balances through GoldRush.
885
1120
 
886
- #### `kit.getGoldRushBalances(options)`
1121
+ Add-on required: `goldrush`
887
1122
 
888
1123
  ```ts
889
1124
  const balances = await kit.getGoldRushBalances({
@@ -901,7 +1136,15 @@ for (const item of balances.items) {
901
1136
  }
902
1137
  ```
903
1138
 
904
- #### `kit.getGoldRushTransactions(options)`
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`
905
1148
 
906
1149
  ```ts
907
1150
  const txs = await kit.getGoldRushTransactions({
@@ -911,24 +1154,20 @@ const txs = await kit.getGoldRushTransactions({
911
1154
  pageNumber: 0,
912
1155
  });
913
1156
 
914
- console.log(txs.currentPage);
915
-
916
1157
  for (const tx of txs.items) {
917
1158
  console.log(tx.txHash, tx.successful, tx.value);
918
1159
  }
919
1160
  ```
920
1161
 
921
- ### Titan
1162
+ How it works:
922
1163
 
923
- Requires: `titan`
1164
+ - calls REST route under `/goldrush/v1/`
924
1165
 
925
- The SDK supports:
1166
+ ### `getTitanSwapQuote(options)`
926
1167
 
927
- - point-in-time quote
928
- - swap execution
929
- - quote streaming over WebSocket
1168
+ Gets a swap quote from Titan.
930
1169
 
931
- #### `kit.getTitanSwapQuote(options)`
1170
+ Add-on required: `titan`
932
1171
 
933
1172
  ```ts
934
1173
  const quote = await kit.getTitanSwapQuote({
@@ -940,11 +1179,18 @@ const quote = await kit.getTitanSwapQuote({
940
1179
 
941
1180
  console.log(quote.inAmount);
942
1181
  console.log(quote.outAmount);
943
- console.log(quote.minOutAmount);
944
1182
  console.log(quote.routes);
945
1183
  ```
946
1184
 
947
- #### `kit.titanSwap(options)`
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`
948
1194
 
949
1195
  ```ts
950
1196
  const result = await kit.titanSwap({
@@ -952,7 +1198,7 @@ const result = await kit.titanSwap({
952
1198
  outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
953
1199
  amount: '10000000',
954
1200
  slippageBps: 50,
955
- userPublicKey: walletPublicKey,
1201
+ userPublicKey: 'WALLET_PUBLIC_KEY',
956
1202
  });
957
1203
 
958
1204
  console.log(result.signature);
@@ -960,7 +1206,19 @@ console.log(result.inAmount);
960
1206
  console.log(result.outAmount);
961
1207
  ```
962
1208
 
963
- #### `kit.subscribeTitanQuotes(options, onQuote, onError?)`
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`
964
1222
 
965
1223
  ```ts
966
1224
  const unsubscribe = kit.subscribeTitanQuotes(
@@ -971,23 +1229,25 @@ const unsubscribe = kit.subscribeTitanQuotes(
971
1229
  slippageBps: 50,
972
1230
  },
973
1231
  (quote) => {
974
- console.log('quote', quote.outAmount, quote.priceImpactPct);
1232
+ console.log('quote', quote.outAmount);
975
1233
  },
976
1234
  (err) => {
977
1235
  console.error(err);
978
1236
  },
979
1237
  );
980
1238
 
981
- setTimeout(() => unsubscribe(), 15_000);
1239
+ setTimeout(() => unsubscribe(), 15000);
982
1240
  ```
983
1241
 
984
- ### Scorechain
1242
+ How it works:
985
1243
 
986
- Requires: `scorechain`
1244
+ - opens a WebSocket to the Titan stream route on your endpoint
987
1245
 
988
- Uses REST path `/scorechain/v1/risk`.
1246
+ ### `assessWalletRisk(options)`
989
1247
 
990
- #### `kit.assessWalletRisk(options)`
1248
+ Gets Scorechain risk information for a wallet.
1249
+
1250
+ Add-on required: `scorechain`
991
1251
 
992
1252
  ```ts
993
1253
  const assessment = await kit.assessWalletRisk({
@@ -1000,12 +1260,19 @@ console.log(assessment.riskScore);
1000
1260
  console.log(assessment.riskLevel);
1001
1261
  console.log(assessment.amlStatus);
1002
1262
  console.log(assessment.flags);
1003
- console.log(assessment.reportUrl);
1004
1263
  ```
1005
1264
 
1006
- #### `kit.isWalletSafe(address)`
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`
1007
1274
 
1008
- Returns `true` only when:
1275
+ This returns `true` only when:
1009
1276
 
1010
1277
  - `amlStatus === 'clean'`
1011
1278
  - `riskLevel === 'low'`
@@ -1015,6 +1282,42 @@ const safe = await kit.isWalletSafe('WALLET_ADDRESS');
1015
1282
  console.log(safe);
1016
1283
  ```
1017
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
+ ```
1320
+
1018
1321
  ## Error Handling
1019
1322
 
1020
1323
  The package exports custom errors:
@@ -1053,9 +1356,7 @@ try {
1053
1356
  }
1054
1357
  ```
1055
1358
 
1056
- ## Examples Included In The Package
1057
-
1058
- Run the examples from the package folder:
1359
+ ## Included Example Scripts
1059
1360
 
1060
1361
  ```bash
1061
1362
  npm run example:tx
@@ -1065,7 +1366,7 @@ npm run example:swap
1065
1366
  npm run example:all
1066
1367
  ```
1067
1368
 
1068
- Environment variables used by the examples:
1369
+ Suggested `.env` values:
1069
1370
 
1070
1371
  ```bash
1071
1372
  QN_ENDPOINT_URL=
@@ -1077,77 +1378,66 @@ ADDON_METIS=true
1077
1378
  EXECUTE_SWAP=false
1078
1379
  ```
1079
1380
 
1080
- ## Minimal Examples
1381
+ ## Recommended Learning Order
1382
+
1383
+ If you are new to Solana or QuickNode, this order works well:
1384
+
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()`
1081
1392
 
1082
- ### Minimal client
1393
+ ## Starter Example
1083
1394
 
1084
1395
  ```ts
1396
+ import { PublicKey } from '@solana/web3.js';
1085
1397
  import { QNSolanaKit } from 'quicknode-solana-kit';
1086
1398
 
1087
1399
  const kit = new QNSolanaKit({
1088
1400
  endpointUrl: process.env.QN_ENDPOINT_URL!,
1401
+ addOns: {
1402
+ priorityFees: true,
1403
+ das: true,
1404
+ },
1089
1405
  });
1090
- ```
1091
1406
 
1092
- ### Minimal fee estimate
1407
+ async function main() {
1408
+ const wallet = new PublicKey('E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk');
1093
1409
 
1094
- ```ts
1095
- const fees = await kit.estimatePriorityFees();
1096
- console.log(fees.recommended);
1097
- ```
1410
+ const balance = await kit.connection.getBalance(wallet);
1411
+ console.log('SOL balance:', balance / 1e9);
1098
1412
 
1099
- ### Minimal NFT query
1413
+ const tokenAccounts = await kit.getTokenAccounts(wallet.toString());
1414
+ console.log('Token accounts:', tokenAccounts.length);
1100
1415
 
1101
- ```ts
1102
- const assets = await kit.getAssetsByOwner({
1103
- ownerAddress: 'WALLET_ADDRESS',
1104
- });
1416
+ const fees = await kit.estimatePriorityFees();
1417
+ console.log('Recommended priority fee:', fees.recommended);
1105
1418
 
1106
- console.log(assets.items.length);
1107
- ```
1108
-
1109
- ### Minimal swap quote
1110
-
1111
- ```ts
1112
- import { TOKENS } from 'quicknode-solana-kit';
1113
-
1114
- const quote = await kit.getSwapQuote({
1115
- inputMint: TOKENS.SOL,
1116
- outputMint: TOKENS.USDC,
1117
- amount: BigInt(1_000_000_000),
1118
- });
1419
+ const assets = await kit.getAssetsByOwner({
1420
+ ownerAddress: wallet.toString(),
1421
+ limit: 5,
1422
+ });
1423
+ console.log('Assets:', assets.items.length);
1424
+ }
1119
1425
 
1120
- console.log(quote.outAmount);
1426
+ main().catch(console.error);
1121
1427
  ```
1122
1428
 
1123
- ## Notes and Current Limitations
1124
-
1125
- - `yellowstone` is exposed in config and add-on checks, but account streaming currently falls back to standard Solana WebSockets.
1126
- - `liljit` is probed by `checkAddOns()`, but `sendSmartTransaction()` does not currently route through Jito bundles yet.
1127
- - `sendSmartTransaction()` works without `priorityFees`, but falls back to a default compute unit price.
1128
- - some add-ons return serialized transactions; the SDK signs and sends those locally using `@solana/web3.js`
1129
-
1130
- ## Import Patterns
1429
+ ## Current Limitations
1131
1430
 
1132
- Class-based usage:
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
1133
1435
 
1134
- ```ts
1135
- import { QNSolanaKit } from 'quicknode-solana-kit';
1136
- ```
1436
+ ## Beginner Guide
1137
1437
 
1138
- Function-level usage:
1438
+ If you want a more beginner-first walkthrough, see:
1139
1439
 
1140
- ```ts
1141
- import {
1142
- estimatePriorityFees,
1143
- getAssetsByOwner,
1144
- getSwapQuote,
1145
- swap,
1146
- watchAccount,
1147
- TOKENS,
1148
- OO_TOKENS,
1149
- } from 'quicknode-solana-kit';
1150
- ```
1440
+ - [readmetounderstand.md](/home/rachit/Videos/QuickNode-Starter-Kit/qn-solana-kit-v2/readmetounderstand.md)
1151
1441
 
1152
1442
  ## License
1153
1443