@shadow-corp/nearconnect 1.0.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.
- package/README.md +546 -0
- package/build/InjectedWallet.d.ts +22 -0
- package/build/InjectedWallet.js +58 -0
- package/build/InjectedWallet.js.map +1 -0
- package/build/NearConnector.d.ts +151 -0
- package/build/NearConnector.js +536 -0
- package/build/NearConnector.js.map +1 -0
- package/build/ParentFrameWallet.d.ts +22 -0
- package/build/ParentFrameWallet.js +66 -0
- package/build/ParentFrameWallet.js.map +1 -0
- package/build/SandboxedWallet/code.d.ts +7 -0
- package/build/SandboxedWallet/code.js +324 -0
- package/build/SandboxedWallet/code.js.map +1 -0
- package/build/SandboxedWallet/executor.d.ts +23 -0
- package/build/SandboxedWallet/executor.js +338 -0
- package/build/SandboxedWallet/executor.js.map +1 -0
- package/build/SandboxedWallet/iframe.d.ts +18 -0
- package/build/SandboxedWallet/iframe.js +78 -0
- package/build/SandboxedWallet/iframe.js.map +1 -0
- package/build/SandboxedWallet/index.d.ts +24 -0
- package/build/SandboxedWallet/index.js +54 -0
- package/build/SandboxedWallet/index.js.map +1 -0
- package/build/actions/index.d.ts +3 -0
- package/build/actions/index.js +105 -0
- package/build/actions/index.js.map +1 -0
- package/build/actions/types.d.ts +76 -0
- package/build/actions/types.js +3 -0
- package/build/actions/types.js.map +1 -0
- package/build/connection/health.d.ts +213 -0
- package/build/connection/health.js +391 -0
- package/build/connection/health.js.map +1 -0
- package/build/connection/index.d.ts +4 -0
- package/build/connection/index.js +48 -0
- package/build/connection/index.js.map +1 -0
- package/build/connection/reconnect.d.ts +261 -0
- package/build/connection/reconnect.js +454 -0
- package/build/connection/reconnect.js.map +1 -0
- package/build/connection/retry.d.ts +187 -0
- package/build/connection/retry.js +427 -0
- package/build/connection/retry.js.map +1 -0
- package/build/connection/state.d.ts +222 -0
- package/build/connection/state.js +431 -0
- package/build/connection/state.js.map +1 -0
- package/build/errors.d.ts +177 -0
- package/build/errors.js +546 -0
- package/build/errors.js.map +1 -0
- package/build/hardware/errors.d.ts +36 -0
- package/build/hardware/errors.js +127 -0
- package/build/hardware/errors.js.map +1 -0
- package/build/hardware/index.d.ts +7 -0
- package/build/hardware/index.js +39 -0
- package/build/hardware/index.js.map +1 -0
- package/build/hardware/near-app.d.ts +95 -0
- package/build/hardware/near-app.js +291 -0
- package/build/hardware/near-app.js.map +1 -0
- package/build/hardware/transport.d.ts +94 -0
- package/build/hardware/transport.js +267 -0
- package/build/hardware/transport.js.map +1 -0
- package/build/hardware/types.d.ts +98 -0
- package/build/hardware/types.js +72 -0
- package/build/hardware/types.js.map +1 -0
- package/build/helpers/analytics.d.ts +191 -0
- package/build/helpers/analytics.js +304 -0
- package/build/helpers/analytics.js.map +1 -0
- package/build/helpers/base58.d.ts +6 -0
- package/build/helpers/base58.js +47 -0
- package/build/helpers/base58.js.map +1 -0
- package/build/helpers/events.d.ts +42 -0
- package/build/helpers/events.js +68 -0
- package/build/helpers/events.js.map +1 -0
- package/build/helpers/html.d.ts +8 -0
- package/build/helpers/html.js +30 -0
- package/build/helpers/html.js.map +1 -0
- package/build/helpers/indexdb.d.ts +14 -0
- package/build/helpers/indexdb.js +166 -0
- package/build/helpers/indexdb.js.map +1 -0
- package/build/helpers/manifest.d.ts +147 -0
- package/build/helpers/manifest.js +329 -0
- package/build/helpers/manifest.js.map +1 -0
- package/build/helpers/queue.d.ts +11 -0
- package/build/helpers/queue.js +48 -0
- package/build/helpers/queue.js.map +1 -0
- package/build/helpers/session.d.ts +119 -0
- package/build/helpers/session.js +289 -0
- package/build/helpers/session.js.map +1 -0
- package/build/helpers/simulation.d.ts +128 -0
- package/build/helpers/simulation.js +441 -0
- package/build/helpers/simulation.js.map +1 -0
- package/build/helpers/storage.d.ts +58 -0
- package/build/helpers/storage.js +190 -0
- package/build/helpers/storage.js.map +1 -0
- package/build/helpers/trust.d.ts +157 -0
- package/build/helpers/trust.js +340 -0
- package/build/helpers/trust.js.map +1 -0
- package/build/helpers/url.d.ts +1 -0
- package/build/helpers/url.js +13 -0
- package/build/helpers/url.js.map +1 -0
- package/build/helpers/uuid.d.ts +1 -0
- package/build/helpers/uuid.js +14 -0
- package/build/helpers/uuid.js.map +1 -0
- package/build/index.d.ts +21 -0
- package/build/index.js +167 -0
- package/build/index.js.map +1 -0
- package/build/popups/IframeWalletPopup.d.ts +16 -0
- package/build/popups/IframeWalletPopup.js +38 -0
- package/build/popups/IframeWalletPopup.js.map +1 -0
- package/build/popups/NearWalletsPopup.d.ts +25 -0
- package/build/popups/NearWalletsPopup.js +153 -0
- package/build/popups/NearWalletsPopup.js.map +1 -0
- package/build/popups/Popup.d.ts +22 -0
- package/build/popups/Popup.js +94 -0
- package/build/popups/Popup.js.map +1 -0
- package/build/popups/styles.d.ts +1 -0
- package/build/popups/styles.js +257 -0
- package/build/popups/styles.js.map +1 -0
- package/build/security/audit-log.d.ts +123 -0
- package/build/security/audit-log.js +268 -0
- package/build/security/audit-log.js.map +1 -0
- package/build/security/csp.d.ts +68 -0
- package/build/security/csp.js +328 -0
- package/build/security/csp.js.map +1 -0
- package/build/security/index.d.ts +10 -0
- package/build/security/index.js +42 -0
- package/build/security/index.js.map +1 -0
- package/build/security/origin-guard.d.ts +90 -0
- package/build/security/origin-guard.js +244 -0
- package/build/security/origin-guard.js.map +1 -0
- package/build/security/rate-limiter.d.ts +84 -0
- package/build/security/rate-limiter.js +212 -0
- package/build/security/rate-limiter.js.map +1 -0
- package/build/security/secure-storage.d.ts +77 -0
- package/build/security/secure-storage.js +242 -0
- package/build/security/secure-storage.js.map +1 -0
- package/build/security/transaction-guard.d.ts +71 -0
- package/build/security/transaction-guard.js +239 -0
- package/build/security/transaction-guard.js.map +1 -0
- package/build/types.d.ts +508 -0
- package/build/types.js +3 -0
- package/build/types.js.map +1 -0
- package/build/ui/AccountSwitcherModal.d.ts +53 -0
- package/build/ui/AccountSwitcherModal.js +239 -0
- package/build/ui/AccountSwitcherModal.js.map +1 -0
- package/build/ui/Modal.d.ts +84 -0
- package/build/ui/Modal.js +278 -0
- package/build/ui/Modal.js.map +1 -0
- package/build/ui/TransactionModal.d.ts +84 -0
- package/build/ui/TransactionModal.js +406 -0
- package/build/ui/TransactionModal.js.map +1 -0
- package/build/ui/WalletSelectorModal.d.ts +97 -0
- package/build/ui/WalletSelectorModal.js +481 -0
- package/build/ui/WalletSelectorModal.js.map +1 -0
- package/build/ui/icons.d.ts +19 -0
- package/build/ui/icons.js +65 -0
- package/build/ui/icons.js.map +1 -0
- package/build/ui/index.d.ts +10 -0
- package/build/ui/index.js +31 -0
- package/build/ui/index.js.map +1 -0
- package/build/ui/styles.d.ts +5 -0
- package/build/ui/styles.js +973 -0
- package/build/ui/styles.js.map +1 -0
- package/build/ui/theme.d.ts +133 -0
- package/build/ui/theme.js +204 -0
- package/build/ui/theme.js.map +1 -0
- package/build/wallets/external/index.d.ts +4 -0
- package/build/wallets/external/index.js +9 -0
- package/build/wallets/external/index.js.map +1 -0
- package/build/wallets/external/manager.d.ts +152 -0
- package/build/wallets/external/manager.js +586 -0
- package/build/wallets/external/manager.js.map +1 -0
- package/build/wallets/privileged/index.d.ts +5 -0
- package/build/wallets/privileged/index.js +12 -0
- package/build/wallets/privileged/index.js.map +1 -0
- package/build/wallets/privileged/ledger.d.ts +132 -0
- package/build/wallets/privileged/ledger.js +563 -0
- package/build/wallets/privileged/ledger.js.map +1 -0
- package/build/wallets/privileged/manager.d.ts +54 -0
- package/build/wallets/privileged/manager.js +174 -0
- package/build/wallets/privileged/manager.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CircuitBreaker = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.DEFAULT_TIMEOUT_CONFIG = exports.DEFAULT_RETRY_CONFIG = void 0;
|
|
4
|
+
exports.calculateBackoffDelay = calculateBackoffDelay;
|
|
5
|
+
exports.isRetryableError = isRetryableError;
|
|
6
|
+
exports.withRetry = withRetry;
|
|
7
|
+
exports.withTimeout = withTimeout;
|
|
8
|
+
exports.withRetryAndTimeout = withRetryAndTimeout;
|
|
9
|
+
exports.createRetryWrapper = createRetryWrapper;
|
|
10
|
+
exports.createTimeoutWrapper = createTimeoutWrapper;
|
|
11
|
+
exports.makeCancellable = makeCancellable;
|
|
12
|
+
const errors_1 = require("../errors");
|
|
13
|
+
/**
|
|
14
|
+
* Default retry configuration
|
|
15
|
+
*/
|
|
16
|
+
exports.DEFAULT_RETRY_CONFIG = {
|
|
17
|
+
maxAttempts: 3,
|
|
18
|
+
baseDelay: 1000,
|
|
19
|
+
maxDelay: 30000,
|
|
20
|
+
backoffMultiplier: 2,
|
|
21
|
+
jitter: true,
|
|
22
|
+
retryableErrors: [
|
|
23
|
+
errors_1.ErrorCode.CONNECTION_TIMEOUT,
|
|
24
|
+
errors_1.ErrorCode.RPC_ERROR,
|
|
25
|
+
errors_1.ErrorCode.NETWORK_MISMATCH,
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Default timeout configuration
|
|
30
|
+
*/
|
|
31
|
+
exports.DEFAULT_TIMEOUT_CONFIG = {
|
|
32
|
+
connection: 30000,
|
|
33
|
+
signTransaction: 120000,
|
|
34
|
+
signMessage: 60000,
|
|
35
|
+
broadcast: 60000,
|
|
36
|
+
warningThreshold: 0.8,
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Default circuit breaker configuration
|
|
40
|
+
*/
|
|
41
|
+
exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
42
|
+
failureThreshold: 5,
|
|
43
|
+
cooldownPeriod: 60000,
|
|
44
|
+
healthCheckInterval: 10000,
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Calculate delay for a given attempt with exponential backoff
|
|
48
|
+
*/
|
|
49
|
+
function calculateBackoffDelay(attempt, config) {
|
|
50
|
+
// Exponential backoff: baseDelay * (multiplier ^ attempt)
|
|
51
|
+
let delay = config.baseDelay * Math.pow(config.backoffMultiplier, attempt);
|
|
52
|
+
// Cap at maxDelay
|
|
53
|
+
delay = Math.min(delay, config.maxDelay);
|
|
54
|
+
// Add jitter (±25% randomization)
|
|
55
|
+
if (config.jitter) {
|
|
56
|
+
const jitterFactor = 0.75 + Math.random() * 0.5; // 0.75 to 1.25
|
|
57
|
+
delay = Math.floor(delay * jitterFactor);
|
|
58
|
+
}
|
|
59
|
+
return delay;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if an error is retryable based on config
|
|
63
|
+
*/
|
|
64
|
+
function isRetryableError(error, config) {
|
|
65
|
+
if (config.shouldRetry) {
|
|
66
|
+
return config.shouldRetry(error, 0);
|
|
67
|
+
}
|
|
68
|
+
if (error instanceof errors_1.WalletError) {
|
|
69
|
+
return config.retryableErrors.includes(error.code);
|
|
70
|
+
}
|
|
71
|
+
// Network errors are generally retryable
|
|
72
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Execute an operation with retry logic
|
|
79
|
+
*/
|
|
80
|
+
async function withRetry(operation, config = {}) {
|
|
81
|
+
const fullConfig = { ...exports.DEFAULT_RETRY_CONFIG, ...config };
|
|
82
|
+
let lastError;
|
|
83
|
+
for (let attempt = 0; attempt < fullConfig.maxAttempts; attempt++) {
|
|
84
|
+
try {
|
|
85
|
+
return await operation();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
lastError = error;
|
|
89
|
+
// Check if we should retry
|
|
90
|
+
const shouldRetry = fullConfig.shouldRetry
|
|
91
|
+
? fullConfig.shouldRetry(error, attempt)
|
|
92
|
+
: isRetryableError(error, fullConfig);
|
|
93
|
+
if (!shouldRetry || attempt >= fullConfig.maxAttempts - 1) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
// Calculate delay for next attempt
|
|
97
|
+
const delay = calculateBackoffDelay(attempt, fullConfig);
|
|
98
|
+
// Notify about retry
|
|
99
|
+
fullConfig.onRetry?.(attempt + 1, delay, error);
|
|
100
|
+
// Wait before retrying
|
|
101
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// All retries exhausted
|
|
105
|
+
fullConfig.onExhausted?.(lastError, fullConfig.maxAttempts);
|
|
106
|
+
throw lastError;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Execute an operation with timeout
|
|
110
|
+
*/
|
|
111
|
+
async function withTimeout(operation, timeoutMs, operationName = "operation", onWarning, warningThreshold = 0.8) {
|
|
112
|
+
return new Promise((resolve, reject) => {
|
|
113
|
+
let warningTimer = null;
|
|
114
|
+
let completed = false;
|
|
115
|
+
// Set up warning timer
|
|
116
|
+
if (onWarning && warningThreshold > 0 && warningThreshold < 1) {
|
|
117
|
+
const warningTime = timeoutMs * warningThreshold;
|
|
118
|
+
warningTimer = setTimeout(() => {
|
|
119
|
+
if (!completed) {
|
|
120
|
+
onWarning(warningTime, timeoutMs);
|
|
121
|
+
}
|
|
122
|
+
}, warningTime);
|
|
123
|
+
}
|
|
124
|
+
// Set up timeout
|
|
125
|
+
const timeoutId = setTimeout(() => {
|
|
126
|
+
if (!completed) {
|
|
127
|
+
completed = true;
|
|
128
|
+
if (warningTimer)
|
|
129
|
+
clearTimeout(warningTimer);
|
|
130
|
+
reject(new errors_1.WalletError({
|
|
131
|
+
code: errors_1.ErrorCode.CONNECTION_TIMEOUT,
|
|
132
|
+
message: `${operationName} timed out after ${timeoutMs}ms`,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
}, timeoutMs);
|
|
136
|
+
// Execute operation
|
|
137
|
+
operation()
|
|
138
|
+
.then((result) => {
|
|
139
|
+
if (!completed) {
|
|
140
|
+
completed = true;
|
|
141
|
+
clearTimeout(timeoutId);
|
|
142
|
+
if (warningTimer)
|
|
143
|
+
clearTimeout(warningTimer);
|
|
144
|
+
resolve(result);
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
.catch((error) => {
|
|
148
|
+
if (!completed) {
|
|
149
|
+
completed = true;
|
|
150
|
+
clearTimeout(timeoutId);
|
|
151
|
+
if (warningTimer)
|
|
152
|
+
clearTimeout(warningTimer);
|
|
153
|
+
reject(error);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Combine retry and timeout
|
|
160
|
+
*/
|
|
161
|
+
async function withRetryAndTimeout(operation, timeoutMs, retryConfig = {}, operationName = "operation") {
|
|
162
|
+
return withRetry(() => withTimeout(operation, timeoutMs, operationName), retryConfig);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Circuit Breaker
|
|
166
|
+
*
|
|
167
|
+
* Prevents hammering a failing wallet by temporarily disabling connections
|
|
168
|
+
*/
|
|
169
|
+
class CircuitBreaker {
|
|
170
|
+
circuits = new Map();
|
|
171
|
+
config;
|
|
172
|
+
healthCheckTimers = new Map();
|
|
173
|
+
constructor(config = {}) {
|
|
174
|
+
this.config = { ...exports.DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get or create circuit entry for a wallet
|
|
178
|
+
*/
|
|
179
|
+
getCircuit(walletId) {
|
|
180
|
+
let circuit = this.circuits.get(walletId);
|
|
181
|
+
if (!circuit) {
|
|
182
|
+
circuit = {
|
|
183
|
+
state: "closed",
|
|
184
|
+
failures: 0,
|
|
185
|
+
lastFailure: 0,
|
|
186
|
+
lastSuccess: 0,
|
|
187
|
+
openedAt: null,
|
|
188
|
+
};
|
|
189
|
+
this.circuits.set(walletId, circuit);
|
|
190
|
+
}
|
|
191
|
+
return circuit;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Check if a wallet's circuit allows requests
|
|
195
|
+
*/
|
|
196
|
+
isAllowed(walletId) {
|
|
197
|
+
const circuit = this.getCircuit(walletId);
|
|
198
|
+
switch (circuit.state) {
|
|
199
|
+
case "closed":
|
|
200
|
+
return true;
|
|
201
|
+
case "open":
|
|
202
|
+
// Check if cooldown has passed
|
|
203
|
+
if (circuit.openedAt && Date.now() - circuit.openedAt >= this.config.cooldownPeriod) {
|
|
204
|
+
this.transitionTo(walletId, "half-open");
|
|
205
|
+
return true; // Allow one test request
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
case "half-open":
|
|
209
|
+
// Only allow one request at a time in half-open state
|
|
210
|
+
return true;
|
|
211
|
+
default:
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Record a successful operation
|
|
217
|
+
*/
|
|
218
|
+
recordSuccess(walletId) {
|
|
219
|
+
const circuit = this.getCircuit(walletId);
|
|
220
|
+
circuit.lastSuccess = Date.now();
|
|
221
|
+
if (circuit.state === "half-open") {
|
|
222
|
+
// Success in half-open state closes the circuit
|
|
223
|
+
this.transitionTo(walletId, "closed");
|
|
224
|
+
circuit.failures = 0;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Record a failed operation
|
|
229
|
+
*/
|
|
230
|
+
recordFailure(walletId) {
|
|
231
|
+
const circuit = this.getCircuit(walletId);
|
|
232
|
+
circuit.failures++;
|
|
233
|
+
circuit.lastFailure = Date.now();
|
|
234
|
+
if (circuit.state === "half-open") {
|
|
235
|
+
// Failure in half-open state re-opens the circuit
|
|
236
|
+
this.transitionTo(walletId, "open");
|
|
237
|
+
}
|
|
238
|
+
else if (circuit.state === "closed" &&
|
|
239
|
+
circuit.failures >= this.config.failureThreshold) {
|
|
240
|
+
// Too many failures, open the circuit
|
|
241
|
+
this.transitionTo(walletId, "open");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Transition circuit to a new state
|
|
246
|
+
*/
|
|
247
|
+
transitionTo(walletId, state) {
|
|
248
|
+
const circuit = this.getCircuit(walletId);
|
|
249
|
+
const previousState = circuit.state;
|
|
250
|
+
circuit.state = state;
|
|
251
|
+
// Handle state-specific actions
|
|
252
|
+
switch (state) {
|
|
253
|
+
case "open":
|
|
254
|
+
circuit.openedAt = Date.now();
|
|
255
|
+
this.config.onOpen?.(walletId, circuit.failures);
|
|
256
|
+
this.scheduleHealthCheck(walletId);
|
|
257
|
+
break;
|
|
258
|
+
case "closed":
|
|
259
|
+
circuit.openedAt = null;
|
|
260
|
+
circuit.failures = 0;
|
|
261
|
+
this.config.onClose?.(walletId);
|
|
262
|
+
this.cancelHealthCheck(walletId);
|
|
263
|
+
break;
|
|
264
|
+
case "half-open":
|
|
265
|
+
this.config.onHalfOpen?.(walletId);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Schedule health check for an open circuit
|
|
271
|
+
*/
|
|
272
|
+
scheduleHealthCheck(walletId) {
|
|
273
|
+
// Cancel existing timer
|
|
274
|
+
this.cancelHealthCheck(walletId);
|
|
275
|
+
// Schedule check at cooldown period
|
|
276
|
+
const timer = setTimeout(() => {
|
|
277
|
+
const circuit = this.getCircuit(walletId);
|
|
278
|
+
if (circuit.state === "open") {
|
|
279
|
+
this.transitionTo(walletId, "half-open");
|
|
280
|
+
}
|
|
281
|
+
}, this.config.cooldownPeriod);
|
|
282
|
+
this.healthCheckTimers.set(walletId, timer);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Cancel health check timer
|
|
286
|
+
*/
|
|
287
|
+
cancelHealthCheck(walletId) {
|
|
288
|
+
const timer = this.healthCheckTimers.get(walletId);
|
|
289
|
+
if (timer) {
|
|
290
|
+
clearTimeout(timer);
|
|
291
|
+
this.healthCheckTimers.delete(walletId);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Manually reset a circuit
|
|
296
|
+
*/
|
|
297
|
+
reset(walletId) {
|
|
298
|
+
this.cancelHealthCheck(walletId);
|
|
299
|
+
const circuit = this.getCircuit(walletId);
|
|
300
|
+
circuit.state = "closed";
|
|
301
|
+
circuit.failures = 0;
|
|
302
|
+
circuit.openedAt = null;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Manually reset all circuits
|
|
306
|
+
*/
|
|
307
|
+
resetAll() {
|
|
308
|
+
for (const walletId of this.circuits.keys()) {
|
|
309
|
+
this.reset(walletId);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Get circuit state for a wallet
|
|
314
|
+
*/
|
|
315
|
+
getState(walletId) {
|
|
316
|
+
return this.getCircuit(walletId).state;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get circuit info for a wallet
|
|
320
|
+
*/
|
|
321
|
+
getInfo(walletId) {
|
|
322
|
+
const circuit = this.getCircuit(walletId);
|
|
323
|
+
let remainingCooldown = null;
|
|
324
|
+
if (circuit.state === "open" && circuit.openedAt) {
|
|
325
|
+
const elapsed = Date.now() - circuit.openedAt;
|
|
326
|
+
remainingCooldown = Math.max(0, this.config.cooldownPeriod - elapsed);
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
state: circuit.state,
|
|
330
|
+
failures: circuit.failures,
|
|
331
|
+
lastFailure: circuit.lastFailure,
|
|
332
|
+
lastSuccess: circuit.lastSuccess,
|
|
333
|
+
remainingCooldown,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get all circuit states
|
|
338
|
+
*/
|
|
339
|
+
getAllStates() {
|
|
340
|
+
const states = {};
|
|
341
|
+
for (const [walletId, circuit] of this.circuits) {
|
|
342
|
+
states[walletId] = circuit.state;
|
|
343
|
+
}
|
|
344
|
+
return states;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Execute an operation through the circuit breaker
|
|
348
|
+
*/
|
|
349
|
+
async execute(walletId, operation) {
|
|
350
|
+
if (!this.isAllowed(walletId)) {
|
|
351
|
+
const info = this.getInfo(walletId);
|
|
352
|
+
throw new errors_1.WalletError({
|
|
353
|
+
code: errors_1.ErrorCode.CONNECTION_TIMEOUT,
|
|
354
|
+
message: `Circuit breaker open for wallet ${walletId}. Try again in ${info.remainingCooldown}ms`,
|
|
355
|
+
walletId,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
const result = await operation();
|
|
360
|
+
this.recordSuccess(walletId);
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
this.recordFailure(walletId);
|
|
365
|
+
throw error;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Cleanup all timers
|
|
370
|
+
*/
|
|
371
|
+
destroy() {
|
|
372
|
+
for (const timer of this.healthCheckTimers.values()) {
|
|
373
|
+
clearTimeout(timer);
|
|
374
|
+
}
|
|
375
|
+
this.healthCheckTimers.clear();
|
|
376
|
+
this.circuits.clear();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
exports.CircuitBreaker = CircuitBreaker;
|
|
380
|
+
/**
|
|
381
|
+
* Create a retry wrapper with default configuration
|
|
382
|
+
*/
|
|
383
|
+
function createRetryWrapper(config = {}) {
|
|
384
|
+
const fullConfig = { ...exports.DEFAULT_RETRY_CONFIG, ...config };
|
|
385
|
+
return (operation) => withRetry(operation, fullConfig);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Create a timeout wrapper with default configuration
|
|
389
|
+
*/
|
|
390
|
+
function createTimeoutWrapper(timeoutMs, operationName, onWarning) {
|
|
391
|
+
return (operation) => withTimeout(operation, timeoutMs, operationName, onWarning);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Create a cancellable operation
|
|
395
|
+
*/
|
|
396
|
+
function makeCancellable(operation) {
|
|
397
|
+
let cancelled = false;
|
|
398
|
+
let rejectFn;
|
|
399
|
+
const promise = new Promise((resolve, reject) => {
|
|
400
|
+
rejectFn = reject;
|
|
401
|
+
operation()
|
|
402
|
+
.then((result) => {
|
|
403
|
+
if (!cancelled) {
|
|
404
|
+
resolve(result);
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
.catch((error) => {
|
|
408
|
+
if (!cancelled) {
|
|
409
|
+
reject(error);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
return {
|
|
414
|
+
promise,
|
|
415
|
+
cancel: () => {
|
|
416
|
+
if (!cancelled) {
|
|
417
|
+
cancelled = true;
|
|
418
|
+
rejectFn(new errors_1.WalletError({
|
|
419
|
+
code: errors_1.ErrorCode.USER_REJECTED,
|
|
420
|
+
message: "Operation cancelled by user",
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
isCancelled: () => cancelled,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/connection/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { WalletError } from "../errors";
|
|
2
|
+
import { Account } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Connection state types
|
|
5
|
+
*/
|
|
6
|
+
export type ConnectionStatus = "idle" | "detecting" | "connecting" | "authenticating" | "connected" | "signing" | "reconnecting" | "disconnecting" | "error";
|
|
7
|
+
/**
|
|
8
|
+
* Connection state with context
|
|
9
|
+
*/
|
|
10
|
+
export type ConnectionState = {
|
|
11
|
+
status: "idle";
|
|
12
|
+
} | {
|
|
13
|
+
status: "detecting";
|
|
14
|
+
walletId: string;
|
|
15
|
+
startedAt: number;
|
|
16
|
+
} | {
|
|
17
|
+
status: "connecting";
|
|
18
|
+
walletId: string;
|
|
19
|
+
startedAt: number;
|
|
20
|
+
} | {
|
|
21
|
+
status: "authenticating";
|
|
22
|
+
walletId: string;
|
|
23
|
+
startedAt: number;
|
|
24
|
+
} | {
|
|
25
|
+
status: "connected";
|
|
26
|
+
walletId: string;
|
|
27
|
+
accounts: Account[];
|
|
28
|
+
connectedAt: number;
|
|
29
|
+
} | {
|
|
30
|
+
status: "signing";
|
|
31
|
+
walletId: string;
|
|
32
|
+
operation: string;
|
|
33
|
+
startedAt: number;
|
|
34
|
+
} | {
|
|
35
|
+
status: "reconnecting";
|
|
36
|
+
walletId: string;
|
|
37
|
+
attempt: number;
|
|
38
|
+
startedAt: number;
|
|
39
|
+
} | {
|
|
40
|
+
status: "disconnecting";
|
|
41
|
+
walletId: string;
|
|
42
|
+
startedAt: number;
|
|
43
|
+
} | {
|
|
44
|
+
status: "error";
|
|
45
|
+
walletId?: string;
|
|
46
|
+
error: WalletError;
|
|
47
|
+
occurredAt: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* State transition history entry
|
|
51
|
+
*/
|
|
52
|
+
export interface StateHistoryEntry {
|
|
53
|
+
from: ConnectionState;
|
|
54
|
+
to: ConnectionState;
|
|
55
|
+
timestamp: number;
|
|
56
|
+
reason?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* State machine configuration
|
|
60
|
+
*/
|
|
61
|
+
export interface StateMachineConfig {
|
|
62
|
+
/** Maximum history entries to keep (default: 50) */
|
|
63
|
+
maxHistorySize: number;
|
|
64
|
+
/** Persist state to storage (default: false) */
|
|
65
|
+
persistState: boolean;
|
|
66
|
+
/** Storage key for persistence */
|
|
67
|
+
storageKey: string;
|
|
68
|
+
/** State expiration in ms (default: 24 hours) */
|
|
69
|
+
stateExpiration: number;
|
|
70
|
+
/** Callback when state changes */
|
|
71
|
+
onStateChange?: (from: ConnectionState, to: ConnectionState) => void;
|
|
72
|
+
/** Callback when invalid transition attempted */
|
|
73
|
+
onInvalidTransition?: (current: ConnectionStatus, attempted: ConnectionStatus) => void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Default state machine configuration
|
|
77
|
+
*/
|
|
78
|
+
export declare const DEFAULT_STATE_MACHINE_CONFIG: StateMachineConfig;
|
|
79
|
+
/**
|
|
80
|
+
* Connection State Machine
|
|
81
|
+
*
|
|
82
|
+
* Manages connection lifecycle with proper state transitions
|
|
83
|
+
*/
|
|
84
|
+
export declare class ConnectionStateMachine {
|
|
85
|
+
private state;
|
|
86
|
+
private history;
|
|
87
|
+
private config;
|
|
88
|
+
private listeners;
|
|
89
|
+
constructor(config?: Partial<StateMachineConfig>);
|
|
90
|
+
/**
|
|
91
|
+
* Get current state
|
|
92
|
+
*/
|
|
93
|
+
get current(): ConnectionState;
|
|
94
|
+
/**
|
|
95
|
+
* Get current status (convenience getter)
|
|
96
|
+
*/
|
|
97
|
+
get status(): ConnectionStatus;
|
|
98
|
+
/**
|
|
99
|
+
* Check if currently in a specific status
|
|
100
|
+
*/
|
|
101
|
+
is(status: ConnectionStatus): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Check if in any of the given statuses
|
|
104
|
+
*/
|
|
105
|
+
isAnyOf(...statuses: ConnectionStatus[]): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Check if a transition is valid
|
|
108
|
+
*/
|
|
109
|
+
canTransition(to: ConnectionStatus): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Transition to a new state
|
|
112
|
+
*/
|
|
113
|
+
transition(to: ConnectionState, reason?: string): void;
|
|
114
|
+
/**
|
|
115
|
+
* Convenience methods for common transitions
|
|
116
|
+
*/
|
|
117
|
+
toDetecting(walletId: string): void;
|
|
118
|
+
toConnecting(walletId: string): void;
|
|
119
|
+
toAuthenticating(walletId: string): void;
|
|
120
|
+
toConnected(walletId: string, accounts: Account[]): void;
|
|
121
|
+
toSigning(walletId: string, operation: string): void;
|
|
122
|
+
toReconnecting(walletId: string, attempt?: number): void;
|
|
123
|
+
toDisconnecting(walletId: string): void;
|
|
124
|
+
toError(error: WalletError, walletId?: string): void;
|
|
125
|
+
toIdle(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Reset to idle state (bypasses transition validation)
|
|
128
|
+
*/
|
|
129
|
+
reset(): void;
|
|
130
|
+
/**
|
|
131
|
+
* Record state transition in history
|
|
132
|
+
*/
|
|
133
|
+
private recordHistory;
|
|
134
|
+
/**
|
|
135
|
+
* Get state history
|
|
136
|
+
*/
|
|
137
|
+
getHistory(): StateHistoryEntry[];
|
|
138
|
+
/**
|
|
139
|
+
* Get last N history entries
|
|
140
|
+
*/
|
|
141
|
+
getRecentHistory(count?: number): StateHistoryEntry[];
|
|
142
|
+
/**
|
|
143
|
+
* Clear history
|
|
144
|
+
*/
|
|
145
|
+
clearHistory(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Register callback for entering a state
|
|
148
|
+
*/
|
|
149
|
+
onEnter(status: ConnectionStatus, callback: (state: ConnectionState) => void): () => void;
|
|
150
|
+
/**
|
|
151
|
+
* Register callback for exiting a state
|
|
152
|
+
*/
|
|
153
|
+
onExit(status: ConnectionStatus, callback: (state: ConnectionState) => void): () => void;
|
|
154
|
+
/**
|
|
155
|
+
* Register callback for any transition
|
|
156
|
+
*/
|
|
157
|
+
onTransition(callback: (from: ConnectionState, to: ConnectionState) => void): () => void;
|
|
158
|
+
/**
|
|
159
|
+
* Get connected wallet ID if in connected state
|
|
160
|
+
*/
|
|
161
|
+
getConnectedWalletId(): string | null;
|
|
162
|
+
/**
|
|
163
|
+
* Get connected accounts if in connected state
|
|
164
|
+
*/
|
|
165
|
+
getConnectedAccounts(): Account[];
|
|
166
|
+
/**
|
|
167
|
+
* Get error if in error state
|
|
168
|
+
*/
|
|
169
|
+
getError(): WalletError | null;
|
|
170
|
+
/**
|
|
171
|
+
* Get time spent in current state
|
|
172
|
+
*/
|
|
173
|
+
getTimeInCurrentState(): number;
|
|
174
|
+
/**
|
|
175
|
+
* Check if current state has timed out
|
|
176
|
+
*/
|
|
177
|
+
hasTimedOut(timeoutMs: number): boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Persist state to storage
|
|
180
|
+
*/
|
|
181
|
+
private persistState;
|
|
182
|
+
/**
|
|
183
|
+
* Restore state from storage
|
|
184
|
+
*/
|
|
185
|
+
private restoreState;
|
|
186
|
+
/**
|
|
187
|
+
* Clear persisted state
|
|
188
|
+
*/
|
|
189
|
+
private clearPersistedState;
|
|
190
|
+
/**
|
|
191
|
+
* Create a snapshot of current state
|
|
192
|
+
*/
|
|
193
|
+
snapshot(): {
|
|
194
|
+
state: ConnectionState;
|
|
195
|
+
history: StateHistoryEntry[];
|
|
196
|
+
timestamp: number;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Check if currently processing (not idle or connected)
|
|
200
|
+
*/
|
|
201
|
+
isProcessing(): boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Check if in a stable state (idle or connected)
|
|
204
|
+
*/
|
|
205
|
+
isStable(): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Wait for state to become stable
|
|
208
|
+
*/
|
|
209
|
+
waitForStable(timeoutMs?: number): Promise<ConnectionState>;
|
|
210
|
+
/**
|
|
211
|
+
* Cleanup
|
|
212
|
+
*/
|
|
213
|
+
destroy(): void;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Create a simple state machine instance
|
|
217
|
+
*/
|
|
218
|
+
export declare function createStateMachine(config?: Partial<StateMachineConfig>): ConnectionStateMachine;
|
|
219
|
+
/**
|
|
220
|
+
* Get human-readable status description
|
|
221
|
+
*/
|
|
222
|
+
export declare function getStatusDescription(status: ConnectionStatus): string;
|