@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.
@@ -342,6 +342,31 @@ declare function getVaultTopology(publicClient: PublicClient, vault: Address, fa
342
342
  * @param factoryAddress MoreVaults factory (defaults to OMNI_FACTORY_ADDRESS)
343
343
  */
344
344
  declare function getFullVaultTopology(hubChainClient: PublicClient, vault: Address, factoryAddress?: Address): Promise<VaultTopology>;
345
+ /**
346
+ * Discover a vault's topology across all supported chains.
347
+ *
348
+ * Unlike `getVaultTopology` (which queries a single chain), this function
349
+ * automatically iterates all supported chains when the initial query returns
350
+ * `role: "local"`. This handles the case where the caller doesn't know which
351
+ * chain the vault is deployed on, or when no wallet is connected.
352
+ *
353
+ * If a `publicClient` is provided, it's tried first. If that returns "local",
354
+ * every other supported chain is probed via `createChainClient` (public RPCs).
355
+ * If no `publicClient` is provided, all chains are probed.
356
+ *
357
+ * Once a hub is found, `getFullVaultTopology` is called to get the complete
358
+ * spoke list.
359
+ *
360
+ * @param vault Vault address (same on all chains via CREATE3)
361
+ * @param publicClient Optional — client for the "preferred" chain to try first
362
+ * @param factoryAddress MoreVaults factory (defaults to OMNI_FACTORY_ADDRESS)
363
+ *
364
+ * @example
365
+ * // No wallet connected — discovers that 0x8f74... is hub on Base
366
+ * const topo = await discoverVaultTopology('0x8f740...')
367
+ * // { role: 'hub', hubChainId: 8453, spokeChainIds: [1, 42161] }
368
+ */
369
+ declare function discoverVaultTopology(vault: Address, publicClient?: PublicClient | null, factoryAddress?: Address): Promise<VaultTopology>;
345
370
  /**
346
371
  * Check if a wallet is connected to the hub chain for a given vault.
347
372
  * Useful for showing a "Switch to Base" prompt before deposit.
@@ -514,4 +539,4 @@ declare function getOutboundRoutes(hubChainId: number, vault: Address): Promise<
514
539
  */
515
540
  declare function quoteRouteDepositFee(route: InboundRoute, hubChainId: number, amount: bigint, userAddress: Address): Promise<bigint>;
516
541
 
517
- export { type AsyncRequestStatus as A, getVaultSummary as B, getVaultTopology as C, type DepositBlockReason as D, isAsyncMode as E, isOnHubChain as F, previewDeposit as G, previewRedeem as H, type InboundRoute as I, quoteLzFee as J, quoteRouteDepositFee as K, waitForTx as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, type SpokeBalance as S, type UserBalances as U, type VaultDistribution as V, type AsyncRequestStatusInfo as a, type DepositEligibility as b, type InboundRouteWithBalance as c, type OutboundRoute as d, type UserPosition as e, type VaultMetadata as f, type VaultMode as g, type VaultStatus as h, type VaultSummary as i, type VaultTopology as j, canDeposit as k, ensureAllowance as l, getAllVaultChainIds as m, getAsyncRequestStatus as n, getAsyncRequestStatusLabel as o, getFullVaultTopology as p, getInboundRoutes as q, getMaxWithdrawable as r, getOutboundRoutes as s, getUserBalances as t, getUserBalancesForRoutes as u, getUserPosition as v, getVaultDistribution as w, getVaultDistributionWithTopology as x, getVaultMetadata as y, getVaultStatus as z };
542
+ export { type AsyncRequestStatus as A, getVaultStatus as B, getVaultSummary as C, type DepositBlockReason as D, getVaultTopology as E, isAsyncMode as F, isOnHubChain as G, previewDeposit as H, type InboundRoute as I, previewRedeem as J, quoteLzFee as K, quoteRouteDepositFee as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, waitForTx as P, type SpokeBalance as S, type UserBalances as U, type VaultDistribution as V, type AsyncRequestStatusInfo as a, type DepositEligibility as b, type InboundRouteWithBalance as c, type OutboundRoute as d, type UserPosition as e, type VaultMetadata as f, type VaultMode as g, type VaultStatus as h, type VaultSummary as i, type VaultTopology as j, canDeposit as k, discoverVaultTopology as l, ensureAllowance as m, getAllVaultChainIds as n, getAsyncRequestStatus as o, getAsyncRequestStatusLabel as p, getFullVaultTopology as q, getInboundRoutes as r, getMaxWithdrawable as s, getOutboundRoutes as t, getUserBalances as u, getUserBalancesForRoutes as v, getUserPosition as w, getVaultDistribution as x, getVaultDistributionWithTopology as y, getVaultMetadata as z };
@@ -342,6 +342,31 @@ declare function getVaultTopology(publicClient: PublicClient, vault: Address, fa
342
342
  * @param factoryAddress MoreVaults factory (defaults to OMNI_FACTORY_ADDRESS)
343
343
  */
344
344
  declare function getFullVaultTopology(hubChainClient: PublicClient, vault: Address, factoryAddress?: Address): Promise<VaultTopology>;
345
+ /**
346
+ * Discover a vault's topology across all supported chains.
347
+ *
348
+ * Unlike `getVaultTopology` (which queries a single chain), this function
349
+ * automatically iterates all supported chains when the initial query returns
350
+ * `role: "local"`. This handles the case where the caller doesn't know which
351
+ * chain the vault is deployed on, or when no wallet is connected.
352
+ *
353
+ * If a `publicClient` is provided, it's tried first. If that returns "local",
354
+ * every other supported chain is probed via `createChainClient` (public RPCs).
355
+ * If no `publicClient` is provided, all chains are probed.
356
+ *
357
+ * Once a hub is found, `getFullVaultTopology` is called to get the complete
358
+ * spoke list.
359
+ *
360
+ * @param vault Vault address (same on all chains via CREATE3)
361
+ * @param publicClient Optional — client for the "preferred" chain to try first
362
+ * @param factoryAddress MoreVaults factory (defaults to OMNI_FACTORY_ADDRESS)
363
+ *
364
+ * @example
365
+ * // No wallet connected — discovers that 0x8f74... is hub on Base
366
+ * const topo = await discoverVaultTopology('0x8f740...')
367
+ * // { role: 'hub', hubChainId: 8453, spokeChainIds: [1, 42161] }
368
+ */
369
+ declare function discoverVaultTopology(vault: Address, publicClient?: PublicClient | null, factoryAddress?: Address): Promise<VaultTopology>;
345
370
  /**
346
371
  * Check if a wallet is connected to the hub chain for a given vault.
347
372
  * Useful for showing a "Switch to Base" prompt before deposit.
@@ -514,4 +539,4 @@ declare function getOutboundRoutes(hubChainId: number, vault: Address): Promise<
514
539
  */
515
540
  declare function quoteRouteDepositFee(route: InboundRoute, hubChainId: number, amount: bigint, userAddress: Address): Promise<bigint>;
516
541
 
517
- export { type AsyncRequestStatus as A, getVaultSummary as B, getVaultTopology as C, type DepositBlockReason as D, isAsyncMode as E, isOnHubChain as F, previewDeposit as G, previewRedeem as H, type InboundRoute as I, quoteLzFee as J, quoteRouteDepositFee as K, waitForTx as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, type SpokeBalance as S, type UserBalances as U, type VaultDistribution as V, type AsyncRequestStatusInfo as a, type DepositEligibility as b, type InboundRouteWithBalance as c, type OutboundRoute as d, type UserPosition as e, type VaultMetadata as f, type VaultMode as g, type VaultStatus as h, type VaultSummary as i, type VaultTopology as j, canDeposit as k, ensureAllowance as l, getAllVaultChainIds as m, getAsyncRequestStatus as n, getAsyncRequestStatusLabel as o, getFullVaultTopology as p, getInboundRoutes as q, getMaxWithdrawable as r, getOutboundRoutes as s, getUserBalances as t, getUserBalancesForRoutes as u, getUserPosition as v, getVaultDistribution as w, getVaultDistributionWithTopology as x, getVaultMetadata as y, getVaultStatus as z };
542
+ export { type AsyncRequestStatus as A, getVaultStatus as B, getVaultSummary as C, type DepositBlockReason as D, getVaultTopology as E, isAsyncMode as F, isOnHubChain as G, previewDeposit as H, type InboundRoute as I, previewRedeem as J, quoteLzFee as K, quoteRouteDepositFee as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, waitForTx as P, type SpokeBalance as S, type UserBalances as U, type VaultDistribution as V, type AsyncRequestStatusInfo as a, type DepositEligibility as b, type InboundRouteWithBalance as c, type OutboundRoute as d, type UserPosition as e, type VaultMetadata as f, type VaultMode as g, type VaultStatus as h, type VaultSummary as i, type VaultTopology as j, canDeposit as k, discoverVaultTopology as l, ensureAllowance as m, getAllVaultChainIds as n, getAsyncRequestStatus as o, getAsyncRequestStatusLabel as p, getFullVaultTopology as q, getInboundRoutes as r, getMaxWithdrawable as s, getOutboundRoutes as t, getUserBalances as u, getUserBalancesForRoutes as v, getUserPosition as w, getVaultDistribution as x, getVaultDistributionWithTopology as y, getVaultMetadata as z };
@@ -1134,93 +1134,6 @@ async function getAsyncRequestStatus(publicClient, vault, guid) {
1134
1134
  result: finalizationResult
1135
1135
  };
1136
1136
  }
1137
- var OMNI_FACTORY_ADDRESS = "0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C";
1138
- var FACTORY_ABI = [
1139
- {
1140
- name: "localEid",
1141
- type: "function",
1142
- inputs: [],
1143
- outputs: [{ type: "uint32" }],
1144
- stateMutability: "view"
1145
- },
1146
- {
1147
- name: "isCrossChainVault",
1148
- type: "function",
1149
- inputs: [{ name: "__eid", type: "uint32" }, { name: "_vault", type: "address" }],
1150
- outputs: [{ type: "bool" }],
1151
- stateMutability: "view"
1152
- },
1153
- {
1154
- name: "hubToSpokes",
1155
- type: "function",
1156
- inputs: [{ name: "__eid", type: "uint32" }, { name: "_hubVault", type: "address" }],
1157
- outputs: [{ name: "eids", type: "uint32[]" }, { name: "vaults", type: "address[]" }],
1158
- stateMutability: "view"
1159
- },
1160
- {
1161
- name: "spokeToHub",
1162
- type: "function",
1163
- inputs: [{ name: "__eid", type: "uint32" }, { name: "_spokeVault", type: "address" }],
1164
- outputs: [{ name: "eid", type: "uint32" }, { name: "vault", type: "address" }],
1165
- stateMutability: "view"
1166
- }
1167
- ];
1168
- async function getVaultTopology(publicClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1169
- const v = viem.getAddress(vault);
1170
- const f = viem.getAddress(factoryAddress);
1171
- const localEid = await publicClient.readContract({
1172
- address: f,
1173
- abi: FACTORY_ABI,
1174
- functionName: "localEid"
1175
- });
1176
- const isHub = await publicClient.readContract({
1177
- address: f,
1178
- abi: FACTORY_ABI,
1179
- functionName: "isCrossChainVault",
1180
- args: [localEid, v]
1181
- });
1182
- if (isHub) {
1183
- const [spokeEids] = await publicClient.readContract({
1184
- address: f,
1185
- abi: FACTORY_ABI,
1186
- functionName: "hubToSpokes",
1187
- args: [localEid, v]
1188
- });
1189
- const localChainId2 = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1190
- const spokeChainIds = spokeEids.map((eid) => EID_TO_CHAIN_ID[eid]).filter((id) => id !== void 0);
1191
- return { role: "hub", hubChainId: localChainId2, spokeChainIds };
1192
- }
1193
- const [hubEid, hubVault] = await publicClient.readContract({
1194
- address: f,
1195
- abi: FACTORY_ABI,
1196
- functionName: "spokeToHub",
1197
- args: [localEid, v]
1198
- });
1199
- if (hubEid !== 0 && hubVault !== "0x0000000000000000000000000000000000000000") {
1200
- const hubChainId = EID_TO_CHAIN_ID[hubEid] ?? 0;
1201
- const spokeChainIds = [];
1202
- const localChainId2 = EID_TO_CHAIN_ID[localEid];
1203
- if (localChainId2 !== void 0) spokeChainIds.push(localChainId2);
1204
- return { role: "spoke", hubChainId, spokeChainIds };
1205
- }
1206
- const localChainId = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1207
- return { role: "local", hubChainId: localChainId, spokeChainIds: [] };
1208
- }
1209
- async function getFullVaultTopology(hubChainClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1210
- const topo = await getVaultTopology(hubChainClient, vault, factoryAddress);
1211
- if (topo.role !== "hub") {
1212
- throw new Error(
1213
- `getFullVaultTopology: client must be connected to the hub chain (${topo.hubChainId}), but got role="${topo.role}". Connect to chainId ${topo.hubChainId} instead.`
1214
- );
1215
- }
1216
- return topo;
1217
- }
1218
- function isOnHubChain(currentChainId, topology) {
1219
- return currentChainId === topology.hubChainId;
1220
- }
1221
- function getAllVaultChainIds(topology) {
1222
- return [topology.hubChainId, ...topology.spokeChainIds];
1223
- }
1224
1137
  var PUBLIC_RPCS = {
1225
1138
  1: [
1226
1139
  "https://ethereum-rpc.publicnode.com",
@@ -1461,6 +1374,144 @@ async function quoteRouteDepositFee(route, hubChainId, amount, userAddress) {
1461
1374
  return fee.nativeFee;
1462
1375
  }
1463
1376
 
1377
+ // src/viem/topology.ts
1378
+ var OMNI_FACTORY_ADDRESS = "0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C";
1379
+ var FACTORY_ABI = [
1380
+ {
1381
+ name: "localEid",
1382
+ type: "function",
1383
+ inputs: [],
1384
+ outputs: [{ type: "uint32" }],
1385
+ stateMutability: "view"
1386
+ },
1387
+ {
1388
+ name: "isCrossChainVault",
1389
+ type: "function",
1390
+ inputs: [{ name: "__eid", type: "uint32" }, { name: "_vault", type: "address" }],
1391
+ outputs: [{ type: "bool" }],
1392
+ stateMutability: "view"
1393
+ },
1394
+ {
1395
+ name: "hubToSpokes",
1396
+ type: "function",
1397
+ inputs: [{ name: "__eid", type: "uint32" }, { name: "_hubVault", type: "address" }],
1398
+ outputs: [{ name: "eids", type: "uint32[]" }, { name: "vaults", type: "address[]" }],
1399
+ stateMutability: "view"
1400
+ },
1401
+ {
1402
+ name: "spokeToHub",
1403
+ type: "function",
1404
+ inputs: [{ name: "__eid", type: "uint32" }, { name: "_spokeVault", type: "address" }],
1405
+ outputs: [{ name: "eid", type: "uint32" }, { name: "vault", type: "address" }],
1406
+ stateMutability: "view"
1407
+ }
1408
+ ];
1409
+ async function getVaultTopology(publicClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1410
+ const v = viem.getAddress(vault);
1411
+ const f = viem.getAddress(factoryAddress);
1412
+ const localEid = await publicClient.readContract({
1413
+ address: f,
1414
+ abi: FACTORY_ABI,
1415
+ functionName: "localEid"
1416
+ });
1417
+ const isHub = await publicClient.readContract({
1418
+ address: f,
1419
+ abi: FACTORY_ABI,
1420
+ functionName: "isCrossChainVault",
1421
+ args: [localEid, v]
1422
+ });
1423
+ if (isHub) {
1424
+ const [spokeEids] = await publicClient.readContract({
1425
+ address: f,
1426
+ abi: FACTORY_ABI,
1427
+ functionName: "hubToSpokes",
1428
+ args: [localEid, v]
1429
+ });
1430
+ const localChainId2 = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1431
+ const spokeChainIds = spokeEids.map((eid) => EID_TO_CHAIN_ID[eid]).filter((id) => id !== void 0);
1432
+ return { role: "hub", hubChainId: localChainId2, spokeChainIds };
1433
+ }
1434
+ const [hubEid, hubVault] = await publicClient.readContract({
1435
+ address: f,
1436
+ abi: FACTORY_ABI,
1437
+ functionName: "spokeToHub",
1438
+ args: [localEid, v]
1439
+ });
1440
+ if (hubEid !== 0 && hubVault !== "0x0000000000000000000000000000000000000000") {
1441
+ const hubChainId = EID_TO_CHAIN_ID[hubEid] ?? 0;
1442
+ const spokeChainIds = [];
1443
+ const localChainId2 = EID_TO_CHAIN_ID[localEid];
1444
+ if (localChainId2 !== void 0) spokeChainIds.push(localChainId2);
1445
+ return { role: "spoke", hubChainId, spokeChainIds };
1446
+ }
1447
+ const localChainId = EID_TO_CHAIN_ID[localEid] ?? Number(publicClient.chain?.id ?? 0);
1448
+ return { role: "local", hubChainId: localChainId, spokeChainIds: [] };
1449
+ }
1450
+ async function getFullVaultTopology(hubChainClient, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1451
+ const topo = await getVaultTopology(hubChainClient, vault, factoryAddress);
1452
+ if (topo.role !== "hub") {
1453
+ throw new Error(
1454
+ `getFullVaultTopology: client must be connected to the hub chain (${topo.hubChainId}), but got role="${topo.role}". Connect to chainId ${topo.hubChainId} instead.`
1455
+ );
1456
+ }
1457
+ return topo;
1458
+ }
1459
+ var DISCOVERY_CHAIN_IDS = Object.values(CHAIN_IDS).filter(
1460
+ (id) => id !== 545
1461
+ // exclude testnet
1462
+ );
1463
+ async function discoverVaultTopology(vault, publicClient, factoryAddress = OMNI_FACTORY_ADDRESS) {
1464
+ const v = viem.getAddress(vault);
1465
+ let triedChainId;
1466
+ if (publicClient) {
1467
+ try {
1468
+ const topo = await getVaultTopology(publicClient, v, factoryAddress);
1469
+ if (topo.role !== "local") {
1470
+ if (topo.role === "spoke") {
1471
+ const hubClient = createChainClient(topo.hubChainId);
1472
+ if (hubClient) {
1473
+ try {
1474
+ return await getFullVaultTopology(hubClient, v, factoryAddress);
1475
+ } catch {
1476
+ }
1477
+ }
1478
+ }
1479
+ return topo;
1480
+ }
1481
+ triedChainId = publicClient.chain?.id;
1482
+ } catch {
1483
+ }
1484
+ }
1485
+ for (const chainId of DISCOVERY_CHAIN_IDS) {
1486
+ if (chainId === triedChainId) continue;
1487
+ const client = createChainClient(chainId);
1488
+ if (!client) continue;
1489
+ try {
1490
+ const topo = await getVaultTopology(client, v, factoryAddress);
1491
+ if (topo.role === "hub") return topo;
1492
+ if (topo.role === "spoke") {
1493
+ const hubClient = createChainClient(topo.hubChainId);
1494
+ if (hubClient) {
1495
+ try {
1496
+ return await getFullVaultTopology(hubClient, v, factoryAddress);
1497
+ } catch {
1498
+ return topo;
1499
+ }
1500
+ }
1501
+ return topo;
1502
+ }
1503
+ } catch {
1504
+ }
1505
+ }
1506
+ return { role: "local", hubChainId: 0, spokeChainIds: [] };
1507
+ }
1508
+ function isOnHubChain(currentChainId, topology) {
1509
+ return currentChainId === topology.hubChainId;
1510
+ }
1511
+ function getAllVaultChainIds(topology) {
1512
+ return [topology.hubChainId, ...topology.spokeChainIds];
1513
+ }
1514
+
1464
1515
  // src/viem/crossChainFlows.ts
1465
1516
  var LZ_ENDPOINT = "0x1a44076050125825900e736c501f859c50fe728c";
1466
1517
  var FACTORY_COMPOSER_ABI = [
@@ -3008,6 +3059,7 @@ exports.depositFromSpoke = depositFromSpoke;
3008
3059
  exports.depositFromSpokeAsync = depositFromSpoke;
3009
3060
  exports.depositMultiAsset = depositMultiAsset;
3010
3061
  exports.depositSimple = depositSimple;
3062
+ exports.discoverVaultTopology = discoverVaultTopology;
3011
3063
  exports.ensureAllowance = ensureAllowance;
3012
3064
  exports.executeCompose = executeCompose;
3013
3065
  exports.getAllVaultChainIds = getAllVaultChainIds;