@openzeppelin/ui-react 3.1.0 → 3.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.
- package/dist/index.cjs +148 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +37 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +145 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,7 @@ let _tanstack_react_query = require("@tanstack/react-query");
|
|
|
33
33
|
let _openzeppelin_ui_components = require("@openzeppelin/ui-components");
|
|
34
34
|
|
|
35
35
|
//#region src/version.ts
|
|
36
|
-
const VERSION = "3.
|
|
36
|
+
const VERSION = "3.2.0";
|
|
37
37
|
|
|
38
38
|
//#endregion
|
|
39
39
|
//#region src/hooks/AdapterContext.tsx
|
|
@@ -86,11 +86,31 @@ function RuntimeProvider({ children, resolveRuntime }) {
|
|
|
86
86
|
const [loadingNetworks, setLoadingNetworks] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
87
87
|
const runtimeRegistryRef = (0, react.useRef)(runtimeRegistry);
|
|
88
88
|
const failedNetworksRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
89
|
+
const resolverGenerationRef = (0, react.useRef)(0);
|
|
90
|
+
const resolverInitializedRef = (0, react.useRef)(false);
|
|
89
91
|
(0, react.useEffect)(() => {
|
|
90
92
|
runtimeRegistryRef.current = runtimeRegistry;
|
|
91
93
|
}, [runtimeRegistry]);
|
|
92
94
|
(0, react.useEffect)(() => {
|
|
95
|
+
if (resolverInitializedRef.current) resolverGenerationRef.current += 1;
|
|
96
|
+
else resolverInitializedRef.current = true;
|
|
97
|
+
const registry = runtimeRegistryRef.current;
|
|
98
|
+
const runtimes = Object.values(registry);
|
|
99
|
+
const hadCachedRuntimes = runtimes.length > 0;
|
|
93
100
|
failedNetworksRef.current = /* @__PURE__ */ new Set();
|
|
101
|
+
setLoadingNetworks(/* @__PURE__ */ new Set());
|
|
102
|
+
if (hadCachedRuntimes) {
|
|
103
|
+
setRuntimeRegistry({});
|
|
104
|
+
setTimeout(() => {
|
|
105
|
+
runtimes.forEach((runtime) => {
|
|
106
|
+
try {
|
|
107
|
+
runtime.dispose();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
_openzeppelin_ui_utils.logger.error("RuntimeProvider", "Error disposing runtime during registry flush:", error);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}, 0);
|
|
113
|
+
}
|
|
94
114
|
}, [resolveRuntime]);
|
|
95
115
|
(0, react.useEffect)(() => {
|
|
96
116
|
return () => {
|
|
@@ -178,7 +198,23 @@ function RuntimeProvider({ children, resolveRuntime }) {
|
|
|
178
198
|
return newSet;
|
|
179
199
|
});
|
|
180
200
|
_openzeppelin_ui_utils.logger.info("RuntimeProvider", `Starting runtime initialization for network ${networkId} (${networkConfig.name})`);
|
|
201
|
+
const generation = resolverGenerationRef.current;
|
|
181
202
|
resolveRuntime(networkConfig).then((runtime) => {
|
|
203
|
+
if (generation !== resolverGenerationRef.current) {
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
try {
|
|
206
|
+
runtime.dispose();
|
|
207
|
+
} catch (error) {
|
|
208
|
+
_openzeppelin_ui_utils.logger.error("RuntimeProvider", `Error disposing stale runtime for network ${networkId}:`, error);
|
|
209
|
+
}
|
|
210
|
+
}, 0);
|
|
211
|
+
setLoadingNetworks((prev) => {
|
|
212
|
+
const newSet = new Set(prev);
|
|
213
|
+
newSet.delete(networkId);
|
|
214
|
+
return newSet;
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
182
218
|
_openzeppelin_ui_utils.logger.info("RuntimeProvider", `Runtime for network ${networkId} loaded successfully`, {
|
|
183
219
|
type: runtime.constructor.name,
|
|
184
220
|
objectId: Object.prototype.toString.call(runtime)
|
|
@@ -193,6 +229,14 @@ function RuntimeProvider({ children, resolveRuntime }) {
|
|
|
193
229
|
return newSet;
|
|
194
230
|
});
|
|
195
231
|
}).catch((error) => {
|
|
232
|
+
if (generation !== resolverGenerationRef.current) {
|
|
233
|
+
setLoadingNetworks((prev) => {
|
|
234
|
+
const newSet = new Set(prev);
|
|
235
|
+
newSet.delete(networkId);
|
|
236
|
+
return newSet;
|
|
237
|
+
});
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
196
240
|
_openzeppelin_ui_utils.logger.error("RuntimeProvider", `Error loading runtime for network ${networkId}:`, error);
|
|
197
241
|
failedNetworksRef.current.add(networkId);
|
|
198
242
|
setLoadingNetworks((prev) => {
|
|
@@ -921,22 +965,42 @@ const DEFAULT_CONFIG = {
|
|
|
921
965
|
};
|
|
922
966
|
/** Stable prefix for every resolution cache key — namespaces this package's keys. */
|
|
923
967
|
const RESOLUTION_KEY_PREFIX = "oz-name-resolution";
|
|
968
|
+
const runtimeInstanceIds = /* @__PURE__ */ new WeakMap();
|
|
969
|
+
let nextRuntimeInstanceId = 1;
|
|
970
|
+
/**
|
|
971
|
+
* Assign a stable, serializable id to each {@link EcosystemRuntime} object identity.
|
|
972
|
+
* A disposed-and-recreated runtime (e.g. SF-4 opt-in toggle after INV-218 flush) gets
|
|
973
|
+
* a new id so resolution cache keys miss and results refresh (INV-230).
|
|
974
|
+
*/
|
|
975
|
+
function getRuntimeInstanceId(runtime) {
|
|
976
|
+
if (!runtime) return 0;
|
|
977
|
+
let id = runtimeInstanceIds.get(runtime);
|
|
978
|
+
if (id === void 0) {
|
|
979
|
+
id = nextRuntimeInstanceId;
|
|
980
|
+
nextRuntimeInstanceId += 1;
|
|
981
|
+
runtimeInstanceIds.set(runtime, id);
|
|
982
|
+
}
|
|
983
|
+
return id;
|
|
984
|
+
}
|
|
924
985
|
/**
|
|
925
986
|
* Build a network-scoped, namespace-separated cache key (INV-40). A name resolves
|
|
926
987
|
* differently per network and provenance can be chain-scoped, so `networkId` is
|
|
927
|
-
* part of the key; `namespace` keeps forward and reverse lookups disjoint
|
|
988
|
+
* part of the key; `namespace` keeps forward and reverse lookups disjoint;
|
|
989
|
+
* `runtimeInstanceId` scopes entries to the active capability instance (INV-230).
|
|
928
990
|
*
|
|
929
|
-
* @param namespace
|
|
930
|
-
* @param networkId
|
|
931
|
-
* @param normalizedInput
|
|
991
|
+
* @param namespace - `'name'` (forward) or `'addr'` (reverse).
|
|
992
|
+
* @param networkId - Active network id (`''` when no network is selected).
|
|
993
|
+
* @param normalizedInput - Trimmed + lowercased input (INV-26).
|
|
994
|
+
* @param runtimeInstanceId - Active runtime instance discriminator (`0` when absent).
|
|
932
995
|
* @returns A readonly tuple suitable for a TanStack Query `queryKey`.
|
|
933
996
|
*/
|
|
934
|
-
function buildResolutionKey(namespace, networkId, normalizedInput) {
|
|
997
|
+
function buildResolutionKey(namespace, networkId, normalizedInput, runtimeInstanceId = 0) {
|
|
935
998
|
return [
|
|
936
999
|
RESOLUTION_KEY_PREFIX,
|
|
937
1000
|
namespace,
|
|
938
1001
|
networkId,
|
|
939
|
-
normalizedInput
|
|
1002
|
+
normalizedInput,
|
|
1003
|
+
runtimeInstanceId
|
|
940
1004
|
];
|
|
941
1005
|
}
|
|
942
1006
|
/**
|
|
@@ -1135,12 +1199,13 @@ function useResolutionEngine(params) {
|
|
|
1135
1199
|
const normalizedKey = effectiveTrimmed.toLowerCase();
|
|
1136
1200
|
const capability = activeRuntime?.nameResolution;
|
|
1137
1201
|
const networkId = activeNetworkId ?? "";
|
|
1202
|
+
const runtimeInstanceId = getRuntimeInstanceId(activeRuntime);
|
|
1138
1203
|
const method = capability ? getMethod(capability) : void 0;
|
|
1139
1204
|
const liveAttemptable = capability ? shouldAttempt(capability, normalizedLive) : false;
|
|
1140
1205
|
const keyAttemptable = capability ? shouldAttempt(capability, normalizedKey) : false;
|
|
1141
1206
|
const queryEnabled = enabled && trimmedLive !== "" && capability != null && method != null && normalizedKey !== "" && keyAttemptable;
|
|
1142
1207
|
const query = (0, _tanstack_react_query.useQuery)({
|
|
1143
|
-
queryKey: buildResolutionKey(namespace, networkId, normalizedKey),
|
|
1208
|
+
queryKey: buildResolutionKey(namespace, networkId, normalizedKey, runtimeInstanceId),
|
|
1144
1209
|
queryFn: async () => {
|
|
1145
1210
|
if (!method) throw new ResolutionQueryError({
|
|
1146
1211
|
code: "ADAPTER_ERROR",
|
|
@@ -1387,8 +1452,10 @@ const EMPTY_RESOLVER = {};
|
|
|
1387
1452
|
function useRuntimeNameResolver() {
|
|
1388
1453
|
const walletState = (0, react.useContext)(WalletStateContext);
|
|
1389
1454
|
const { queryClient, config } = useNameResolutionContext();
|
|
1390
|
-
const
|
|
1455
|
+
const activeRuntime = walletState?.activeRuntime ?? null;
|
|
1456
|
+
const capability = activeRuntime?.nameResolution;
|
|
1391
1457
|
const networkId = walletState?.activeNetworkId ?? "";
|
|
1458
|
+
const runtimeInstanceId = getRuntimeInstanceId(activeRuntime);
|
|
1392
1459
|
return (0, react.useMemo)(() => {
|
|
1393
1460
|
if (!capability) return EMPTY_RESOLVER;
|
|
1394
1461
|
const resolveNameMethod = capability.resolveName;
|
|
@@ -1400,7 +1467,7 @@ function useRuntimeNameResolver() {
|
|
|
1400
1467
|
return {
|
|
1401
1468
|
ok: true,
|
|
1402
1469
|
value: await queryClient.fetchQuery({
|
|
1403
|
-
queryKey: buildResolutionKey("name", networkId, normalized),
|
|
1470
|
+
queryKey: buildResolutionKey("name", networkId, normalized, runtimeInstanceId),
|
|
1404
1471
|
queryFn: async () => {
|
|
1405
1472
|
let result;
|
|
1406
1473
|
try {
|
|
@@ -1432,7 +1499,73 @@ function useRuntimeNameResolver() {
|
|
|
1432
1499
|
capability,
|
|
1433
1500
|
queryClient,
|
|
1434
1501
|
config,
|
|
1435
|
-
networkId
|
|
1502
|
+
networkId,
|
|
1503
|
+
runtimeInstanceId
|
|
1504
|
+
]);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
//#endregion
|
|
1508
|
+
//#region src/hooks/runtime/runtimeCreationConfig.ts
|
|
1509
|
+
/** Safe default: miss-fallback OFF; no uiKit override. INV-204 */
|
|
1510
|
+
const DEFAULT_RUNTIME_CREATION_CONFIG = {};
|
|
1511
|
+
/**
|
|
1512
|
+
* Normalizes the opt-in flag to the adapter's strict-enable contract.
|
|
1513
|
+
* UIKit uses this at the threading boundary so `false` and `undefined` never
|
|
1514
|
+
* emit `enableMainnetL1MissFallback: false` into adapter options (absent = OFF).
|
|
1515
|
+
*/
|
|
1516
|
+
function isMainnetL1MissFallbackEnabled(options) {
|
|
1517
|
+
return options?.enableMainnetL1MissFallback === true;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Builds the `createRuntime` options bag for adapter threading.
|
|
1521
|
+
* When OFF, `nameResolution` is omitted (INV-207). When ON, spreads only
|
|
1522
|
+
* `{ enableMainnetL1MissFallback: true }` (INV-208).
|
|
1523
|
+
*/
|
|
1524
|
+
function buildCreateRuntimeOptions(options) {
|
|
1525
|
+
return {
|
|
1526
|
+
...options?.uiKit !== void 0 ? { uiKit: options.uiKit } : {},
|
|
1527
|
+
...isMainnetL1MissFallbackEnabled(options?.nameResolution) ? { nameResolution: { enableMainnetL1MissFallback: true } } : {}
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
//#endregion
|
|
1532
|
+
//#region src/hooks/runtime/createResolveRuntime.ts
|
|
1533
|
+
/**
|
|
1534
|
+
* Build a `resolveRuntime` callback for {@link RuntimeProvider} that forwards
|
|
1535
|
+
* `CreateRuntimeOptions` to `ecosystemDefinition.createRuntime`.
|
|
1536
|
+
*
|
|
1537
|
+
* Does not cache — {@link RuntimeProvider} owns the per-network singleton registry.
|
|
1538
|
+
*/
|
|
1539
|
+
function createResolveRuntime(ecosystemDefinition, params) {
|
|
1540
|
+
const { profile, options } = params;
|
|
1541
|
+
const mergedOptions = buildCreateRuntimeOptions(options);
|
|
1542
|
+
return (networkConfig) => Promise.resolve(ecosystemDefinition.createRuntime(profile, networkConfig, mergedOptions));
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
//#endregion
|
|
1546
|
+
//#region src/hooks/runtime/useResolveRuntime.ts
|
|
1547
|
+
/**
|
|
1548
|
+
* Memoized {@link createResolveRuntime} for React apps. Recompute when
|
|
1549
|
+
* `ecosystemDefinition`, `profile`, or opt-in posture change (INV-217, INV-222).
|
|
1550
|
+
*
|
|
1551
|
+
* Changing the returned function identity MUST trigger runtime registry flush
|
|
1552
|
+
* in {@link RuntimeProvider} (INV-218).
|
|
1553
|
+
*/
|
|
1554
|
+
function useResolveRuntime(ecosystemDefinition, params) {
|
|
1555
|
+
const { profile, options } = params;
|
|
1556
|
+
const uiKit = options?.uiKit;
|
|
1557
|
+
const enableMainnetL1MissFallback = options?.nameResolution?.enableMainnetL1MissFallback;
|
|
1558
|
+
return (0, react.useMemo)(() => createResolveRuntime(ecosystemDefinition, {
|
|
1559
|
+
profile,
|
|
1560
|
+
options: {
|
|
1561
|
+
...uiKit !== void 0 ? { uiKit } : {},
|
|
1562
|
+
...enableMainnetL1MissFallback === true ? { nameResolution: { enableMainnetL1MissFallback: true } } : {}
|
|
1563
|
+
}
|
|
1564
|
+
}), [
|
|
1565
|
+
ecosystemDefinition,
|
|
1566
|
+
profile,
|
|
1567
|
+
uiKit,
|
|
1568
|
+
enableMainnetL1MissFallback
|
|
1436
1569
|
]);
|
|
1437
1570
|
}
|
|
1438
1571
|
|
|
@@ -1646,6 +1779,7 @@ const NetworkSwitchManager = ({ wallet, networkCatalog, targetNetworkId, onNetwo
|
|
|
1646
1779
|
exports.AnalyticsContext = AnalyticsContext;
|
|
1647
1780
|
exports.AnalyticsProvider = AnalyticsProvider;
|
|
1648
1781
|
exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
|
|
1782
|
+
exports.DEFAULT_RUNTIME_CREATION_CONFIG = DEFAULT_RUNTIME_CREATION_CONFIG;
|
|
1649
1783
|
exports.NameResolutionContext = NameResolutionContext;
|
|
1650
1784
|
exports.NameResolutionProvider = NameResolutionProvider;
|
|
1651
1785
|
exports.NetworkSwitchManager = NetworkSwitchManager;
|
|
@@ -1656,6 +1790,8 @@ exports.WalletConnectionHeader = WalletConnectionHeader;
|
|
|
1656
1790
|
exports.WalletConnectionUI = WalletConnectionUI;
|
|
1657
1791
|
exports.WalletStateContext = WalletStateContext;
|
|
1658
1792
|
exports.WalletStateProvider = WalletStateProvider;
|
|
1793
|
+
exports.createResolveRuntime = createResolveRuntime;
|
|
1794
|
+
exports.isMainnetL1MissFallbackEnabled = isMainnetL1MissFallbackEnabled;
|
|
1659
1795
|
exports.useAnalytics = useAnalytics;
|
|
1660
1796
|
exports.useDerivedAccountStatus = useDerivedAccountStatus;
|
|
1661
1797
|
exports.useDerivedChainInfo = useDerivedChainInfo;
|
|
@@ -1665,6 +1801,7 @@ exports.useDerivedSwitchChainStatus = useDerivedSwitchChainStatus;
|
|
|
1665
1801
|
exports.useNameResolutionContext = useNameResolutionContext;
|
|
1666
1802
|
exports.useResolveAddress = useResolveAddress;
|
|
1667
1803
|
exports.useResolveName = useResolveName;
|
|
1804
|
+
exports.useResolveRuntime = useResolveRuntime;
|
|
1668
1805
|
exports.useRuntimeContext = useRuntimeContext;
|
|
1669
1806
|
exports.useRuntimeNameResolver = useRuntimeNameResolver;
|
|
1670
1807
|
exports.useWalletComponents = useWalletComponents;
|