solana-web3-on-steroids 1.0.2

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.
@@ -0,0 +1,323 @@
1
+ import { Connection } from '@solana/web3.js';
2
+ /**
3
+ * SteroidConnection uses a Proxy pattern to wrap a real @solana/web3.js Connection.
4
+ * This allows swapping the underlying connection (and its internal state/websockets)
5
+ * transparently when a failover occurs.
6
+ */
7
+ export class SteroidConnection {
8
+ static DEFAULT_HEALTH_CHECK_TIMEOUT_MS = 5000;
9
+ static MAX_BACKOFF_DELAY_MS = 10000;
10
+ static JITTER_MS = 100;
11
+ activeConnection;
12
+ urls;
13
+ currentUrlIndex = 0;
14
+ config;
15
+ steroidConfig;
16
+ healthStatus = new Map();
17
+ healthCheckTimer;
18
+ failoverCount = 0;
19
+ lastFailoverTime = 0;
20
+ constructor(endpoint, config = {}) {
21
+ this.urls = [endpoint, ...(config.fallbacks || [])];
22
+ this.config = config;
23
+ this.steroidConfig = {
24
+ maxRetries: config.maxRetries ?? 5,
25
+ retryDelay: config.retryDelay ?? 500,
26
+ healthCheckInterval: config.healthCheckInterval ?? 30000,
27
+ requestTimeout: config.requestTimeout ?? 30000,
28
+ enableLogging: config.enableLogging ?? false,
29
+ };
30
+ // Initialize health status
31
+ this.urls.forEach((url) => {
32
+ this.healthStatus.set(url, {
33
+ url,
34
+ healthy: true,
35
+ lastChecked: Date.now(),
36
+ });
37
+ });
38
+ this.activeConnection = new Connection(endpoint, config);
39
+ // Start health checks if enabled
40
+ if (this.steroidConfig.healthCheckInterval > 0) {
41
+ this.startHealthChecks();
42
+ }
43
+ // Return a Proxy so the user can treat it as a standard Connection object
44
+ return new Proxy(this, {
45
+ get(target, prop, receiver) {
46
+ // 1. If the property exists on our wrapper, use it.
47
+ if (prop in target) {
48
+ return Reflect.get(target, prop, receiver);
49
+ }
50
+ // 2. Otherwise, forward to the active Connection instance.
51
+ const value = Reflect.get(target.activeConnection, prop, target.activeConnection);
52
+ // 3. If it's a function, wrap it with retry/failover logic.
53
+ if (typeof value === 'function') {
54
+ return (...args) => target.executeWithResilience(prop, value, args);
55
+ }
56
+ return value;
57
+ },
58
+ });
59
+ }
60
+ /**
61
+ * Executes a connection method with intelligent retries and failover.
62
+ */
63
+ async executeWithResilience(methodName, method, args) {
64
+ const attemptedUrls = new Set();
65
+ let lastError;
66
+ for (let attempt = 0; attempt < this.steroidConfig.maxRetries; attempt++) {
67
+ try {
68
+ const result = await this.callWithTimeout(method, args, this.activeConnection, this.steroidConfig.requestTimeout);
69
+ this.updateHealthStatus(this.getActiveEndpoint(), true);
70
+ return result;
71
+ }
72
+ catch (error) {
73
+ // Map AbortError from our controller to a "Request timeout" message for consistency
74
+ lastError = error.name === 'AbortError' ? new Error('Request timeout') : error;
75
+ attemptedUrls.add(this.currentUrlIndex);
76
+ this.log('warn', `Method ${methodName} failed (attempt ${attempt + 1}/${this.steroidConfig.maxRetries}):`, lastError.message);
77
+ const shouldRetry = await this.handleExecutionError(lastError, methodName, attempt, attemptedUrls);
78
+ if (!shouldRetry) {
79
+ throw this.enhanceError(lastError, methodName, attempt + 1);
80
+ }
81
+ }
82
+ }
83
+ throw this.enhanceError(lastError, methodName, this.steroidConfig.maxRetries);
84
+ }
85
+ /**
86
+ * Internal helper to execute a method with a promise-based timeout and AbortController.
87
+ * This effectively cancels the underlying network request on timeout.
88
+ */
89
+ async callWithTimeout(method, args, target, timeoutMs) {
90
+ const controller = new AbortController();
91
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
92
+ try {
93
+ // 1. Check if the method likely accepts a config object with an AbortSignal
94
+ // Many web3.js methods take an optional config as the last argument
95
+ const lastArg = args[args.length - 1];
96
+ const methodWithSignal = (typeof lastArg === 'object' && lastArg !== null && !Array.isArray(lastArg))
97
+ ? method.apply(target, [...args.slice(0, -1), { ...lastArg, signal: controller.signal }])
98
+ : method.apply(target, [...args, { signal: controller.signal }]);
99
+ return await methodWithSignal;
100
+ }
101
+ finally {
102
+ clearTimeout(timeoutId);
103
+ }
104
+ }
105
+ /**
106
+ * Updates health status for a specific URL.
107
+ */
108
+ updateHealthStatus(url, healthy, latency) {
109
+ const health = this.healthStatus.get(url);
110
+ if (health) {
111
+ health.healthy = healthy;
112
+ health.lastChecked = Date.now();
113
+ if (latency !== undefined)
114
+ health.latency = latency;
115
+ }
116
+ }
117
+ /**
118
+ * Decides whether to retry or failover based on the error.
119
+ * @returns true if the loop should continue (retry or failover), false if it should throw.
120
+ */
121
+ async handleExecutionError(error, methodName, attempt, attemptedUrls) {
122
+ // 1. Transient Error (Rate limit, etc.) -> Just retry
123
+ if (this.isTransientError(error)) {
124
+ const delay = this.calculateBackoff(attempt + 1);
125
+ this.log('info', `Retrying after ${delay}ms due to transient error`);
126
+ await this.sleep(delay);
127
+ return true;
128
+ }
129
+ // 2. Node Failure -> Mark unhealthy and try next if available
130
+ if (this.isNodeFailure(error)) {
131
+ this.updateHealthStatus(this.urls[this.currentUrlIndex], false);
132
+ if (this.urls.length > 1 && attemptedUrls.size < this.urls.length) {
133
+ this.switchToNextRpc();
134
+ return true;
135
+ }
136
+ }
137
+ return false;
138
+ }
139
+ parseErrorContext(error) {
140
+ return {
141
+ message: error.message?.toLowerCase() || '',
142
+ statusCode: error.statusCode || error.status || 0,
143
+ };
144
+ }
145
+ /**
146
+ * Identifies transient errors that should be retried on the same node (e.g. rate limits).
147
+ */
148
+ isTransientError(error) {
149
+ const { message, statusCode } = this.parseErrorContext(error);
150
+ const TRANSIENT_MESSAGES = ['retry', '429', 'too many requests', 'rate limit'];
151
+ const TRANSIENT_STATUS_CODES = [429, 408];
152
+ const matchedMessage = TRANSIENT_MESSAGES.some((msg) => message.includes(msg));
153
+ const matchedCode = TRANSIENT_STATUS_CODES.includes(statusCode);
154
+ const isRpcTimeout = message.includes('timeout') && !message.includes('transaction');
155
+ return matchedMessage || matchedCode || isRpcTimeout;
156
+ }
157
+ /**
158
+ * Identifies node-level failures that should trigger a failover to a different RPC.
159
+ */
160
+ isNodeFailure(error) {
161
+ const { message, statusCode } = this.parseErrorContext(error);
162
+ const FAILURE_MESSAGES = [
163
+ 'fetch failed',
164
+ 'network error',
165
+ 'econnrefused',
166
+ 'enotfound',
167
+ 'etimedout',
168
+ '503',
169
+ '504',
170
+ '502',
171
+ 'connection reset',
172
+ ];
173
+ const FAILURE_STATUS_CODES = [502, 503, 504];
174
+ const matchedMessage = FAILURE_MESSAGES.some((msg) => message.includes(msg));
175
+ const matchedCode = FAILURE_STATUS_CODES.includes(statusCode);
176
+ return matchedMessage || matchedCode;
177
+ }
178
+ /**
179
+ * Switches to the next available RPC node.
180
+ */
181
+ switchToNextRpc() {
182
+ const nextIndex = this.findNextAvailableRpcIndex();
183
+ const previousUrl = this.urls[this.currentUrlIndex];
184
+ const nextUrl = this.urls[nextIndex];
185
+ this.currentUrlIndex = nextIndex;
186
+ this.failoverCount++;
187
+ this.lastFailoverTime = Date.now();
188
+ this.log('warn', `Failover triggered (#${this.failoverCount}). Switching from ${previousUrl} to ${nextUrl}`);
189
+ // Recreate the connection to clear internal state/websockets
190
+ this.activeConnection = new Connection(nextUrl, this.config);
191
+ }
192
+ /**
193
+ * Finds the index of the next healthy RPC, or the very next one if all are unhealthy.
194
+ */
195
+ findNextAvailableRpcIndex() {
196
+ const startIndex = (this.currentUrlIndex + 1) % this.urls.length;
197
+ // 1. Try to find the next healthy RPC starting from the next in line
198
+ for (let i = 0; i < this.urls.length; i++) {
199
+ const index = (startIndex + i) % this.urls.length;
200
+ if (this.healthStatus.get(this.urls[index])?.healthy) {
201
+ return index;
202
+ }
203
+ }
204
+ // 2. Fallback: if all are unhealthy, just try the very next one in the list
205
+ return startIndex;
206
+ }
207
+ calculateBackoff(attempt) {
208
+ const baseDelay = this.steroidConfig.retryDelay;
209
+ const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);
210
+ const jitter = Math.random() * SteroidConnection.JITTER_MS;
211
+ return Math.min(exponentialDelay + jitter, SteroidConnection.MAX_BACKOFF_DELAY_MS);
212
+ }
213
+ sleep(ms) {
214
+ return new Promise((resolve) => setTimeout(resolve, ms));
215
+ }
216
+ enhanceError(error, methodName, attempts) {
217
+ const enhancedError = new Error(`[SteroidConnection] ${methodName} failed after ${attempts} attempts. Last error: ${error.message}`);
218
+ enhancedError.originalError = error;
219
+ enhancedError.methodName = methodName;
220
+ enhancedError.attempts = attempts;
221
+ enhancedError.currentUrl = this.urls[this.currentUrlIndex];
222
+ return enhancedError;
223
+ }
224
+ log(level, ...args) {
225
+ if (!this.steroidConfig.enableLogging)
226
+ return;
227
+ const prefix = '[SteroidConnection]';
228
+ const finalArgs = [...args];
229
+ if (typeof finalArgs[0] === 'string') {
230
+ finalArgs[0] = `${prefix} ${finalArgs[0]}`;
231
+ }
232
+ else {
233
+ finalArgs.unshift(prefix);
234
+ }
235
+ switch (level) {
236
+ case 'info':
237
+ console.log(...finalArgs);
238
+ break;
239
+ case 'warn':
240
+ console.warn(...finalArgs);
241
+ break;
242
+ case 'error':
243
+ console.error(...finalArgs);
244
+ break;
245
+ }
246
+ }
247
+ /**
248
+ * Perform health checks on all RPC endpoints.
249
+ */
250
+ async performHealthCheck() {
251
+ const checks = this.urls.map((url) => this.checkNodeHealth(url));
252
+ await Promise.allSettled(checks);
253
+ }
254
+ /**
255
+ * Internal helper to check the health of a single RPC node.
256
+ */
257
+ async checkNodeHealth(url) {
258
+ const startTime = Date.now();
259
+ try {
260
+ const tempConn = new Connection(url, { commitment: 'confirmed' });
261
+ // We use getSlot as a lightweight "ping"
262
+ await this.callWithTimeout(tempConn.getSlot, [], tempConn, SteroidConnection.DEFAULT_HEALTH_CHECK_TIMEOUT_MS);
263
+ const latency = Date.now() - startTime;
264
+ this.updateHealthStatus(url, true, latency);
265
+ this.log('info', `Health check passed for ${url} (${latency}ms)`);
266
+ }
267
+ catch (error) {
268
+ this.updateHealthStatus(url, false);
269
+ this.log('warn', `Health check failed for ${url}:`, error.message);
270
+ }
271
+ }
272
+ startHealthChecks() {
273
+ this.healthCheckTimer = setInterval(() => {
274
+ this.performHealthCheck().catch((err) => {
275
+ this.log('error', 'Health check error:', err);
276
+ });
277
+ }, this.steroidConfig.healthCheckInterval);
278
+ }
279
+ /**
280
+ * Clean up resources when done.
281
+ */
282
+ destroy() {
283
+ if (this.healthCheckTimer) {
284
+ clearInterval(this.healthCheckTimer);
285
+ this.healthCheckTimer = undefined;
286
+ }
287
+ }
288
+ /**
289
+ * Get all endpoints for multi-node verification.
290
+ */
291
+ getEndpoints() {
292
+ return [...this.urls];
293
+ }
294
+ /**
295
+ * Get current active endpoint.
296
+ */
297
+ getActiveEndpoint() {
298
+ return this.urls[this.currentUrlIndex];
299
+ }
300
+ /**
301
+ * Get health status of all endpoints.
302
+ */
303
+ getHealthStatus() {
304
+ return Array.from(this.healthStatus.values());
305
+ }
306
+ /**
307
+ * Get failover statistics.
308
+ */
309
+ getFailoverStats() {
310
+ return {
311
+ count: this.failoverCount,
312
+ lastTime: this.lastFailoverTime,
313
+ };
314
+ }
315
+ /**
316
+ * Manually trigger a health check.
317
+ */
318
+ async checkHealth() {
319
+ await this.performHealthCheck();
320
+ return this.getHealthStatus();
321
+ }
322
+ }
323
+ //# sourceMappingURL=SteroidConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SteroidConnection.js","sourceRoot":"","sources":["../../src/connection/SteroidConnection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { SteroidClient, createSteroidClient } from './client/SteroidClient.js';
2
+ export { SteroidConnection } from './connection/SteroidConnection.js';
3
+ export { SteroidTransaction } from './transaction/SteroidTransaction.js';
4
+ export { SteroidWallet, WalletError } from './wallet/SteroidWallet.js';
5
+ export * from './types/SteroidWalletTypes.js';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { SteroidClient, createSteroidClient } from './client/SteroidClient.js';
2
+ export { SteroidConnection } from './connection/SteroidConnection.js';
3
+ export { SteroidTransaction } from './transaction/SteroidTransaction.js';
4
+ export { SteroidWallet, WalletError } from './wallet/SteroidWallet.js';
5
+ export * from './types/SteroidWalletTypes.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACvE,cAAc,+BAA+B,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { Transaction, TransactionSignature, VersionedTransaction } from '@solana/web3.js';
2
+ import { SteroidConnection } from '../connection/SteroidConnection.js';
3
+ import { SteroidSendOptions, TransactionStateInfo } from '../types/SteroidWalletTypes.js';
4
+ /**
5
+ * Enhanced transaction handling with state management, automatic retries,
6
+ * blockhash refresh, and multi-node confirmation.
7
+ */
8
+ export declare class SteroidTransaction {
9
+ private connection;
10
+ private transactionStates;
11
+ constructor(connection: SteroidConnection);
12
+ /**
13
+ * Sends a transaction with continuous re-broadcasting and multi-node monitoring.
14
+ * Includes automatic blockhash refresh and comprehensive error handling.
15
+ */
16
+ sendAndConfirm(transaction: Transaction | VersionedTransaction, options?: SteroidSendOptions): Promise<TransactionSignature>;
17
+ /**
18
+ * Simulates a transaction and provides detailed error information.
19
+ */
20
+ private simulateTransaction;
21
+ /**
22
+ * Polls multiple RPC endpoints for signature status to bypass node lag.
23
+ */
24
+ private pollForConfirmation;
25
+ /**
26
+ * Get fresh blockhash with retry logic.
27
+ */
28
+ private getFreshBlockhash;
29
+ /**
30
+ * Parse simulation errors into human-readable format.
31
+ */
32
+ private parseSimulationError;
33
+ private isBlockhashExpiredError;
34
+ /**
35
+ * Type guard for legacy transactions.
36
+ */
37
+ private isLegacyTransaction;
38
+ /**
39
+ * Serialize transaction to bytes.
40
+ */
41
+ private serializeTransaction;
42
+ private generateStateId;
43
+ private updateState;
44
+ private log;
45
+ private sleep;
46
+ /**
47
+ * Get the current state of a transaction.
48
+ */
49
+ getTransactionState(stateId: string): TransactionStateInfo | undefined;
50
+ /**
51
+ * Get all transaction states (useful for debugging).
52
+ */
53
+ getAllTransactionStates(): Map<string, TransactionStateInfo>;
54
+ /**
55
+ * Clear old transaction states (cleanup).
56
+ */
57
+ clearOldStates(olderThanMs?: number): void;
58
+ }