@agirails/sdk 2.0.3 → 2.2.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 (151) hide show
  1. package/README.md +536 -87
  2. package/dist/adapters/BaseAdapter.js +2 -2
  3. package/dist/adapters/BaseAdapter.js.map +1 -1
  4. package/dist/adapters/BasicAdapter.d.ts.map +1 -1
  5. package/dist/adapters/BasicAdapter.js +8 -0
  6. package/dist/adapters/BasicAdapter.js.map +1 -1
  7. package/dist/adapters/StandardAdapter.d.ts +10 -5
  8. package/dist/adapters/StandardAdapter.d.ts.map +1 -1
  9. package/dist/adapters/StandardAdapter.js +19 -6
  10. package/dist/adapters/StandardAdapter.js.map +1 -1
  11. package/dist/builders/QuoteBuilder.js +1 -1
  12. package/dist/builders/QuoteBuilder.js.map +1 -1
  13. package/dist/cli/commands/config.js +1 -1
  14. package/dist/cli/commands/config.js.map +1 -1
  15. package/dist/cli/commands/simulate.js.map +1 -1
  16. package/dist/cli/commands/time.d.ts.map +1 -1
  17. package/dist/cli/commands/time.js.map +1 -1
  18. package/dist/config/networks.d.ts +9 -0
  19. package/dist/config/networks.d.ts.map +1 -1
  20. package/dist/config/networks.js +25 -10
  21. package/dist/config/networks.js.map +1 -1
  22. package/dist/index.d.ts +6 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +31 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/level0/provide.d.ts.map +1 -1
  27. package/dist/level0/provide.js +2 -1
  28. package/dist/level0/provide.js.map +1 -1
  29. package/dist/level0/request.d.ts.map +1 -1
  30. package/dist/level0/request.js +1 -2
  31. package/dist/level0/request.js.map +1 -1
  32. package/dist/level1/Agent.d.ts.map +1 -1
  33. package/dist/level1/Agent.js +11 -3
  34. package/dist/level1/Agent.js.map +1 -1
  35. package/dist/level1/pricing/PriceCalculator.js +1 -1
  36. package/dist/level1/pricing/PriceCalculator.js.map +1 -1
  37. package/dist/level1/types/Options.d.ts.map +1 -1
  38. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  39. package/dist/protocol/ACTPKernel.js +7 -5
  40. package/dist/protocol/ACTPKernel.js.map +1 -1
  41. package/dist/protocol/DIDResolver.js +1 -1
  42. package/dist/protocol/DIDResolver.js.map +1 -1
  43. package/dist/protocol/EASHelper.d.ts.map +1 -1
  44. package/dist/protocol/EASHelper.js +2 -3
  45. package/dist/protocol/EASHelper.js.map +1 -1
  46. package/dist/protocol/MessageSigner.d.ts.map +1 -1
  47. package/dist/protocol/MessageSigner.js +9 -9
  48. package/dist/protocol/MessageSigner.js.map +1 -1
  49. package/dist/protocol/ProofGenerator.d.ts.map +1 -1
  50. package/dist/protocol/ProofGenerator.js +1 -0
  51. package/dist/protocol/ProofGenerator.js.map +1 -1
  52. package/dist/runtime/BlockchainRuntime.d.ts +10 -3
  53. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  54. package/dist/runtime/BlockchainRuntime.js +41 -25
  55. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  56. package/dist/runtime/IACTPRuntime.d.ts +15 -0
  57. package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
  58. package/dist/runtime/MockRuntime.d.ts +7 -0
  59. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  60. package/dist/runtime/MockRuntime.js +15 -4
  61. package/dist/runtime/MockRuntime.js.map +1 -1
  62. package/dist/runtime/types/MockState.d.ts +5 -2
  63. package/dist/runtime/types/MockState.d.ts.map +1 -1
  64. package/dist/runtime/types/MockState.js.map +1 -1
  65. package/dist/storage/ArchiveBundleBuilder.d.ts +150 -0
  66. package/dist/storage/ArchiveBundleBuilder.d.ts.map +1 -0
  67. package/dist/storage/ArchiveBundleBuilder.js +468 -0
  68. package/dist/storage/ArchiveBundleBuilder.js.map +1 -0
  69. package/dist/storage/ArweaveClient.d.ts +271 -0
  70. package/dist/storage/ArweaveClient.d.ts.map +1 -0
  71. package/dist/storage/ArweaveClient.js +761 -0
  72. package/dist/storage/ArweaveClient.js.map +1 -0
  73. package/dist/storage/FilebaseClient.d.ts +193 -0
  74. package/dist/storage/FilebaseClient.d.ts.map +1 -0
  75. package/dist/storage/FilebaseClient.js +643 -0
  76. package/dist/storage/FilebaseClient.js.map +1 -0
  77. package/dist/storage/index.d.ts +47 -0
  78. package/dist/storage/index.d.ts.map +1 -0
  79. package/dist/storage/index.js +64 -0
  80. package/dist/storage/index.js.map +1 -0
  81. package/dist/storage/types.d.ts +291 -0
  82. package/dist/storage/types.d.ts.map +1 -0
  83. package/dist/storage/types.js +18 -0
  84. package/dist/storage/types.js.map +1 -0
  85. package/dist/types/state.d.ts +5 -4
  86. package/dist/types/state.d.ts.map +1 -1
  87. package/dist/types/state.js +10 -9
  88. package/dist/types/state.js.map +1 -1
  89. package/dist/utils/ErrorRecoveryGuide.d.ts.map +1 -1
  90. package/dist/utils/ErrorRecoveryGuide.js +1 -2
  91. package/dist/utils/ErrorRecoveryGuide.js.map +1 -1
  92. package/dist/utils/IPFSClient.d.ts.map +1 -1
  93. package/dist/utils/IPFSClient.js +5 -2
  94. package/dist/utils/IPFSClient.js.map +1 -1
  95. package/dist/utils/NonceManager.d.ts.map +1 -1
  96. package/dist/utils/NonceManager.js +3 -2
  97. package/dist/utils/NonceManager.js.map +1 -1
  98. package/dist/utils/UsedAttestationTracker.d.ts +1 -1
  99. package/dist/utils/UsedAttestationTracker.d.ts.map +1 -1
  100. package/dist/utils/UsedAttestationTracker.js +4 -4
  101. package/dist/utils/UsedAttestationTracker.js.map +1 -1
  102. package/dist/utils/circuitBreaker.d.ts +136 -0
  103. package/dist/utils/circuitBreaker.d.ts.map +1 -0
  104. package/dist/utils/circuitBreaker.js +253 -0
  105. package/dist/utils/circuitBreaker.js.map +1 -0
  106. package/dist/utils/retry.d.ts +120 -0
  107. package/dist/utils/retry.d.ts.map +1 -0
  108. package/dist/utils/retry.js +260 -0
  109. package/dist/utils/retry.js.map +1 -0
  110. package/dist/utils/validation.d.ts +100 -0
  111. package/dist/utils/validation.d.ts.map +1 -1
  112. package/dist/utils/validation.js +248 -1
  113. package/dist/utils/validation.js.map +1 -1
  114. package/package.json +14 -2
  115. package/src/adapters/BaseAdapter.ts +2 -2
  116. package/src/adapters/BasicAdapter.ts +12 -2
  117. package/src/adapters/StandardAdapter.ts +27 -7
  118. package/src/builders/QuoteBuilder.ts +1 -1
  119. package/src/cli/commands/config.ts +1 -1
  120. package/src/cli/commands/simulate.ts +1 -1
  121. package/src/cli/commands/time.ts +1 -2
  122. package/src/config/networks.ts +34 -10
  123. package/src/index.ts +54 -0
  124. package/src/level0/provide.ts +2 -1
  125. package/src/level0/request.ts +1 -2
  126. package/src/level1/Agent.ts +15 -5
  127. package/src/level1/pricing/PriceCalculator.ts +1 -1
  128. package/src/level1/types/Options.ts +1 -1
  129. package/src/protocol/ACTPKernel.ts +7 -5
  130. package/src/protocol/DIDResolver.ts +1 -1
  131. package/src/protocol/EASHelper.ts +2 -5
  132. package/src/protocol/MessageSigner.ts +9 -15
  133. package/src/protocol/ProofGenerator.ts +1 -0
  134. package/src/runtime/BlockchainRuntime.ts +42 -48
  135. package/src/runtime/IACTPRuntime.ts +16 -0
  136. package/src/runtime/MockRuntime.ts +16 -6
  137. package/src/runtime/types/MockState.ts +5 -2
  138. package/src/storage/ArchiveBundleBuilder.ts +563 -0
  139. package/src/storage/ArweaveClient.ts +945 -0
  140. package/src/storage/FilebaseClient.ts +790 -0
  141. package/src/storage/index.ts +96 -0
  142. package/src/storage/types.ts +348 -0
  143. package/src/types/state.ts +10 -9
  144. package/src/utils/ErrorRecoveryGuide.ts +1 -2
  145. package/src/utils/IPFSClient.ts +5 -4
  146. package/src/utils/NonceManager.ts +3 -2
  147. package/src/utils/UsedAttestationTracker.ts +4 -6
  148. package/src/utils/circuitBreaker.ts +324 -0
  149. package/src/utils/fsSafe.ts +5 -0
  150. package/src/utils/retry.ts +365 -0
  151. package/src/utils/validation.ts +295 -1
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Retry Utility - Exponential Backoff with Jitter (P1-2)
3
+ *
4
+ * Implements retry logic for storage operations with:
5
+ * - Exponential backoff (doubles delay each attempt)
6
+ * - Random jitter (prevents thundering herd)
7
+ * - Maximum retry limit
8
+ * - Configurable retry conditions
9
+ *
10
+ * @module utils/retry
11
+ */
12
+ /**
13
+ * Retry configuration options
14
+ */
15
+ export interface RetryOptions {
16
+ /** Maximum number of retry attempts (default: 3) */
17
+ maxAttempts?: number;
18
+ /** Initial delay in milliseconds (default: 1000) */
19
+ initialDelayMs?: number;
20
+ /** Maximum delay in milliseconds (default: 30000) */
21
+ maxDelayMs?: number;
22
+ /** Multiplier for exponential backoff (default: 2) */
23
+ backoffMultiplier?: number;
24
+ /** Jitter factor 0-1 (default: 0.1 = ±10%) */
25
+ jitterFactor?: number;
26
+ /** Function to determine if error is retryable (default: built-in check) */
27
+ isRetryable?: (error: unknown) => boolean;
28
+ /** Callback for each retry attempt (for logging) */
29
+ onRetry?: (attempt: number, error: unknown, delayMs: number) => void;
30
+ }
31
+ /**
32
+ * Result of retry operation
33
+ */
34
+ export interface RetryResult<T> {
35
+ /** Operation result (if successful) */
36
+ result?: T;
37
+ /** Final error (if all retries failed) */
38
+ error?: unknown;
39
+ /** Number of attempts made */
40
+ attempts: number;
41
+ /** Total time spent (including delays) */
42
+ totalTimeMs: number;
43
+ /** Whether operation succeeded */
44
+ success: boolean;
45
+ }
46
+ /**
47
+ * Default function to determine if error is retryable
48
+ *
49
+ * @param error - Error to check
50
+ * @returns True if error should trigger retry
51
+ */
52
+ export declare function isRetryableError(error: unknown): boolean;
53
+ /**
54
+ * Calculate delay with exponential backoff and jitter
55
+ *
56
+ * @param attempt - Current attempt number (1-based)
57
+ * @param options - Retry options
58
+ * @returns Delay in milliseconds
59
+ */
60
+ export declare function calculateBackoffDelay(attempt: number, options?: RetryOptions): number;
61
+ /**
62
+ * Execute async operation with retry logic
63
+ *
64
+ * Implements exponential backoff with jitter for handling transient failures.
65
+ * Particularly useful for storage operations that may fail due to:
66
+ * - Rate limiting
67
+ * - Network timeouts
68
+ * - Temporary service unavailability
69
+ *
70
+ * @param operation - Async function to execute
71
+ * @param options - Retry configuration
72
+ * @returns Promise resolving to operation result or throwing final error
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * // Basic usage
77
+ * const result = await withRetry(
78
+ * () => client.uploadJSON(data),
79
+ * { maxAttempts: 3 }
80
+ * );
81
+ *
82
+ * // With logging
83
+ * const result = await withRetry(
84
+ * () => client.downloadJSON(cid),
85
+ * {
86
+ * maxAttempts: 5,
87
+ * onRetry: (attempt, error, delay) => {
88
+ * console.log(`Retry ${attempt}, waiting ${delay}ms:`, error);
89
+ * }
90
+ * }
91
+ * );
92
+ * ```
93
+ */
94
+ export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
95
+ /**
96
+ * Execute async operation with retry logic, returning detailed result
97
+ *
98
+ * Unlike `withRetry`, this function never throws - it returns a result object
99
+ * with success/failure status and metadata.
100
+ *
101
+ * @param operation - Async function to execute
102
+ * @param options - Retry configuration
103
+ * @returns Promise resolving to detailed result object
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * const result = await withRetryResult(
108
+ * () => client.uploadJSON(data),
109
+ * { maxAttempts: 3 }
110
+ * );
111
+ *
112
+ * if (result.success) {
113
+ * console.log('Uploaded:', result.result);
114
+ * } else {
115
+ * console.error(`Failed after ${result.attempts} attempts:`, result.error);
116
+ * }
117
+ * ```
118
+ */
119
+ export declare function withRetryResult<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<RetryResult<T>>;
120
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAE1C,oDAAoD;IACpD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,uCAAuC;IACvC,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IAEjB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IAEpB,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;CAClB;AA0CD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA0CxD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,YAAiB,GACzB,MAAM,CAmBR;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,CAAC,CA8CZ;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CA2DzB"}
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ /**
3
+ * Retry Utility - Exponential Backoff with Jitter (P1-2)
4
+ *
5
+ * Implements retry logic for storage operations with:
6
+ * - Exponential backoff (doubles delay each attempt)
7
+ * - Random jitter (prevents thundering herd)
8
+ * - Maximum retry limit
9
+ * - Configurable retry conditions
10
+ *
11
+ * @module utils/retry
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.withRetryResult = exports.withRetry = exports.calculateBackoffDelay = exports.isRetryableError = void 0;
15
+ const errors_1 = require("../errors");
16
+ // ============================================================================
17
+ // Constants
18
+ // ============================================================================
19
+ const DEFAULT_MAX_ATTEMPTS = 3;
20
+ const DEFAULT_INITIAL_DELAY_MS = 1000;
21
+ const DEFAULT_MAX_DELAY_MS = 10000; // Reduced from 30s to 10s (NEW-4: prevent long stalls)
22
+ const DEFAULT_BACKOFF_MULTIPLIER = 2;
23
+ const DEFAULT_JITTER_FACTOR = 0.1;
24
+ /**
25
+ * Default list of retryable HTTP status codes
26
+ */
27
+ const RETRYABLE_STATUS_CODES = new Set([
28
+ 408, // Request Timeout
29
+ 429, // Too Many Requests
30
+ 500, // Internal Server Error
31
+ 502, // Bad Gateway
32
+ 503, // Service Unavailable
33
+ 504 // Gateway Timeout
34
+ ]);
35
+ /**
36
+ * Default list of retryable error codes
37
+ */
38
+ const RETRYABLE_ERROR_CODES = new Set([
39
+ 'ECONNRESET',
40
+ 'ECONNREFUSED',
41
+ 'ETIMEDOUT',
42
+ 'ENOTFOUND',
43
+ 'ENETUNREACH',
44
+ 'EAI_AGAIN',
45
+ 'EPIPE',
46
+ 'EHOSTUNREACH'
47
+ ]);
48
+ // ============================================================================
49
+ // Functions
50
+ // ============================================================================
51
+ /**
52
+ * Default function to determine if error is retryable
53
+ *
54
+ * @param error - Error to check
55
+ * @returns True if error should trigger retry
56
+ */
57
+ function isRetryableError(error) {
58
+ if (!error)
59
+ return false;
60
+ // Rate limit errors are always retryable
61
+ if (error instanceof errors_1.StorageRateLimitError) {
62
+ return true;
63
+ }
64
+ const e = error;
65
+ // Check HTTP status codes
66
+ if (e.statusCode && RETRYABLE_STATUS_CODES.has(e.statusCode)) {
67
+ return true;
68
+ }
69
+ if (e.status && RETRYABLE_STATUS_CODES.has(e.status)) {
70
+ return true;
71
+ }
72
+ // Check error codes (network errors)
73
+ if (e.code && RETRYABLE_ERROR_CODES.has(e.code)) {
74
+ return true;
75
+ }
76
+ // Check for timeout errors
77
+ if (e.name === 'AbortError' || e.name === 'TimeoutError') {
78
+ return true;
79
+ }
80
+ // Check message for common retryable patterns
81
+ const message = String(e.message || e).toLowerCase();
82
+ if (message.includes('timeout') ||
83
+ message.includes('rate limit') ||
84
+ message.includes('too many requests') ||
85
+ message.includes('service unavailable') ||
86
+ message.includes('temporarily unavailable')) {
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+ exports.isRetryableError = isRetryableError;
92
+ /**
93
+ * Calculate delay with exponential backoff and jitter
94
+ *
95
+ * @param attempt - Current attempt number (1-based)
96
+ * @param options - Retry options
97
+ * @returns Delay in milliseconds
98
+ */
99
+ function calculateBackoffDelay(attempt, options = {}) {
100
+ const { initialDelayMs = DEFAULT_INITIAL_DELAY_MS, maxDelayMs = DEFAULT_MAX_DELAY_MS, backoffMultiplier = DEFAULT_BACKOFF_MULTIPLIER, jitterFactor = DEFAULT_JITTER_FACTOR } = options;
101
+ // Exponential backoff: initialDelay * (multiplier ^ (attempt - 1))
102
+ const exponentialDelay = initialDelayMs * Math.pow(backoffMultiplier, attempt - 1);
103
+ // Cap at max delay
104
+ const cappedDelay = Math.min(exponentialDelay, maxDelayMs);
105
+ // Add jitter: ±jitterFactor
106
+ const jitter = cappedDelay * jitterFactor * (Math.random() * 2 - 1);
107
+ const finalDelay = Math.max(0, cappedDelay + jitter);
108
+ return Math.round(finalDelay);
109
+ }
110
+ exports.calculateBackoffDelay = calculateBackoffDelay;
111
+ /**
112
+ * Sleep for specified duration
113
+ *
114
+ * @param ms - Milliseconds to sleep
115
+ */
116
+ function sleep(ms) {
117
+ return new Promise(resolve => setTimeout(resolve, ms));
118
+ }
119
+ /**
120
+ * Execute async operation with retry logic
121
+ *
122
+ * Implements exponential backoff with jitter for handling transient failures.
123
+ * Particularly useful for storage operations that may fail due to:
124
+ * - Rate limiting
125
+ * - Network timeouts
126
+ * - Temporary service unavailability
127
+ *
128
+ * @param operation - Async function to execute
129
+ * @param options - Retry configuration
130
+ * @returns Promise resolving to operation result or throwing final error
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * // Basic usage
135
+ * const result = await withRetry(
136
+ * () => client.uploadJSON(data),
137
+ * { maxAttempts: 3 }
138
+ * );
139
+ *
140
+ * // With logging
141
+ * const result = await withRetry(
142
+ * () => client.downloadJSON(cid),
143
+ * {
144
+ * maxAttempts: 5,
145
+ * onRetry: (attempt, error, delay) => {
146
+ * console.log(`Retry ${attempt}, waiting ${delay}ms:`, error);
147
+ * }
148
+ * }
149
+ * );
150
+ * ```
151
+ */
152
+ async function withRetry(operation, options = {}) {
153
+ const { maxAttempts = DEFAULT_MAX_ATTEMPTS, isRetryable = isRetryableError, onRetry } = options;
154
+ let lastError;
155
+ const startTime = Date.now();
156
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
157
+ try {
158
+ return await operation();
159
+ }
160
+ catch (error) {
161
+ lastError = error;
162
+ // Check if this is the last attempt
163
+ if (attempt >= maxAttempts) {
164
+ break;
165
+ }
166
+ // Check if error is retryable
167
+ if (!isRetryable(error)) {
168
+ break;
169
+ }
170
+ // Calculate delay
171
+ let delayMs = calculateBackoffDelay(attempt, options);
172
+ // If rate limit error with retry-after header, use that instead
173
+ if (error instanceof errors_1.StorageRateLimitError && error.details?.retryAfter) {
174
+ delayMs = Math.max(delayMs, error.details.retryAfter * 1000);
175
+ }
176
+ // Notify callback
177
+ if (onRetry) {
178
+ onRetry(attempt, error, delayMs);
179
+ }
180
+ // Wait before retry
181
+ await sleep(delayMs);
182
+ }
183
+ }
184
+ // All retries failed
185
+ throw lastError;
186
+ }
187
+ exports.withRetry = withRetry;
188
+ /**
189
+ * Execute async operation with retry logic, returning detailed result
190
+ *
191
+ * Unlike `withRetry`, this function never throws - it returns a result object
192
+ * with success/failure status and metadata.
193
+ *
194
+ * @param operation - Async function to execute
195
+ * @param options - Retry configuration
196
+ * @returns Promise resolving to detailed result object
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const result = await withRetryResult(
201
+ * () => client.uploadJSON(data),
202
+ * { maxAttempts: 3 }
203
+ * );
204
+ *
205
+ * if (result.success) {
206
+ * console.log('Uploaded:', result.result);
207
+ * } else {
208
+ * console.error(`Failed after ${result.attempts} attempts:`, result.error);
209
+ * }
210
+ * ```
211
+ */
212
+ async function withRetryResult(operation, options = {}) {
213
+ const { maxAttempts = DEFAULT_MAX_ATTEMPTS, isRetryable = isRetryableError, onRetry } = options;
214
+ let lastError;
215
+ const startTime = Date.now();
216
+ let attempts = 0;
217
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
218
+ attempts = attempt;
219
+ try {
220
+ const result = await operation();
221
+ return {
222
+ result,
223
+ attempts,
224
+ totalTimeMs: Date.now() - startTime,
225
+ success: true
226
+ };
227
+ }
228
+ catch (error) {
229
+ lastError = error;
230
+ // Check if this is the last attempt
231
+ if (attempt >= maxAttempts) {
232
+ break;
233
+ }
234
+ // Check if error is retryable
235
+ if (!isRetryable(error)) {
236
+ break;
237
+ }
238
+ // Calculate delay
239
+ let delayMs = calculateBackoffDelay(attempt, options);
240
+ // If rate limit error with retry-after header, use that instead
241
+ if (error instanceof errors_1.StorageRateLimitError && error.details?.retryAfter) {
242
+ delayMs = Math.max(delayMs, error.details.retryAfter * 1000);
243
+ }
244
+ // Notify callback
245
+ if (onRetry) {
246
+ onRetry(attempt, error, delayMs);
247
+ }
248
+ // Wait before retry
249
+ await sleep(delayMs);
250
+ }
251
+ }
252
+ return {
253
+ error: lastError,
254
+ attempts,
255
+ totalTimeMs: Date.now() - startTime,
256
+ success: false
257
+ };
258
+ }
259
+ exports.withRetryResult = withRetryResult;
260
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,sCAAkD;AAoDlD,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,wBAAwB,GAAG,IAAI,CAAC;AACtC,MAAM,oBAAoB,GAAG,KAAK,CAAC,CAAC,uDAAuD;AAC3F,MAAM,0BAA0B,GAAG,CAAC,CAAC;AACrC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;GAEG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,oBAAoB;IACzB,GAAG,EAAE,wBAAwB;IAC7B,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,sBAAsB;IAC3B,GAAG,CAAE,kBAAkB;CACxB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,YAAY;IACZ,cAAc;IACd,WAAW;IACX,WAAW;IACX,aAAa;IACb,WAAW;IACX,OAAO;IACP,cAAc;CACf,CAAC,CAAC;AAEH,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,KAAc;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,yCAAyC;IACzC,IAAI,KAAK,YAAY,8BAAqB,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,GAAG,KAAY,CAAC;IAEvB,0BAA0B;IAC1B,IAAI,CAAC,CAAC,UAAU,IAAI,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,IAAI,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qCAAqC;IACrC,IAAI,CAAC,CAAC,IAAI,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2BAA2B;IAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8CAA8C;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACrD,IACE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC9B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACrC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QACvC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAC3C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AA1CD,4CA0CC;AAED;;;;;;GAMG;AACH,SAAgB,qBAAqB,CACnC,OAAe,EACf,UAAwB,EAAE;IAE1B,MAAM,EACJ,cAAc,GAAG,wBAAwB,EACzC,UAAU,GAAG,oBAAoB,EACjC,iBAAiB,GAAG,0BAA0B,EAC9C,YAAY,GAAG,qBAAqB,EACrC,GAAG,OAAO,CAAC;IAEZ,mEAAmE;IACnE,MAAM,gBAAgB,GAAG,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IAEnF,mBAAmB;IACnB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAE3D,4BAA4B;IAC5B,MAAM,MAAM,GAAG,WAAW,GAAG,YAAY,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,CAAC;IAErD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAtBD,sDAsBC;AAED;;;;GAIG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACI,KAAK,UAAU,SAAS,CAC7B,SAA2B,EAC3B,UAAwB,EAAE;IAE1B,MAAM,EACJ,WAAW,GAAG,oBAAoB,EAClC,WAAW,GAAG,gBAAgB,EAC9B,OAAO,EACR,GAAG,OAAO,CAAC;IAEZ,IAAI,SAAkB,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;YAElB,oCAAoC;YACpC,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;gBAC3B,MAAM;YACR,CAAC;YAED,8BAA8B;YAC9B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM;YACR,CAAC;YAED,kBAAkB;YAClB,IAAI,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAEtD,gEAAgE;YAChE,IAAI,KAAK,YAAY,8BAAqB,IAAI,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;gBACxE,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;YAC/D,CAAC;YAED,kBAAkB;YAClB,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,oBAAoB;YACpB,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,SAAS,CAAC;AAClB,CAAC;AAjDD,8BAiDC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACI,KAAK,UAAU,eAAe,CACnC,SAA2B,EAC3B,UAAwB,EAAE;IAE1B,MAAM,EACJ,WAAW,GAAG,oBAAoB,EAClC,WAAW,GAAG,gBAAgB,EAC9B,OAAO,EACR,GAAG,OAAO,CAAC;IAEZ,IAAI,SAAkB,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,QAAQ,GAAG,OAAO,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,OAAO;gBACL,MAAM;gBACN,QAAQ;gBACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;gBACnC,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;YAElB,oCAAoC;YACpC,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;gBAC3B,MAAM;YACR,CAAC;YAED,8BAA8B;YAC9B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM;YACR,CAAC;YAED,kBAAkB;YAClB,IAAI,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAEtD,gEAAgE;YAChE,IAAI,KAAK,YAAY,8BAAqB,IAAI,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;gBACxE,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;YAC/D,CAAC;YAED,kBAAkB;YAClB,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,oBAAoB;YACpB,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,QAAQ;QACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QACnC,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AA9DD,0CA8DC"}
@@ -1,6 +1,30 @@
1
1
  /**
2
2
  * Input validation utilities
3
3
  */
4
+ /** Ethereum address validation pattern */
5
+ export declare const ADDRESS_PATTERN: RegExp;
6
+ /** Transaction ID (bytes32) validation pattern */
7
+ export declare const TX_ID_PATTERN: RegExp;
8
+ /** Hash (bytes32) validation pattern */
9
+ export declare const HASH_PATTERN: RegExp;
10
+ /** Signature (65 bytes = 130 hex chars) validation pattern */
11
+ export declare const SIGNATURE_PATTERN: RegExp;
12
+ /** CID validation pattern (CIDv0 or CIDv1) */
13
+ export declare const CID_PATTERN: RegExp;
14
+ /** Arweave TX ID pattern (43 characters, base64url) */
15
+ export declare const ARWEAVE_TX_ID_PATTERN: RegExp;
16
+ /** Semver pattern for version validation */
17
+ export declare const SEMVER_PATTERN: RegExp;
18
+ /**
19
+ * Allowed IPFS gateway domains
20
+ * Only whitelisted gateways are allowed for downloads
21
+ */
22
+ export declare const ALLOWED_IPFS_GATEWAYS: readonly ["ipfs.filebase.io", "gateway.pinata.cloud", "cloudflare-ipfs.com", "ipfs.io", "dweb.link", "w3s.link", "nftstorage.link"];
23
+ /**
24
+ * Allowed Arweave gateway domains
25
+ * Only whitelisted gateways are allowed for downloads
26
+ */
27
+ export declare const ALLOWED_ARWEAVE_GATEWAYS: readonly ["arweave.net", "gateway.irys.xyz", "arweave.dev"];
4
28
  /**
5
29
  * Validate Ethereum address
6
30
  */
@@ -43,4 +67,80 @@ export declare function validateTxId(txId: string, fieldName?: string): void;
43
67
  * @throws {ValidationError} If endpoint is invalid or points to private IP
44
68
  */
45
69
  export declare function validateEndpointURL(endpoint: string, fieldName?: string): Promise<void>;
70
+ /**
71
+ * Validate IPFS CID format
72
+ *
73
+ * @param cid - IPFS CID to validate
74
+ * @param fieldName - Field name for error messages
75
+ * @throws {InvalidCIDError} If CID is invalid
76
+ */
77
+ export declare function validateCID(cid: string, fieldName?: string): void;
78
+ /**
79
+ * Validate Arweave transaction ID format
80
+ *
81
+ * @param txId - Arweave TX ID to validate
82
+ * @param fieldName - Field name for error messages
83
+ * @throws {InvalidArweaveTxIdError} If TX ID is invalid
84
+ */
85
+ export declare function validateArweaveTxId(txId: string, fieldName?: string): void;
86
+ /**
87
+ * Validate gateway URL against whitelist (SSRF Protection - P0-1)
88
+ *
89
+ * SECURITY FIX: Only allow downloads from whitelisted gateway domains.
90
+ * This prevents SSRF attacks where attacker controls the gateway URL.
91
+ *
92
+ * @param url - Full gateway URL to validate
93
+ * @param allowedGateways - List of allowed gateway domains
94
+ * @param fieldName - Field name for error messages
95
+ * @throws {ValidationError} If gateway is not whitelisted
96
+ */
97
+ export declare function validateGatewayURL(url: string, allowedGateways: readonly string[], fieldName?: string): void;
98
+ /**
99
+ * Validate semver version string
100
+ *
101
+ * @param version - Version string to validate
102
+ * @param fieldName - Field name for error messages
103
+ * @throws {ValidationError} If version is invalid
104
+ */
105
+ export declare function validateSemver(version: string, fieldName?: string): void;
106
+ /**
107
+ * Validate hash (bytes32) format
108
+ *
109
+ * @param hash - Hash to validate
110
+ * @param fieldName - Field name for error messages
111
+ * @throws {ValidationError} If hash is invalid
112
+ */
113
+ export declare function validateHash(hash: string, fieldName?: string): void;
114
+ /**
115
+ * Validate signature format (65 bytes)
116
+ *
117
+ * @param signature - Signature to validate
118
+ * @param fieldName - Field name for error messages
119
+ * @throws {ValidationError} If signature is invalid
120
+ */
121
+ export declare function validateSignature(signature: string, fieldName?: string): void;
122
+ /**
123
+ * Sanitize error messages to remove sensitive data
124
+ *
125
+ * SECURITY FIX (P0-2): Removes credentials, private keys, and other
126
+ * sensitive data from error messages before logging/returning.
127
+ *
128
+ * @param error - Error to sanitize
129
+ * @returns Sanitized error message
130
+ */
131
+ export declare function sanitizeErrorMessage(error: unknown): string;
132
+ /**
133
+ * Create a safe error object for external consumption
134
+ *
135
+ * SECURITY FIX (P0-2): Returns error without stack trace or sensitive details
136
+ *
137
+ * @param error - Original error
138
+ * @param operation - What operation failed
139
+ * @returns Safe error object
140
+ */
141
+ export declare function createSafeError(error: unknown, operation: string): {
142
+ message: string;
143
+ code: string;
144
+ operation: string;
145
+ };
46
146
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAOA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAkB,GAAG,IAAI,CAQpF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,GAAE,MAAiB,GAAG,IAAI,CASlF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAmB,GAAG,IAAI,CASvF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,SAAS,GAAE,MAAwB,GAClC,IAAI,CAaN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAe,GAAG,IAAI,CAI3E;AAwDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFzG"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AASA;;GAEG;AAMH,0CAA0C;AAC1C,eAAO,MAAM,eAAe,QAAwB,CAAC;AAErD,kDAAkD;AAClD,eAAO,MAAM,aAAa,QAAwB,CAAC;AAEnD,wCAAwC;AACxC,eAAO,MAAM,YAAY,QAAwB,CAAC;AAElD,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,QAAyB,CAAC;AAExD,8CAA8C;AAC9C,eAAO,MAAM,WAAW,QAAkD,CAAC;AAE3E,uDAAuD;AACvD,eAAO,MAAM,qBAAqB,QAAwB,CAAC;AAE3D,4CAA4C;AAC5C,eAAO,MAAM,cAAc,QAAoB,CAAC;AAMhD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,qIAQxB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,wBAAwB,6DAI3B,CAAC;AAMX;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAkB,GAAG,IAAI,CAQpF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,GAAE,MAAiB,GAAG,IAAI,CASlF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAmB,GAAG,IAAI,CASvF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,SAAS,GAAE,MAAwB,GAClC,IAAI,CAaN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAe,GAAG,IAAI,CAI3E;AA8DD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFzG;AAMD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,GAAE,MAAc,GAAG,IAAI,CAQxE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAe,GAAG,IAAI,CAWlF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,SAAS,GAAE,MAAqB,GAC/B,IAAI,CA0CN;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAkB,GAAG,IAAI,CAQnF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAe,GAAG,IAAI,CAQ3E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,MAAoB,GAAG,IAAI,CAW1F;AAMD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAsC3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAStD"}