@openzeppelin/ui-utils 1.1.1 → 1.2.1
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/dist/index.cjs +201 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +93 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +195 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1425,7 +1425,7 @@ function simpleHash(str) {
|
|
|
1425
1425
|
* ```
|
|
1426
1426
|
*/
|
|
1427
1427
|
function validateBytes(value, options = {}) {
|
|
1428
|
-
const { acceptedFormats = "both", maxBytes, allowHexPrefix = true } = options;
|
|
1428
|
+
const { acceptedFormats = "both", maxBytes, exactBytes, allowHexPrefix = true } = options;
|
|
1429
1429
|
if (!value || value.trim() === "") return {
|
|
1430
1430
|
isValid: true,
|
|
1431
1431
|
cleanedValue: "",
|
|
@@ -1487,6 +1487,13 @@ function validateBytes(value, options = {}) {
|
|
|
1487
1487
|
cleanedValue: cleanValue,
|
|
1488
1488
|
detectedFormat
|
|
1489
1489
|
};
|
|
1490
|
+
if (exactBytes && byteSize !== exactBytes) return {
|
|
1491
|
+
isValid: false,
|
|
1492
|
+
error: `Exactly ${exactBytes} bytes required (${detectedFormat === "hex" ? `${exactBytes * 2} hex characters` : `${exactBytes} bytes`}), got ${byteSize} bytes`,
|
|
1493
|
+
cleanedValue: cleanValue,
|
|
1494
|
+
detectedFormat,
|
|
1495
|
+
byteSize
|
|
1496
|
+
};
|
|
1490
1497
|
if (maxBytes && byteSize > maxBytes) return {
|
|
1491
1498
|
isValid: false,
|
|
1492
1499
|
error: `Maximum ${maxBytes} bytes allowed (${detectedFormat === "hex" ? `${maxBytes * 2} hex characters` : `${maxBytes} bytes`})`,
|
|
@@ -2256,14 +2263,204 @@ function getWalletNetworkSwitcherVariantClassName(variant) {
|
|
|
2256
2263
|
}
|
|
2257
2264
|
}
|
|
2258
2265
|
|
|
2266
|
+
//#endregion
|
|
2267
|
+
//#region src/serviceErrorDetection.ts
|
|
2268
|
+
/**
|
|
2269
|
+
* Utilities for detecting and categorizing network service connection errors.
|
|
2270
|
+
* This module provides functions to identify when errors are caused by network
|
|
2271
|
+
* service failures (RPC, Explorer, Indexer, etc.) and determine which service
|
|
2272
|
+
* type was affected.
|
|
2273
|
+
*/
|
|
2274
|
+
/**
|
|
2275
|
+
* Common patterns that indicate a network service connection failure.
|
|
2276
|
+
* These patterns help distinguish network/service issues from other errors.
|
|
2277
|
+
*/
|
|
2278
|
+
const SERVICE_ERROR_PATTERNS = [
|
|
2279
|
+
"failed to fetch",
|
|
2280
|
+
"network error",
|
|
2281
|
+
"connection refused",
|
|
2282
|
+
"timeout",
|
|
2283
|
+
"econnrefused",
|
|
2284
|
+
"fetch failed",
|
|
2285
|
+
"network request failed",
|
|
2286
|
+
"connection timeout",
|
|
2287
|
+
"unable to connect",
|
|
2288
|
+
"no response",
|
|
2289
|
+
"service unavailable",
|
|
2290
|
+
"could not connect",
|
|
2291
|
+
"connection failed",
|
|
2292
|
+
"network unavailable",
|
|
2293
|
+
"dns resolution failed",
|
|
2294
|
+
"socket hang up",
|
|
2295
|
+
"read econnreset",
|
|
2296
|
+
"503",
|
|
2297
|
+
"502",
|
|
2298
|
+
"504",
|
|
2299
|
+
"500",
|
|
2300
|
+
"gateway timeout",
|
|
2301
|
+
"bad gateway",
|
|
2302
|
+
"internal server error",
|
|
2303
|
+
"rpc error",
|
|
2304
|
+
"rpc endpoint",
|
|
2305
|
+
"indexer",
|
|
2306
|
+
"explorer",
|
|
2307
|
+
"horizon",
|
|
2308
|
+
"api error",
|
|
2309
|
+
"rate limit",
|
|
2310
|
+
"too many requests",
|
|
2311
|
+
"429"
|
|
2312
|
+
];
|
|
2313
|
+
/**
|
|
2314
|
+
* Known network service types with their display names.
|
|
2315
|
+
* Adapters can use any service ID, but these are common ones.
|
|
2316
|
+
*/
|
|
2317
|
+
const SERVICE_DISPLAY_NAMES = {
|
|
2318
|
+
rpc: "RPC Provider",
|
|
2319
|
+
explorer: "Block Explorer",
|
|
2320
|
+
indexer: "Indexer",
|
|
2321
|
+
horizon: "Horizon API",
|
|
2322
|
+
"contract-definitions": "Contract Definitions",
|
|
2323
|
+
soroban: "Soroban RPC",
|
|
2324
|
+
graphql: "GraphQL API",
|
|
2325
|
+
"proof-server": "Proof Server",
|
|
2326
|
+
node: "Node Provider"
|
|
2327
|
+
};
|
|
2328
|
+
/**
|
|
2329
|
+
* Patterns that suggest a specific service type caused the error.
|
|
2330
|
+
* More specific patterns take priority in the detection order.
|
|
2331
|
+
*/
|
|
2332
|
+
const SERVICE_TYPE_HINTS = [
|
|
2333
|
+
{
|
|
2334
|
+
patterns: [
|
|
2335
|
+
"indexer",
|
|
2336
|
+
"graphql",
|
|
2337
|
+
"subquery",
|
|
2338
|
+
"subgraph",
|
|
2339
|
+
"the graph"
|
|
2340
|
+
],
|
|
2341
|
+
serviceType: "indexer"
|
|
2342
|
+
},
|
|
2343
|
+
{
|
|
2344
|
+
patterns: [
|
|
2345
|
+
"explorer",
|
|
2346
|
+
"etherscan",
|
|
2347
|
+
"blockscout",
|
|
2348
|
+
"sourcify",
|
|
2349
|
+
"polygonscan",
|
|
2350
|
+
"bscscan"
|
|
2351
|
+
],
|
|
2352
|
+
serviceType: "explorer"
|
|
2353
|
+
},
|
|
2354
|
+
{
|
|
2355
|
+
patterns: ["horizon", "stellar"],
|
|
2356
|
+
serviceType: "horizon"
|
|
2357
|
+
},
|
|
2358
|
+
{
|
|
2359
|
+
patterns: ["soroban"],
|
|
2360
|
+
serviceType: "soroban"
|
|
2361
|
+
},
|
|
2362
|
+
{
|
|
2363
|
+
patterns: [
|
|
2364
|
+
"rpc",
|
|
2365
|
+
"jsonrpc",
|
|
2366
|
+
"json-rpc",
|
|
2367
|
+
"eth_",
|
|
2368
|
+
"web3",
|
|
2369
|
+
"provider",
|
|
2370
|
+
"node"
|
|
2371
|
+
],
|
|
2372
|
+
serviceType: "rpc"
|
|
2373
|
+
}
|
|
2374
|
+
];
|
|
2375
|
+
/**
|
|
2376
|
+
* Checks if an error message indicates a network service connection failure.
|
|
2377
|
+
*
|
|
2378
|
+
* @param errorMessage The error message to check
|
|
2379
|
+
* @returns True if the error appears to be caused by a service connection issue
|
|
2380
|
+
*
|
|
2381
|
+
* @example
|
|
2382
|
+
* ```ts
|
|
2383
|
+
* isServiceConnectionError('Failed to fetch'); // true
|
|
2384
|
+
* isServiceConnectionError('Invalid address'); // false
|
|
2385
|
+
* ```
|
|
2386
|
+
*/
|
|
2387
|
+
function isServiceConnectionError(errorMessage) {
|
|
2388
|
+
if (!errorMessage) return false;
|
|
2389
|
+
const lowerCaseError = errorMessage.toLowerCase();
|
|
2390
|
+
return SERVICE_ERROR_PATTERNS.some((pattern) => lowerCaseError.includes(pattern));
|
|
2391
|
+
}
|
|
2392
|
+
/**
|
|
2393
|
+
* Attempts to determine which service type caused the error based on the error message.
|
|
2394
|
+
* Falls back to 'rpc' as the most common case for blockchain-related failures.
|
|
2395
|
+
*
|
|
2396
|
+
* @param errorMessage The error message to analyze
|
|
2397
|
+
* @returns The detected service type (e.g., 'rpc', 'explorer', 'indexer')
|
|
2398
|
+
*
|
|
2399
|
+
* @example
|
|
2400
|
+
* ```ts
|
|
2401
|
+
* detectServiceType('Indexer connection failed'); // 'indexer'
|
|
2402
|
+
* detectServiceType('Etherscan API error'); // 'explorer'
|
|
2403
|
+
* detectServiceType('RPC endpoint timeout'); // 'rpc'
|
|
2404
|
+
* detectServiceType('Unknown error'); // 'rpc' (default)
|
|
2405
|
+
* ```
|
|
2406
|
+
*/
|
|
2407
|
+
function detectServiceType(errorMessage) {
|
|
2408
|
+
if (!errorMessage) return "rpc";
|
|
2409
|
+
const lowerCaseError = errorMessage.toLowerCase();
|
|
2410
|
+
for (const { patterns, serviceType } of SERVICE_TYPE_HINTS) if (patterns.some((pattern) => lowerCaseError.includes(pattern))) return serviceType;
|
|
2411
|
+
return "rpc";
|
|
2412
|
+
}
|
|
2413
|
+
/**
|
|
2414
|
+
* Gets a user-friendly display name for a service type.
|
|
2415
|
+
* Falls back to capitalizing the service ID if not found in known mappings.
|
|
2416
|
+
*
|
|
2417
|
+
* @param serviceType The service type identifier (e.g., 'rpc', 'explorer')
|
|
2418
|
+
* @returns A user-friendly display name (e.g., 'RPC Provider', 'Block Explorer')
|
|
2419
|
+
*
|
|
2420
|
+
* @example
|
|
2421
|
+
* ```ts
|
|
2422
|
+
* getServiceDisplayName('rpc'); // 'RPC Provider'
|
|
2423
|
+
* getServiceDisplayName('indexer'); // 'Indexer'
|
|
2424
|
+
* getServiceDisplayName('custom-service'); // 'Custom service'
|
|
2425
|
+
* ```
|
|
2426
|
+
*/
|
|
2427
|
+
function getServiceDisplayName(serviceType) {
|
|
2428
|
+
return SERVICE_DISPLAY_NAMES[serviceType] || serviceType.charAt(0).toUpperCase() + serviceType.slice(1).replace(/-/g, " ");
|
|
2429
|
+
}
|
|
2430
|
+
/**
|
|
2431
|
+
* Analyzes an error and returns detailed information about the service failure.
|
|
2432
|
+
*
|
|
2433
|
+
* @param errorMessage The error message to analyze
|
|
2434
|
+
* @returns Object containing detection results
|
|
2435
|
+
*
|
|
2436
|
+
* @example
|
|
2437
|
+
* ```ts
|
|
2438
|
+
* const result = analyzeServiceError('Indexer timeout');
|
|
2439
|
+
* // { isServiceError: true, serviceType: 'indexer', serviceName: 'Indexer' }
|
|
2440
|
+
* ```
|
|
2441
|
+
*/
|
|
2442
|
+
function analyzeServiceError(errorMessage) {
|
|
2443
|
+
const isServiceError = isServiceConnectionError(errorMessage);
|
|
2444
|
+
const serviceType = detectServiceType(errorMessage);
|
|
2445
|
+
return {
|
|
2446
|
+
isServiceError,
|
|
2447
|
+
serviceType,
|
|
2448
|
+
serviceName: getServiceDisplayName(serviceType)
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2259
2452
|
//#endregion
|
|
2260
2453
|
exports.AnalyticsService = AnalyticsService;
|
|
2261
2454
|
exports.AppConfigService = AppConfigService;
|
|
2262
2455
|
exports.DEFAULT_CONCURRENCY_LIMIT = DEFAULT_CONCURRENCY_LIMIT;
|
|
2456
|
+
exports.SERVICE_DISPLAY_NAMES = SERVICE_DISPLAY_NAMES;
|
|
2457
|
+
exports.SERVICE_ERROR_PATTERNS = SERVICE_ERROR_PATTERNS;
|
|
2458
|
+
exports.SERVICE_TYPE_HINTS = SERVICE_TYPE_HINTS;
|
|
2263
2459
|
exports.UserExplorerConfigService = UserExplorerConfigService;
|
|
2264
2460
|
exports.UserNetworkServiceConfigService = UserNetworkServiceConfigService;
|
|
2265
2461
|
exports.UserRpcConfigService = UserRpcConfigService;
|
|
2266
2462
|
exports.addressesEqual = addressesEqual;
|
|
2463
|
+
exports.analyzeServiceError = analyzeServiceError;
|
|
2267
2464
|
exports.appConfigService = appConfigService;
|
|
2268
2465
|
exports.base64ToBytes = base64ToBytes;
|
|
2269
2466
|
exports.buildRequiredInputSnapshot = buildRequiredInputSnapshot;
|
|
@@ -2275,6 +2472,7 @@ exports.createEmptySnapshot = createEmptySnapshot;
|
|
|
2275
2472
|
exports.delay = delay;
|
|
2276
2473
|
exports.deserializeSnapshot = deserializeSnapshot;
|
|
2277
2474
|
exports.detectBytesEncoding = detectBytesEncoding;
|
|
2475
|
+
exports.detectServiceType = detectServiceType;
|
|
2278
2476
|
exports.enhanceNumericValidation = enhanceNumericValidation;
|
|
2279
2477
|
exports.findRoleAssignment = findRoleAssignment;
|
|
2280
2478
|
exports.formatAccessControlError = formatAccessControlError;
|
|
@@ -2287,6 +2485,7 @@ exports.getErrorMessage = getErrorMessage;
|
|
|
2287
2485
|
exports.getForcedService = getForcedService;
|
|
2288
2486
|
exports.getInvalidUrlMessage = getInvalidUrlMessage;
|
|
2289
2487
|
exports.getMissingRequiredContractInputs = getMissingRequiredContractInputs;
|
|
2488
|
+
exports.getServiceDisplayName = getServiceDisplayName;
|
|
2290
2489
|
exports.getTotalMemberCount = getTotalMemberCount;
|
|
2291
2490
|
exports.getWalletAccountDisplaySizeProps = getWalletAccountDisplaySizeProps;
|
|
2292
2491
|
exports.getWalletButtonSizeProps = getWalletButtonSizeProps;
|
|
@@ -2301,6 +2500,7 @@ exports.isDevelopmentOrTestEnvironment = isDevelopmentOrTestEnvironment;
|
|
|
2301
2500
|
exports.isPlainObject = isPlainObject;
|
|
2302
2501
|
exports.isProductionEnvironment = isProductionEnvironment;
|
|
2303
2502
|
exports.isRecordWithProperties = isRecordWithProperties;
|
|
2503
|
+
exports.isServiceConnectionError = isServiceConnectionError;
|
|
2304
2504
|
exports.isValidUrl = isValidUrl;
|
|
2305
2505
|
exports.logger = logger;
|
|
2306
2506
|
exports.normalizeAddress = normalizeAddress;
|