@oydual31/more-vaults-sdk 0.2.1 → 0.2.3

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.
@@ -1031,84 +1031,6 @@ async function isAsyncMode(publicClient, vault) {
1031
1031
  });
1032
1032
  return !oraclesEnabled;
1033
1033
  }
1034
- var OMNI_FACTORY_ADDRESS = "0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C";
1035
- var FACTORY_ABI = [
1036
- {
1037
- name: "localEid",
1038
- type: "function",
1039
- inputs: [],
1040
- outputs: [{ type: "uint32" }],
1041
- stateMutability: "view"
1042
- },
1043
- {
1044
- name: "isCrossChainVault",
1045
- type: "function",
1046
- inputs: [{ name: "__eid", type: "uint32" }, { name: "_vault", type: "address" }],
1047
- outputs: [{ type: "bool" }],
1048
- stateMutability: "view"
1049
- },
1050
- {
1051
- name: "hubToSpokes",
1052
- type: "function",
1053
- inputs: [{ name: "__eid", type: "uint32" }, { name: "_hubVault", type: "address" }],
1054
- outputs: [{ name: "eids", type: "uint32[]" }, { name: "vaults", type: "address[]" }],
1055
- stateMutability: "view"
1056
- },
1057
- {
1058
- name: "spokeToHub",
1059
- type: "function",
1060
- inputs: [{ name: "__eid", type: "uint32" }, { name: "_spokeVault", type: "address" }],
1061
- outputs: [{ name: "eid", type: "uint32" }, { name: "vault", type: "address" }],
1062
- stateMutability: "view"
1063
- }
1064
- ];
1065
- async function getVaultTopology(publicClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1066
- const v = viem.getAddress(vault);
1067
- const f = viem.getAddress(factoryAddress);
1068
- const localEid = await publicClient.readContract({
1069
- address: f,
1070
- abi: FACTORY_ABI,
1071
- functionName: "localEid"
1072
- });
1073
- const isHub = await publicClient.readContract({
1074
- address: f,
1075
- abi: FACTORY_ABI,
1076
- functionName: "isCrossChainVault",
1077
- args: [localEid, v]
1078
- });
1079
- if (isHub) {
1080
- const [spokeEids] = await publicClient.readContract({
1081
- address: f,
1082
- abi: FACTORY_ABI,
1083
- functionName: "hubToSpokes",
1084
- args: [localEid, v]
1085
- });
1086
- const localChainId2 = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1087
- const spokeChainIds = spokeEids.map((eid) => EID_TO_CHAIN_ID[eid]).filter((id) => id !== void 0);
1088
- return { role: "hub", hubChainId: localChainId2, spokeChainIds };
1089
- }
1090
- const [hubEid, hubVault] = await publicClient.readContract({
1091
- address: f,
1092
- abi: FACTORY_ABI,
1093
- functionName: "spokeToHub",
1094
- args: [localEid, v]
1095
- });
1096
- if (hubEid !== 0 && hubVault !== "0x0000000000000000000000000000000000000000") {
1097
- const hubChainId = EID_TO_CHAIN_ID[hubEid] ?? 0;
1098
- const spokeChainIds = [];
1099
- const localChainId2 = EID_TO_CHAIN_ID[localEid];
1100
- if (localChainId2 !== void 0) spokeChainIds.push(localChainId2);
1101
- return { role: "spoke", hubChainId, spokeChainIds };
1102
- }
1103
- const localChainId = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1104
- return { role: "local", hubChainId: localChainId, spokeChainIds: [] };
1105
- }
1106
- function isOnHubChain(currentChainId, topology) {
1107
- return currentChainId === topology.hubChainId;
1108
- }
1109
- function getAllVaultChainIds(topology) {
1110
- return [topology.hubChainId, ...topology.spokeChainIds];
1111
- }
1112
1034
  var PUBLIC_RPCS = {
1113
1035
  1: [
1114
1036
  "https://ethereum-rpc.publicnode.com",
@@ -1299,6 +1221,144 @@ async function getUserBalancesForRoutes(routes, userAddress) {
1299
1221
  );
1300
1222
  }
1301
1223
 
1224
+ // src/viem/topology.ts
1225
+ var OMNI_FACTORY_ADDRESS = "0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C";
1226
+ var FACTORY_ABI = [
1227
+ {
1228
+ name: "localEid",
1229
+ type: "function",
1230
+ inputs: [],
1231
+ outputs: [{ type: "uint32" }],
1232
+ stateMutability: "view"
1233
+ },
1234
+ {
1235
+ name: "isCrossChainVault",
1236
+ type: "function",
1237
+ inputs: [{ name: "__eid", type: "uint32" }, { name: "_vault", type: "address" }],
1238
+ outputs: [{ type: "bool" }],
1239
+ stateMutability: "view"
1240
+ },
1241
+ {
1242
+ name: "hubToSpokes",
1243
+ type: "function",
1244
+ inputs: [{ name: "__eid", type: "uint32" }, { name: "_hubVault", type: "address" }],
1245
+ outputs: [{ name: "eids", type: "uint32[]" }, { name: "vaults", type: "address[]" }],
1246
+ stateMutability: "view"
1247
+ },
1248
+ {
1249
+ name: "spokeToHub",
1250
+ type: "function",
1251
+ inputs: [{ name: "__eid", type: "uint32" }, { name: "_spokeVault", type: "address" }],
1252
+ outputs: [{ name: "eid", type: "uint32" }, { name: "vault", type: "address" }],
1253
+ stateMutability: "view"
1254
+ }
1255
+ ];
1256
+ async function getVaultTopology(publicClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1257
+ const v = viem.getAddress(vault);
1258
+ const f = viem.getAddress(factoryAddress);
1259
+ const localEid = await publicClient.readContract({
1260
+ address: f,
1261
+ abi: FACTORY_ABI,
1262
+ functionName: "localEid"
1263
+ });
1264
+ const isHub = await publicClient.readContract({
1265
+ address: f,
1266
+ abi: FACTORY_ABI,
1267
+ functionName: "isCrossChainVault",
1268
+ args: [localEid, v]
1269
+ });
1270
+ if (isHub) {
1271
+ const [spokeEids] = await publicClient.readContract({
1272
+ address: f,
1273
+ abi: FACTORY_ABI,
1274
+ functionName: "hubToSpokes",
1275
+ args: [localEid, v]
1276
+ });
1277
+ const localChainId2 = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1278
+ const spokeChainIds = spokeEids.map((eid) => EID_TO_CHAIN_ID[eid]).filter((id) => id !== void 0);
1279
+ return { role: "hub", hubChainId: localChainId2, spokeChainIds };
1280
+ }
1281
+ const [hubEid, hubVault] = await publicClient.readContract({
1282
+ address: f,
1283
+ abi: FACTORY_ABI,
1284
+ functionName: "spokeToHub",
1285
+ args: [localEid, v]
1286
+ });
1287
+ if (hubEid !== 0 && hubVault !== "0x0000000000000000000000000000000000000000") {
1288
+ const hubChainId = EID_TO_CHAIN_ID[hubEid] ?? 0;
1289
+ const spokeChainIds = [];
1290
+ const localChainId2 = EID_TO_CHAIN_ID[localEid];
1291
+ if (localChainId2 !== void 0) spokeChainIds.push(localChainId2);
1292
+ return { role: "spoke", hubChainId, spokeChainIds };
1293
+ }
1294
+ const localChainId = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1295
+ return { role: "local", hubChainId: localChainId, spokeChainIds: [] };
1296
+ }
1297
+ async function getFullVaultTopology(hubChainClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1298
+ const topo = await getVaultTopology(hubChainClient, vault, factoryAddress);
1299
+ if (topo.role !== "hub") {
1300
+ throw new Error(
1301
+ `getFullVaultTopology: client must be connected to the hub chain (${topo.hubChainId}), but got role="${topo.role}". Connect to chainId ${topo.hubChainId} instead.`
1302
+ );
1303
+ }
1304
+ return topo;
1305
+ }
1306
+ var DISCOVERY_CHAIN_IDS = Object.values(CHAIN_IDS).filter(
1307
+ (id) => id !== 545
1308
+ // exclude testnet
1309
+ );
1310
+ async function discoverVaultTopology(vault, publicClient, factoryAddress = OMNI_FACTORY_ADDRESS) {
1311
+ const v = viem.getAddress(vault);
1312
+ let triedChainId;
1313
+ if (publicClient) {
1314
+ try {
1315
+ const topo = await getVaultTopology(publicClient, v, factoryAddress);
1316
+ if (topo.role !== "local") {
1317
+ if (topo.role === "spoke") {
1318
+ const hubClient = createChainClient(topo.hubChainId);
1319
+ if (hubClient) {
1320
+ try {
1321
+ return await getFullVaultTopology(hubClient, v, factoryAddress);
1322
+ } catch {
1323
+ }
1324
+ }
1325
+ }
1326
+ return topo;
1327
+ }
1328
+ triedChainId = publicClient.chain?.id;
1329
+ } catch {
1330
+ }
1331
+ }
1332
+ for (const chainId of DISCOVERY_CHAIN_IDS) {
1333
+ if (chainId === triedChainId) continue;
1334
+ const client = createChainClient(chainId);
1335
+ if (!client) continue;
1336
+ try {
1337
+ const topo = await getVaultTopology(client, v, factoryAddress);
1338
+ if (topo.role === "hub") return topo;
1339
+ if (topo.role === "spoke") {
1340
+ const hubClient = createChainClient(topo.hubChainId);
1341
+ if (hubClient) {
1342
+ try {
1343
+ return await getFullVaultTopology(hubClient, v, factoryAddress);
1344
+ } catch {
1345
+ return topo;
1346
+ }
1347
+ }
1348
+ return topo;
1349
+ }
1350
+ } catch {
1351
+ }
1352
+ }
1353
+ return { role: "local", hubChainId: 0, spokeChainIds: [] };
1354
+ }
1355
+ function isOnHubChain(currentChainId, topology) {
1356
+ return currentChainId === topology.hubChainId;
1357
+ }
1358
+ function getAllVaultChainIds(topology) {
1359
+ return [topology.hubChainId, ...topology.spokeChainIds];
1360
+ }
1361
+
1302
1362
  // src/viem/preflight.ts
1303
1363
  async function preflightAsync(publicClient, vault, escrow) {
1304
1364
  const v = viem.getAddress(vault);
@@ -1787,9 +1847,14 @@ function useVaultTopology(vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1787
1847
  const currentChainId = wagmi.useChainId();
1788
1848
  const publicClient = wagmi.usePublicClient();
1789
1849
  const { data: topology, isLoading } = reactQuery.useQuery({
1790
- queryKey: ["vaultTopology", vault, currentChainId, factoryAddress],
1791
- queryFn: () => getVaultTopology(asSdkClient(publicClient), vault, factoryAddress),
1792
- enabled: !!vault && !!publicClient,
1850
+ // Key does NOT include currentChainId — topology is chain-independent
1851
+ queryKey: ["vaultTopology", vault, factoryAddress],
1852
+ queryFn: () => discoverVaultTopology(
1853
+ vault,
1854
+ publicClient ? asSdkClient(publicClient) : null,
1855
+ factoryAddress
1856
+ ),
1857
+ enabled: !!vault,
1793
1858
  staleTime: 5 * 60 * 1e3
1794
1859
  // topology rarely changes — 5 min cache
1795
1860
  });
@@ -1974,9 +2039,12 @@ function useRedeemShares(vault, chainId) {
1974
2039
  };
1975
2040
  }
1976
2041
  function useVaultDistribution(vault) {
1977
- const chainId = wagmi.useChainId();
1978
- const publicClient = wagmi.usePublicClient();
1979
- const { topology } = useVaultTopology(vault);
2042
+ const { data: topology } = reactQuery.useQuery({
2043
+ queryKey: ["vaultTopology", vault],
2044
+ queryFn: () => discoverVaultTopology(vault),
2045
+ enabled: !!vault,
2046
+ staleTime: 5 * 60 * 1e3
2047
+ });
1980
2048
  const spokeClients = react.useMemo(() => {
1981
2049
  if (!topology) return {};
1982
2050
  const clients = {};
@@ -1987,13 +2055,13 @@ function useVaultDistribution(vault) {
1987
2055
  return clients;
1988
2056
  }, [topology]);
1989
2057
  const { data: distribution, isLoading } = reactQuery.useQuery({
1990
- queryKey: ["vaultDistribution", vault, chainId],
1991
- queryFn: () => getVaultDistribution(
1992
- asSdkClient(publicClient),
1993
- vault,
1994
- spokeClients
1995
- ),
1996
- enabled: !!vault && !!publicClient,
2058
+ queryKey: ["vaultDistribution", vault, topology?.hubChainId],
2059
+ queryFn: () => {
2060
+ const hubClient = createChainClient(topology.hubChainId);
2061
+ if (!hubClient) throw new Error(`No public RPC for hub chainId ${topology.hubChainId}`);
2062
+ return getVaultDistribution(hubClient, vault, spokeClients);
2063
+ },
2064
+ enabled: !!vault && !!topology && topology.role !== "local",
1997
2065
  staleTime: 3e4
1998
2066
  });
1999
2067
  return { distribution, isLoading };