@openzeppelin/ui-react 3.1.0 → 3.3.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/dist/index.cjs +304 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -10
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +69 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +299 -87
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { QueryClient, useQuery } from "@tanstack/react-query";
|
|
|
5
5
|
import { Button } from "@openzeppelin/ui-components";
|
|
6
6
|
|
|
7
7
|
//#region src/version.ts
|
|
8
|
-
const VERSION = "3.
|
|
8
|
+
const VERSION = "3.3.0";
|
|
9
9
|
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/hooks/AdapterContext.tsx
|
|
@@ -58,11 +58,31 @@ function RuntimeProvider({ children, resolveRuntime }) {
|
|
|
58
58
|
const [loadingNetworks, setLoadingNetworks] = useState(/* @__PURE__ */ new Set());
|
|
59
59
|
const runtimeRegistryRef = useRef(runtimeRegistry);
|
|
60
60
|
const failedNetworksRef = useRef(/* @__PURE__ */ new Set());
|
|
61
|
+
const resolverGenerationRef = useRef(0);
|
|
62
|
+
const resolverInitializedRef = useRef(false);
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
runtimeRegistryRef.current = runtimeRegistry;
|
|
63
65
|
}, [runtimeRegistry]);
|
|
64
66
|
useEffect(() => {
|
|
67
|
+
if (resolverInitializedRef.current) resolverGenerationRef.current += 1;
|
|
68
|
+
else resolverInitializedRef.current = true;
|
|
69
|
+
const registry = runtimeRegistryRef.current;
|
|
70
|
+
const runtimes = Object.values(registry);
|
|
71
|
+
const hadCachedRuntimes = runtimes.length > 0;
|
|
65
72
|
failedNetworksRef.current = /* @__PURE__ */ new Set();
|
|
73
|
+
setLoadingNetworks(/* @__PURE__ */ new Set());
|
|
74
|
+
if (hadCachedRuntimes) {
|
|
75
|
+
setRuntimeRegistry({});
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
runtimes.forEach((runtime) => {
|
|
78
|
+
try {
|
|
79
|
+
runtime.dispose();
|
|
80
|
+
} catch (error) {
|
|
81
|
+
logger.error("RuntimeProvider", "Error disposing runtime during registry flush:", error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}, 0);
|
|
85
|
+
}
|
|
66
86
|
}, [resolveRuntime]);
|
|
67
87
|
useEffect(() => {
|
|
68
88
|
return () => {
|
|
@@ -150,7 +170,23 @@ function RuntimeProvider({ children, resolveRuntime }) {
|
|
|
150
170
|
return newSet;
|
|
151
171
|
});
|
|
152
172
|
logger.info("RuntimeProvider", `Starting runtime initialization for network ${networkId} (${networkConfig.name})`);
|
|
173
|
+
const generation = resolverGenerationRef.current;
|
|
153
174
|
resolveRuntime(networkConfig).then((runtime) => {
|
|
175
|
+
if (generation !== resolverGenerationRef.current) {
|
|
176
|
+
setTimeout(() => {
|
|
177
|
+
try {
|
|
178
|
+
runtime.dispose();
|
|
179
|
+
} catch (error) {
|
|
180
|
+
logger.error("RuntimeProvider", `Error disposing stale runtime for network ${networkId}:`, error);
|
|
181
|
+
}
|
|
182
|
+
}, 0);
|
|
183
|
+
setLoadingNetworks((prev) => {
|
|
184
|
+
const newSet = new Set(prev);
|
|
185
|
+
newSet.delete(networkId);
|
|
186
|
+
return newSet;
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
154
190
|
logger.info("RuntimeProvider", `Runtime for network ${networkId} loaded successfully`, {
|
|
155
191
|
type: runtime.constructor.name,
|
|
156
192
|
objectId: Object.prototype.toString.call(runtime)
|
|
@@ -165,6 +201,14 @@ function RuntimeProvider({ children, resolveRuntime }) {
|
|
|
165
201
|
return newSet;
|
|
166
202
|
});
|
|
167
203
|
}).catch((error) => {
|
|
204
|
+
if (generation !== resolverGenerationRef.current) {
|
|
205
|
+
setLoadingNetworks((prev) => {
|
|
206
|
+
const newSet = new Set(prev);
|
|
207
|
+
newSet.delete(networkId);
|
|
208
|
+
return newSet;
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
168
212
|
logger.error("RuntimeProvider", `Error loading runtime for network ${networkId}:`, error);
|
|
169
213
|
failedNetworksRef.current.add(networkId);
|
|
170
214
|
setLoadingNetworks((prev) => {
|
|
@@ -893,22 +937,42 @@ const DEFAULT_CONFIG = {
|
|
|
893
937
|
};
|
|
894
938
|
/** Stable prefix for every resolution cache key — namespaces this package's keys. */
|
|
895
939
|
const RESOLUTION_KEY_PREFIX = "oz-name-resolution";
|
|
940
|
+
const runtimeInstanceIds = /* @__PURE__ */ new WeakMap();
|
|
941
|
+
let nextRuntimeInstanceId = 1;
|
|
942
|
+
/**
|
|
943
|
+
* Assign a stable, serializable id to each {@link EcosystemRuntime} object identity.
|
|
944
|
+
* A disposed-and-recreated runtime (e.g. SF-4 opt-in toggle after INV-218 flush) gets
|
|
945
|
+
* a new id so resolution cache keys miss and results refresh (INV-230).
|
|
946
|
+
*/
|
|
947
|
+
function getRuntimeInstanceId(runtime) {
|
|
948
|
+
if (!runtime) return 0;
|
|
949
|
+
let id = runtimeInstanceIds.get(runtime);
|
|
950
|
+
if (id === void 0) {
|
|
951
|
+
id = nextRuntimeInstanceId;
|
|
952
|
+
nextRuntimeInstanceId += 1;
|
|
953
|
+
runtimeInstanceIds.set(runtime, id);
|
|
954
|
+
}
|
|
955
|
+
return id;
|
|
956
|
+
}
|
|
896
957
|
/**
|
|
897
958
|
* Build a network-scoped, namespace-separated cache key (INV-40). A name resolves
|
|
898
959
|
* differently per network and provenance can be chain-scoped, so `networkId` is
|
|
899
|
-
* part of the key; `namespace` keeps forward and reverse lookups disjoint
|
|
960
|
+
* part of the key; `namespace` keeps forward and reverse lookups disjoint;
|
|
961
|
+
* `runtimeInstanceId` scopes entries to the active capability instance (INV-230).
|
|
900
962
|
*
|
|
901
|
-
* @param namespace
|
|
902
|
-
* @param networkId
|
|
903
|
-
* @param normalizedInput
|
|
963
|
+
* @param namespace - `'name'` (forward) or `'addr'` (reverse).
|
|
964
|
+
* @param networkId - Active network id (`''` when no network is selected).
|
|
965
|
+
* @param normalizedInput - Trimmed + lowercased input (INV-26).
|
|
966
|
+
* @param runtimeInstanceId - Active runtime instance discriminator (`0` when absent).
|
|
904
967
|
* @returns A readonly tuple suitable for a TanStack Query `queryKey`.
|
|
905
968
|
*/
|
|
906
|
-
function buildResolutionKey(namespace, networkId, normalizedInput) {
|
|
969
|
+
function buildResolutionKey(namespace, networkId, normalizedInput, runtimeInstanceId = 0) {
|
|
907
970
|
return [
|
|
908
971
|
RESOLUTION_KEY_PREFIX,
|
|
909
972
|
namespace,
|
|
910
973
|
networkId,
|
|
911
|
-
normalizedInput
|
|
974
|
+
normalizedInput,
|
|
975
|
+
runtimeInstanceId
|
|
912
976
|
];
|
|
913
977
|
}
|
|
914
978
|
/**
|
|
@@ -1081,11 +1145,11 @@ const NOOP_RETRY = () => {};
|
|
|
1081
1145
|
* {@link EngineResult}. Not exported from the package.
|
|
1082
1146
|
*/
|
|
1083
1147
|
function useResolutionEngine(params) {
|
|
1084
|
-
const { input, namespace, debounceMs, enabled, shouldAttempt, getMethod } = params;
|
|
1148
|
+
const { input, namespace, debounceMs, enabled, shouldAttempt, getMethod, runtimeSource } = params;
|
|
1085
1149
|
const walletState = useContext(WalletStateContext);
|
|
1086
|
-
const activeRuntime = walletState?.activeRuntime ?? null;
|
|
1087
|
-
const activeNetworkId = walletState?.activeNetworkId ?? null;
|
|
1088
|
-
const isRuntimeLoading = walletState?.isRuntimeLoading ?? false;
|
|
1150
|
+
const activeRuntime = runtimeSource ? runtimeSource.runtime : walletState?.activeRuntime ?? null;
|
|
1151
|
+
const activeNetworkId = runtimeSource ? runtimeSource.networkId : walletState?.activeNetworkId ?? null;
|
|
1152
|
+
const isRuntimeLoading = runtimeSource ? runtimeSource.isRuntimeLoading : walletState?.isRuntimeLoading ?? false;
|
|
1089
1153
|
const { queryClient, config } = useNameResolutionContext();
|
|
1090
1154
|
const trimmedLive = (input ?? "").trim();
|
|
1091
1155
|
const normalizedLive = trimmedLive.toLowerCase();
|
|
@@ -1107,12 +1171,13 @@ function useResolutionEngine(params) {
|
|
|
1107
1171
|
const normalizedKey = effectiveTrimmed.toLowerCase();
|
|
1108
1172
|
const capability = activeRuntime?.nameResolution;
|
|
1109
1173
|
const networkId = activeNetworkId ?? "";
|
|
1174
|
+
const runtimeInstanceId = getRuntimeInstanceId(activeRuntime);
|
|
1110
1175
|
const method = capability ? getMethod(capability) : void 0;
|
|
1111
1176
|
const liveAttemptable = capability ? shouldAttempt(capability, normalizedLive) : false;
|
|
1112
1177
|
const keyAttemptable = capability ? shouldAttempt(capability, normalizedKey) : false;
|
|
1113
1178
|
const queryEnabled = enabled && trimmedLive !== "" && capability != null && method != null && normalizedKey !== "" && keyAttemptable;
|
|
1114
1179
|
const query = useQuery({
|
|
1115
|
-
queryKey: buildResolutionKey(namespace, networkId, normalizedKey),
|
|
1180
|
+
queryKey: buildResolutionKey(namespace, networkId, normalizedKey, runtimeInstanceId),
|
|
1116
1181
|
queryFn: async () => {
|
|
1117
1182
|
if (!method) throw new ResolutionQueryError({
|
|
1118
1183
|
code: "ADAPTER_ERROR",
|
|
@@ -1239,40 +1304,13 @@ function toNameResult(engine) {
|
|
|
1239
1304
|
}
|
|
1240
1305
|
|
|
1241
1306
|
//#endregion
|
|
1242
|
-
//#region src/hooks/nameResolution/
|
|
1243
|
-
/**
|
|
1244
|
-
* Reverse-resolve an address to a name. Soft-reads the active runtime from
|
|
1245
|
-
* `WalletStateContext` (never throws when no provider is mounted — degrades to
|
|
1246
|
-
* idle / UNSUPPORTED_NETWORK) and calls `runtime.nameResolution?.resolveAddress`.
|
|
1247
|
-
* Caches per (network, address) via the owned QueryClient. Not debounced by
|
|
1248
|
-
* default — addresses are pasted, not typed char-by-char.
|
|
1249
|
-
*
|
|
1250
|
-
* Applies no client-side address-shape check (INV-32): resolution is attempted on
|
|
1251
|
-
* any non-empty input and malformed addresses are rejected via the adapter's typed
|
|
1252
|
-
* error union. Address-shape validation is SF-3's concern.
|
|
1253
|
-
*
|
|
1254
|
-
* @param address - The address to reverse-resolve. `null` / empty yields
|
|
1255
|
-
* `status: 'idle'`.
|
|
1256
|
-
* @param options - `debounceMs` / `enabled` overrides.
|
|
1257
|
-
* @returns The current {@link UseResolveAddressResult}.
|
|
1258
|
-
*/
|
|
1259
|
-
function useResolveAddress(address, options) {
|
|
1260
|
-
const { config } = useNameResolutionContext();
|
|
1261
|
-
return toAddressResult(useResolutionEngine({
|
|
1262
|
-
input: address,
|
|
1263
|
-
namespace: "addr",
|
|
1264
|
-
debounceMs: options?.debounceMs ?? config.reverseDebounceMs,
|
|
1265
|
-
enabled: options?.enabled ?? true,
|
|
1266
|
-
shouldAttempt: () => true,
|
|
1267
|
-
getMethod: (cap) => cap.resolveAddress
|
|
1268
|
-
}));
|
|
1269
|
-
}
|
|
1307
|
+
//#region src/hooks/nameResolution/mapAddressEngineResult.ts
|
|
1270
1308
|
/**
|
|
1271
1309
|
* Remap the engine's generic `input` to `address` (INV-24). A `debouncing` arm —
|
|
1272
1310
|
* only reachable when a caller passes a non-zero reverse `debounceMs` — collapses
|
|
1273
1311
|
* to `loading` so {@link UseResolveAddressResult} keeps no `debouncing` variant.
|
|
1274
1312
|
*/
|
|
1275
|
-
function
|
|
1313
|
+
function mapAddressEngineResult(engine) {
|
|
1276
1314
|
switch (engine.status) {
|
|
1277
1315
|
case "idle": return { status: "idle" };
|
|
1278
1316
|
case "debouncing":
|
|
@@ -1294,6 +1332,71 @@ function toAddressResult(engine) {
|
|
|
1294
1332
|
}
|
|
1295
1333
|
}
|
|
1296
1334
|
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region src/hooks/nameResolution/useNetworkRuntimeSource.ts
|
|
1337
|
+
/**
|
|
1338
|
+
* Soft-reads {@link RuntimeContext} (never throws) and requests the registry
|
|
1339
|
+
* runtime for `network`. Call during render so loading state updates propagate.
|
|
1340
|
+
*
|
|
1341
|
+
* Does not mutate {@link WalletStateProvider}'s active network — wallet-global
|
|
1342
|
+
* runtime is never consulted when a scoped network is supplied (INV-154).
|
|
1343
|
+
*/
|
|
1344
|
+
function useNetworkRuntimeSource(network) {
|
|
1345
|
+
const runtimeContext = useContext(RuntimeContext);
|
|
1346
|
+
if (!network) return {
|
|
1347
|
+
runtime: null,
|
|
1348
|
+
networkId: "",
|
|
1349
|
+
isRuntimeLoading: false
|
|
1350
|
+
};
|
|
1351
|
+
if (!runtimeContext) return {
|
|
1352
|
+
runtime: null,
|
|
1353
|
+
networkId: network.id,
|
|
1354
|
+
isRuntimeLoading: false
|
|
1355
|
+
};
|
|
1356
|
+
const { runtime, isLoading } = runtimeContext.getRuntimeForNetwork(network);
|
|
1357
|
+
return {
|
|
1358
|
+
runtime,
|
|
1359
|
+
networkId: network.id,
|
|
1360
|
+
isRuntimeLoading: isLoading
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
//#endregion
|
|
1365
|
+
//#region src/hooks/nameResolution/useResolveAddress.ts
|
|
1366
|
+
/**
|
|
1367
|
+
* Reverse-resolve an address to a name. Soft-reads the active runtime from
|
|
1368
|
+
* `WalletStateContext` (never throws when no provider is mounted — degrades to
|
|
1369
|
+
* idle / UNSUPPORTED_NETWORK) and calls `runtime.nameResolution?.resolveAddress`.
|
|
1370
|
+
* Pass `options.network` to scope resolution to a specific network without
|
|
1371
|
+
* changing the wallet's active network. Caches per (network, address) via the
|
|
1372
|
+
* owned QueryClient. Not debounced by default — addresses are pasted, not
|
|
1373
|
+
* typed char-by-char.
|
|
1374
|
+
*
|
|
1375
|
+
* Applies no client-side address-shape check (INV-32): resolution is attempted on
|
|
1376
|
+
* any non-empty input and malformed addresses are rejected via the adapter's typed
|
|
1377
|
+
* error union. Address-shape validation is SF-3's concern.
|
|
1378
|
+
*
|
|
1379
|
+
* @param address - The address to reverse-resolve. `null` / empty yields
|
|
1380
|
+
* `status: 'idle'`.
|
|
1381
|
+
* @param options - `debounceMs` / `enabled` / `network` overrides.
|
|
1382
|
+
* @returns The current {@link UseResolveAddressResult}.
|
|
1383
|
+
*/
|
|
1384
|
+
function useResolveAddress(address, options) {
|
|
1385
|
+
const { config } = useNameResolutionContext();
|
|
1386
|
+
const debounceMs = options?.debounceMs ?? config.reverseDebounceMs;
|
|
1387
|
+
const enabled = options?.enabled ?? true;
|
|
1388
|
+
const networkSource = useNetworkRuntimeSource(options?.network ?? null);
|
|
1389
|
+
return mapAddressEngineResult(useResolutionEngine({
|
|
1390
|
+
input: address,
|
|
1391
|
+
namespace: "addr",
|
|
1392
|
+
debounceMs,
|
|
1393
|
+
enabled,
|
|
1394
|
+
shouldAttempt: () => true,
|
|
1395
|
+
getMethod: (cap) => cap.resolveAddress,
|
|
1396
|
+
runtimeSource: options?.network != null ? networkSource : void 0
|
|
1397
|
+
}));
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1297
1400
|
//#endregion
|
|
1298
1401
|
//#region src/hooks/nameResolution/NameResolutionProvider.tsx
|
|
1299
1402
|
/**
|
|
@@ -1319,6 +1422,54 @@ function NameResolutionProvider({ children, config, queryClient }) {
|
|
|
1319
1422
|
});
|
|
1320
1423
|
}
|
|
1321
1424
|
|
|
1425
|
+
//#endregion
|
|
1426
|
+
//#region src/hooks/nameResolution/createNameResolver.ts
|
|
1427
|
+
const EMPTY_RESOLVER$1 = {};
|
|
1428
|
+
/**
|
|
1429
|
+
* Projects a {@link NameResolutionCapability} into the SF-3 {@link NameResolver}
|
|
1430
|
+
* seam with SF-2 cache-key parity (INV-119).
|
|
1431
|
+
*/
|
|
1432
|
+
function createNameResolverFromCapability(capability, networkId, runtimeInstanceId, queryClient, config) {
|
|
1433
|
+
if (!capability) return EMPTY_RESOLVER$1;
|
|
1434
|
+
const resolveNameMethod = capability.resolveName;
|
|
1435
|
+
return {
|
|
1436
|
+
isValidName: (name) => capability.isValidName(name),
|
|
1437
|
+
resolveName: resolveNameMethod ? async (name) => {
|
|
1438
|
+
const normalized = name.trim().toLowerCase();
|
|
1439
|
+
try {
|
|
1440
|
+
return {
|
|
1441
|
+
ok: true,
|
|
1442
|
+
value: await queryClient.fetchQuery({
|
|
1443
|
+
queryKey: buildResolutionKey("name", networkId, normalized, runtimeInstanceId),
|
|
1444
|
+
queryFn: async () => {
|
|
1445
|
+
let result;
|
|
1446
|
+
try {
|
|
1447
|
+
result = await resolveNameMethod(normalized);
|
|
1448
|
+
} catch (cause) {
|
|
1449
|
+
throw new ResolutionQueryError({
|
|
1450
|
+
code: "ADAPTER_ERROR",
|
|
1451
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
1452
|
+
cause
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
if (!result.ok) throw new ResolutionQueryError(result.error);
|
|
1456
|
+
return result.value;
|
|
1457
|
+
},
|
|
1458
|
+
staleTime: config.staleTimeMs,
|
|
1459
|
+
gcTime: config.gcTimeMs,
|
|
1460
|
+
retry: (failureCount, error) => (error instanceof ResolutionQueryError ? isTransientError(error.resolutionError) : true) && failureCount < config.transientRetryCount
|
|
1461
|
+
})
|
|
1462
|
+
};
|
|
1463
|
+
} catch (error) {
|
|
1464
|
+
return {
|
|
1465
|
+
ok: false,
|
|
1466
|
+
error: toNameResolutionError(error)
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
} : void 0
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1322
1473
|
//#endregion
|
|
1323
1474
|
//#region src/hooks/nameResolution/useRuntimeNameResolver.ts
|
|
1324
1475
|
/**
|
|
@@ -1328,7 +1479,7 @@ function NameResolutionProvider({ children, config, queryClient }) {
|
|
|
1328
1479
|
*/
|
|
1329
1480
|
const EMPTY_RESOLVER = {};
|
|
1330
1481
|
/**
|
|
1331
|
-
* Project
|
|
1482
|
+
* Project a runtime's `NameResolutionCapability` into the injected
|
|
1332
1483
|
* {@link NameResolver} seam consumed by `@openzeppelin/ui-components` (SF-3, D3).
|
|
1333
1484
|
* Mounted ambiently by the renderer:
|
|
1334
1485
|
*
|
|
@@ -1336,6 +1487,10 @@ const EMPTY_RESOLVER = {};
|
|
|
1336
1487
|
* <NameResolverProvider {...useRuntimeNameResolver()}>{form}</NameResolverProvider>
|
|
1337
1488
|
* ```
|
|
1338
1489
|
*
|
|
1490
|
+
* Pass `scopedNetwork` to resolve against a specific network via
|
|
1491
|
+
* {@link RuntimeProvider}'s registry without changing {@link WalletStateProvider}'s
|
|
1492
|
+
* active network (e.g. address-book Add Alias dropdown).
|
|
1493
|
+
*
|
|
1339
1494
|
* Each imperative call is backed by SF-2's **owned** resolution `QueryClient`
|
|
1340
1495
|
* via `fetchQuery`, reusing SF-2's exact query-key convention
|
|
1341
1496
|
* (`buildResolutionKey('name', networkId, normalizedName)`) — so a name
|
|
@@ -1344,9 +1499,10 @@ const EMPTY_RESOLVER = {};
|
|
|
1344
1499
|
* out-of-order safety, never a parallel cache (INV-119).
|
|
1345
1500
|
*
|
|
1346
1501
|
* Degradation, in order (all method-omission, never a throw):
|
|
1347
|
-
* - No `WalletStateProvider` mounted
|
|
1348
|
-
*
|
|
1349
|
-
* renderer mount stays safe
|
|
1502
|
+
* - No `WalletStateProvider` mounted (wallet path) or no `RuntimeProvider`
|
|
1503
|
+
* (network path) → empty resolver. The context is read directly (not via
|
|
1504
|
+
* `useWalletState()`, which throws) so the ambient renderer mount stays safe
|
|
1505
|
+
* for wallet-less usage.
|
|
1350
1506
|
* - No active runtime, or runtime without the capability → empty resolver.
|
|
1351
1507
|
* - Capability without `resolveName` → `isValidName` only; forward unsupported.
|
|
1352
1508
|
*
|
|
@@ -1356,55 +1512,111 @@ const EMPTY_RESOLVER = {};
|
|
|
1356
1512
|
*
|
|
1357
1513
|
* @returns A referentially stable {@link NameResolver} for the active runtime.
|
|
1358
1514
|
*/
|
|
1359
|
-
function useRuntimeNameResolver() {
|
|
1515
|
+
function useRuntimeNameResolver(scopedNetwork) {
|
|
1360
1516
|
const walletState = useContext(WalletStateContext);
|
|
1361
1517
|
const { queryClient, config } = useNameResolutionContext();
|
|
1362
|
-
const
|
|
1363
|
-
const
|
|
1518
|
+
const networkSource = useNetworkRuntimeSource(scopedNetwork ?? null);
|
|
1519
|
+
const useNetworkScoped = scopedNetwork != null;
|
|
1520
|
+
const activeRuntime = useNetworkScoped ? networkSource.runtime : walletState?.activeRuntime ?? null;
|
|
1521
|
+
const capability = activeRuntime?.nameResolution;
|
|
1522
|
+
const networkId = useNetworkScoped ? networkSource.networkId : walletState?.activeNetworkId ?? "";
|
|
1523
|
+
const runtimeInstanceId = getRuntimeInstanceId(activeRuntime);
|
|
1364
1524
|
return useMemo(() => {
|
|
1365
1525
|
if (!capability) return EMPTY_RESOLVER;
|
|
1366
|
-
|
|
1367
|
-
return {
|
|
1368
|
-
isValidName: (name) => capability.isValidName(name),
|
|
1369
|
-
resolveName: resolveNameMethod ? async (name) => {
|
|
1370
|
-
const normalized = name.trim().toLowerCase();
|
|
1371
|
-
try {
|
|
1372
|
-
return {
|
|
1373
|
-
ok: true,
|
|
1374
|
-
value: await queryClient.fetchQuery({
|
|
1375
|
-
queryKey: buildResolutionKey("name", networkId, normalized),
|
|
1376
|
-
queryFn: async () => {
|
|
1377
|
-
let result;
|
|
1378
|
-
try {
|
|
1379
|
-
result = await resolveNameMethod(normalized);
|
|
1380
|
-
} catch (cause) {
|
|
1381
|
-
throw new ResolutionQueryError({
|
|
1382
|
-
code: "ADAPTER_ERROR",
|
|
1383
|
-
message: cause instanceof Error ? cause.message : String(cause),
|
|
1384
|
-
cause
|
|
1385
|
-
});
|
|
1386
|
-
}
|
|
1387
|
-
if (!result.ok) throw new ResolutionQueryError(result.error);
|
|
1388
|
-
return result.value;
|
|
1389
|
-
},
|
|
1390
|
-
staleTime: config.staleTimeMs,
|
|
1391
|
-
gcTime: config.gcTimeMs,
|
|
1392
|
-
retry: (failureCount, error) => (error instanceof ResolutionQueryError ? isTransientError(error.resolutionError) : true) && failureCount < config.transientRetryCount
|
|
1393
|
-
})
|
|
1394
|
-
};
|
|
1395
|
-
} catch (error) {
|
|
1396
|
-
return {
|
|
1397
|
-
ok: false,
|
|
1398
|
-
error: toNameResolutionError(error)
|
|
1399
|
-
};
|
|
1400
|
-
}
|
|
1401
|
-
} : void 0
|
|
1402
|
-
};
|
|
1526
|
+
return createNameResolverFromCapability(capability, networkId, runtimeInstanceId, queryClient, config);
|
|
1403
1527
|
}, [
|
|
1404
1528
|
capability,
|
|
1529
|
+
networkId,
|
|
1530
|
+
runtimeInstanceId,
|
|
1405
1531
|
queryClient,
|
|
1406
1532
|
config,
|
|
1407
|
-
|
|
1533
|
+
useNetworkScoped ? networkSource.isRuntimeLoading : walletState?.isRuntimeLoading ?? false
|
|
1534
|
+
]);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
//#endregion
|
|
1538
|
+
//#region src/hooks/nameResolution/useNetworkNameResolver.ts
|
|
1539
|
+
/**
|
|
1540
|
+
* @deprecated Pass the network to {@link useRuntimeNameResolver} instead.
|
|
1541
|
+
*/
|
|
1542
|
+
function useNetworkNameResolver(network) {
|
|
1543
|
+
return useRuntimeNameResolver(network ?? void 0);
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
//#endregion
|
|
1547
|
+
//#region src/hooks/nameResolution/useNetworkResolveAddress.ts
|
|
1548
|
+
/**
|
|
1549
|
+
* @deprecated Pass `network` in {@link UseResolveAddressOptions} to {@link useResolveAddress}.
|
|
1550
|
+
*/
|
|
1551
|
+
function useNetworkResolveAddress(address, network, options) {
|
|
1552
|
+
return useResolveAddress(address, network != null ? {
|
|
1553
|
+
...options,
|
|
1554
|
+
network
|
|
1555
|
+
} : options);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
//#endregion
|
|
1559
|
+
//#region src/hooks/runtime/runtimeCreationConfig.ts
|
|
1560
|
+
/** Safe default: miss-fallback OFF; no uiKit override. INV-204 */
|
|
1561
|
+
const DEFAULT_RUNTIME_CREATION_CONFIG = {};
|
|
1562
|
+
/**
|
|
1563
|
+
* Normalizes the opt-in flag to the adapter's strict-enable contract.
|
|
1564
|
+
* UIKit uses this at the threading boundary so `false` and `undefined` never
|
|
1565
|
+
* emit `enableMainnetL1MissFallback: false` into adapter options (absent = OFF).
|
|
1566
|
+
*/
|
|
1567
|
+
function isMainnetL1MissFallbackEnabled(options) {
|
|
1568
|
+
return options?.enableMainnetL1MissFallback === true;
|
|
1569
|
+
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Builds the `createRuntime` options bag for adapter threading.
|
|
1572
|
+
* When OFF, `nameResolution` is omitted (INV-207). When ON, spreads only
|
|
1573
|
+
* `{ enableMainnetL1MissFallback: true }` (INV-208).
|
|
1574
|
+
*/
|
|
1575
|
+
function buildCreateRuntimeOptions(options) {
|
|
1576
|
+
return {
|
|
1577
|
+
...options?.uiKit !== void 0 ? { uiKit: options.uiKit } : {},
|
|
1578
|
+
...isMainnetL1MissFallbackEnabled(options?.nameResolution) ? { nameResolution: { enableMainnetL1MissFallback: true } } : {}
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
//#endregion
|
|
1583
|
+
//#region src/hooks/runtime/createResolveRuntime.ts
|
|
1584
|
+
/**
|
|
1585
|
+
* Build a `resolveRuntime` callback for {@link RuntimeProvider} that forwards
|
|
1586
|
+
* `CreateRuntimeOptions` to `ecosystemDefinition.createRuntime`.
|
|
1587
|
+
*
|
|
1588
|
+
* Does not cache — {@link RuntimeProvider} owns the per-network singleton registry.
|
|
1589
|
+
*/
|
|
1590
|
+
function createResolveRuntime(ecosystemDefinition, params) {
|
|
1591
|
+
const { profile, options } = params;
|
|
1592
|
+
const mergedOptions = buildCreateRuntimeOptions(options);
|
|
1593
|
+
return (networkConfig) => Promise.resolve(ecosystemDefinition.createRuntime(profile, networkConfig, mergedOptions));
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
//#endregion
|
|
1597
|
+
//#region src/hooks/runtime/useResolveRuntime.ts
|
|
1598
|
+
/**
|
|
1599
|
+
* Memoized {@link createResolveRuntime} for React apps. Recompute when
|
|
1600
|
+
* `ecosystemDefinition`, `profile`, or opt-in posture change (INV-217, INV-222).
|
|
1601
|
+
*
|
|
1602
|
+
* Changing the returned function identity MUST trigger runtime registry flush
|
|
1603
|
+
* in {@link RuntimeProvider} (INV-218).
|
|
1604
|
+
*/
|
|
1605
|
+
function useResolveRuntime(ecosystemDefinition, params) {
|
|
1606
|
+
const { profile, options } = params;
|
|
1607
|
+
const uiKit = options?.uiKit;
|
|
1608
|
+
const enableMainnetL1MissFallback = options?.nameResolution?.enableMainnetL1MissFallback;
|
|
1609
|
+
return useMemo(() => createResolveRuntime(ecosystemDefinition, {
|
|
1610
|
+
profile,
|
|
1611
|
+
options: {
|
|
1612
|
+
...uiKit !== void 0 ? { uiKit } : {},
|
|
1613
|
+
...enableMainnetL1MissFallback === true ? { nameResolution: { enableMainnetL1MissFallback: true } } : {}
|
|
1614
|
+
}
|
|
1615
|
+
}), [
|
|
1616
|
+
ecosystemDefinition,
|
|
1617
|
+
profile,
|
|
1618
|
+
uiKit,
|
|
1619
|
+
enableMainnetL1MissFallback
|
|
1408
1620
|
]);
|
|
1409
1621
|
}
|
|
1410
1622
|
|
|
@@ -1615,5 +1827,5 @@ const NetworkSwitchManager = ({ wallet, networkCatalog, targetNetworkId, onNetwo
|
|
|
1615
1827
|
};
|
|
1616
1828
|
|
|
1617
1829
|
//#endregion
|
|
1618
|
-
export { AnalyticsContext, AnalyticsProvider, DEFAULT_CONFIG, NameResolutionContext, NameResolutionProvider, NetworkSwitchManager, RuntimeContext, RuntimeProvider, VERSION, WalletConnectionHeader, WalletConnectionUI, WalletStateContext, WalletStateProvider, useAnalytics, useDerivedAccountStatus, useDerivedChainInfo, useDerivedConnectStatus, useDerivedDisconnect, useDerivedSwitchChainStatus, useNameResolutionContext, useResolveAddress, useResolveName, useRuntimeContext, useRuntimeNameResolver, useWalletComponents, useWalletReconnectionHandler, useWalletState };
|
|
1830
|
+
export { AnalyticsContext, AnalyticsProvider, DEFAULT_CONFIG, DEFAULT_RUNTIME_CREATION_CONFIG, NameResolutionContext, NameResolutionProvider, NetworkSwitchManager, RuntimeContext, RuntimeProvider, VERSION, WalletConnectionHeader, WalletConnectionUI, WalletStateContext, WalletStateProvider, createResolveRuntime, isMainnetL1MissFallbackEnabled, useAnalytics, useDerivedAccountStatus, useDerivedChainInfo, useDerivedConnectStatus, useDerivedDisconnect, useDerivedSwitchChainStatus, useNameResolutionContext, useNetworkNameResolver, useNetworkResolveAddress, useResolveAddress, useResolveName, useResolveRuntime, useRuntimeContext, useRuntimeNameResolver, useWalletComponents, useWalletReconnectionHandler, useWalletState };
|
|
1619
1831
|
//# sourceMappingURL=index.mjs.map
|