solana-priority-fee 1.0.0 → 1.1.0

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 (3) hide show
  1. package/fee.js +36 -0
  2. package/index.js +137 -21
  3. package/package.json +3 -2
package/fee.js ADDED
@@ -0,0 +1,36 @@
1
+ const { Connection, PublicKey } = require('@solana/web3.js');
2
+ const { SolanaFeeEstimator } = require('solana-priority-fee');
3
+
4
+ const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=af5cb288-41c0-4728-a606-fee9e27909ea');
5
+
6
+ // Hot DeFi accounts
7
+ const HOT_ACCOUNTS = [
8
+ new PublicKey('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'), // Raydium
9
+ new PublicKey('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), // Jupiter
10
+ new PublicKey('whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc'), // Orca
11
+ ];
12
+
13
+ // Convert to SOL (assuming 200k compute units)
14
+ function toSol(microlamports) {
15
+ return (microlamports * 200000) / 1_000_000 / 1_000_000_000;
16
+ }
17
+
18
+ async function main() {
19
+ console.log('Solana Priority Fees\n');
20
+
21
+ const estimator = new SolanaFeeEstimator(connection);
22
+ const fees = await estimator.getAllFees(HOT_ACCOUNTS);
23
+
24
+ console.log('┌──────────┬─────────────────┐');
25
+ console.log('│ Level │ Fee (SOL) │');
26
+ console.log('├──────────┼─────────────────┤');
27
+ console.log(`│ Economy │ ${toSol(fees.economy).toFixed(9)} │`);
28
+ console.log(`│ Medium │ ${toSol(fees.medium).toFixed(9)} │`);
29
+ console.log(`│ Fast │ ${toSol(fees.fast).toFixed(9)} │`);
30
+ console.log(`│ Urgent │ ${toSol(fees.urgent).toFixed(9)} │`);
31
+ console.log('└──────────┴─────────────────┘');
32
+
33
+ console.log(`\nBased on ${fees.raw.samples} recent transactions`);
34
+ }
35
+
36
+ main().catch(console.error);
package/index.js CHANGED
@@ -1,22 +1,20 @@
1
- const { Connection } = require('@solana/web3.js');
1
+ const { Connection, PublicKey } = require('@solana/web3.js');
2
2
 
3
3
  /**
4
- * SolanaFeeEstimator - Priority fee estimation with caching and monitoring
4
+ * SolanaFeeEstimator - Priority fee + Jito tip estimation
5
5
  */
6
6
  class SolanaFeeEstimator {
7
7
  constructor(connection, options = {}) {
8
8
  this.connection = connection;
9
9
 
10
- // Configuration
11
10
  this.config = {
12
- cacheMs: options.cacheMs ?? 5000, // Cache duration
13
- sampleSize: options.sampleSize ?? 150, // Recent slots to analyze
14
- minFee: options.minFee ?? 1000, // Minimum fee (microlamports)
15
- maxFee: options.maxFee ?? 10_000_000, // Maximum fee cap
11
+ cacheMs: options.cacheMs ?? 5000,
12
+ minFee: options.minFee ?? 1000,
13
+ maxFee: options.maxFee ?? 10_000_000,
14
+ jitoEndpoint: options.jitoEndpoint ?? 'https://bundles.jito.wtf/api/v1/bundles/tip_floor',
16
15
  ...options
17
16
  };
18
17
 
19
- // Percentiles for each level
20
18
  this.levels = {
21
19
  economy: 0.25,
22
20
  medium: 0.50,
@@ -24,22 +22,21 @@ class SolanaFeeEstimator {
24
22
  urgent: 0.95
25
23
  };
26
24
 
27
- // Cache
28
25
  this.cache = {
29
26
  global: null,
30
27
  accounts: new Map(),
31
- lastUpdate: 0
28
+ jito: null,
29
+ lastUpdate: 0,
30
+ jitoLastUpdate: 0
32
31
  };
33
32
 
34
- // Stats tracking
35
33
  this.stats = {
36
34
  requests: 0,
37
35
  cacheHits: 0,
38
- estimates: [], // { level, fee, timestamp }
39
- confirmed: [], // { level, fee, landed, timestamp }
36
+ estimates: [],
37
+ confirmed: [],
40
38
  };
41
39
 
42
- // WebSocket subscription
43
40
  this.subscription = null;
44
41
  this.realtimeFees = [];
45
42
  }
@@ -56,7 +53,6 @@ class SolanaFeeEstimator {
56
53
 
57
54
  this.stats.requests++;
58
55
 
59
- // Check cache
60
56
  const cacheKey = accountKeys.length > 0
61
57
  ? accountKeys.sort().join(',')
62
58
  : 'global';
@@ -66,13 +62,11 @@ class SolanaFeeEstimator {
66
62
  return this._calculateFee(this._getCachedFees(cacheKey), level);
67
63
  }
68
64
 
69
- // Fetch fresh data
70
65
  const fees = await this._fetchFees(accountKeys);
71
66
  this._updateCache(cacheKey, fees);
72
67
 
73
68
  const estimate = this._calculateFee(fees, level);
74
69
 
75
- // Track estimate
76
70
  this.stats.estimates.push({
77
71
  level,
78
72
  fee: estimate,
@@ -102,6 +96,122 @@ class SolanaFeeEstimator {
102
96
  };
103
97
  }
104
98
 
99
+ /**
100
+ * Get Jito tip recommendations (the real cost for fast landing)
101
+ */
102
+ async getJitoTips() {
103
+ const now = Date.now();
104
+
105
+ // Check cache
106
+ if (this.cache.jito && (now - this.cache.jitoLastUpdate) < this.config.cacheMs) {
107
+ return this.cache.jito;
108
+ }
109
+
110
+ try {
111
+ const response = await fetch(this.config.jitoEndpoint);
112
+ const data = await response.json();
113
+
114
+ // Jito returns tips in lamports
115
+ const tips = {
116
+ landed_tips_25th_percentile: data[0]?.landed_tips_25th_percentile ?? 0,
117
+ landed_tips_50th_percentile: data[0]?.landed_tips_50th_percentile ?? 0,
118
+ landed_tips_75th_percentile: data[0]?.landed_tips_75th_percentile ?? 0,
119
+ landed_tips_95th_percentile: data[0]?.landed_tips_95th_percentile ?? 0,
120
+ landed_tips_99th_percentile: data[0]?.landed_tips_99th_percentile ?? 0,
121
+ };
122
+
123
+ const result = {
124
+ // In SOL
125
+ economy: tips.landed_tips_25th_percentile / 1_000_000_000,
126
+ medium: tips.landed_tips_50th_percentile / 1_000_000_000,
127
+ fast: tips.landed_tips_75th_percentile / 1_000_000_000,
128
+ urgent: tips.landed_tips_95th_percentile / 1_000_000_000,
129
+ max: tips.landed_tips_99th_percentile / 1_000_000_000,
130
+ // Raw lamports
131
+ raw: tips
132
+ };
133
+
134
+ this.cache.jito = result;
135
+ this.cache.jitoLastUpdate = now;
136
+
137
+ return result;
138
+ } catch (error) {
139
+ console.error('Failed to fetch Jito tips:', error.message);
140
+ // Return defaults if API fails
141
+ return {
142
+ economy: 0.0001,
143
+ medium: 0.001,
144
+ fast: 0.01,
145
+ urgent: 0.05,
146
+ max: 0.1,
147
+ raw: null,
148
+ error: error.message
149
+ };
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Get total landing cost (priority fee + Jito tip)
155
+ */
156
+ async getTotalLandingCost(options = {}) {
157
+ const {
158
+ level = 'medium',
159
+ accountKeys = [],
160
+ computeUnits = 200000
161
+ } = options;
162
+
163
+ const [priorityFees, jitoTips] = await Promise.all([
164
+ this.getAllFees(accountKeys),
165
+ this.getJitoTips()
166
+ ]);
167
+
168
+ // Convert priority fee to SOL
169
+ const priorityFeeSol = (priorityFees[level] * computeUnits) / 1_000_000 / 1_000_000_000;
170
+ const jitoTipSol = jitoTips[level];
171
+
172
+ return {
173
+ priorityFee: priorityFeeSol,
174
+ jitoTip: jitoTipSol,
175
+ total: priorityFeeSol + jitoTipSol,
176
+ breakdown: {
177
+ priorityFee: `${priorityFeeSol.toFixed(9)} SOL`,
178
+ jitoTip: `${jitoTipSol.toFixed(9)} SOL`,
179
+ total: `${(priorityFeeSol + jitoTipSol).toFixed(9)} SOL`
180
+ }
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Get all costs for all levels
186
+ */
187
+ async getAllCosts(accountKeys = [], computeUnits = 200000) {
188
+ const [priorityFees, jitoTips] = await Promise.all([
189
+ this.getAllFees(accountKeys),
190
+ this.getJitoTips()
191
+ ]);
192
+
193
+ const levels = ['economy', 'medium', 'fast', 'urgent'];
194
+ const result = {};
195
+
196
+ for (const level of levels) {
197
+ const priorityFeeSol = (priorityFees[level] * computeUnits) / 1_000_000 / 1_000_000_000;
198
+ const jitoTipSol = jitoTips[level];
199
+
200
+ result[level] = {
201
+ priorityFee: priorityFeeSol,
202
+ jitoTip: jitoTipSol,
203
+ total: priorityFeeSol + jitoTipSol
204
+ };
205
+ }
206
+
207
+ result.raw = {
208
+ priorityFees: priorityFees.raw,
209
+ jitoTips: jitoTips.raw
210
+ };
211
+
212
+ return result;
213
+ }
214
+
105
215
  /**
106
216
  * Start real-time monitoring via WebSocket
107
217
  */
@@ -111,7 +221,6 @@ class SolanaFeeEstimator {
111
221
  return;
112
222
  }
113
223
 
114
- // Subscribe to slot changes
115
224
  this.subscription = this.connection.onSlotChange(async (slotInfo) => {
116
225
  try {
117
226
  const fees = await this._fetchFees([]);
@@ -127,7 +236,6 @@ class SolanaFeeEstimator {
127
236
 
128
237
  this.realtimeFees.push(allFees);
129
238
 
130
- // Keep last 100 samples
131
239
  if (this.realtimeFees.length > 100) {
132
240
  this.realtimeFees.shift();
133
241
  }
@@ -163,7 +271,6 @@ class SolanaFeeEstimator {
163
271
  timestamp: Date.now()
164
272
  });
165
273
 
166
- // Keep last 1000 results
167
274
  if (this.stats.confirmed.length > 1000) {
168
275
  this.stats.confirmed.shift();
169
276
  }
@@ -288,7 +395,6 @@ class SolanaFeeEstimator {
288
395
  } else {
289
396
  this.cache.accounts.set(key, { fees, timestamp: now });
290
397
 
291
- // Limit account cache size
292
398
  if (this.cache.accounts.size > 100) {
293
399
  const oldest = [...this.cache.accounts.entries()]
294
400
  .sort((a, b) => a[1].timestamp - b[1].timestamp)[0];
@@ -306,6 +412,15 @@ async function getPriorityFee(connection, level = 'medium', accountKeys = []) {
306
412
  return estimator.getFee({ level, accountKeys });
307
413
  }
308
414
 
415
+ /**
416
+ * Get Jito tips quickly
417
+ */
418
+ async function getJitoTip(level = 'medium') {
419
+ const estimator = new SolanaFeeEstimator(null);
420
+ const tips = await estimator.getJitoTips();
421
+ return tips[level];
422
+ }
423
+
309
424
  /**
310
425
  * Create compute budget instruction with estimated fee
311
426
  */
@@ -322,5 +437,6 @@ async function createPriorityFeeInstruction(connection, level = 'medium', accoun
322
437
  module.exports = {
323
438
  SolanaFeeEstimator,
324
439
  getPriorityFee,
440
+ getJitoTip,
325
441
  createPriorityFeeInstruction
326
442
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solana-priority-fee",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Priority fee estimation for Solana with caching, monitoring, and success tracking",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -16,6 +16,7 @@
16
16
  "author": "",
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
- "@solana/web3.js": "^1.98.4"
19
+ "@solana/web3.js": "^1.98.4",
20
+ "solana-priority-fee": "^1.0.0"
20
21
  }
21
22
  }