@oydual31/more-vaults-sdk 0.2.2 → 0.2.4

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.
@@ -290,6 +290,40 @@ type VaultSummary = VaultStatus & VaultMetadata;
290
290
  * @returns Merged VaultStatus and VaultMetadata
291
291
  */
292
292
  declare function getVaultSummary(publicClient: PublicClient, vault: Address): Promise<VaultSummary>;
293
+ interface MultiChainUserPosition {
294
+ /** Shares held directly on the hub vault (vault.balanceOf) */
295
+ hubShares: bigint;
296
+ /** Per-spoke SHARE_OFT balances: { [chainId]: bigint } */
297
+ spokeShares: Record<number, bigint>;
298
+ /** hubShares + sum of all spokeShares */
299
+ totalShares: bigint;
300
+ /** convertToAssets(totalShares) on the hub */
301
+ estimatedAssets: bigint;
302
+ /** Share price: convertToAssets(10^decimals) */
303
+ sharePrice: bigint;
304
+ /** Vault decimals */
305
+ decimals: number;
306
+ /** Pending async withdrawal request on hub, or null */
307
+ pendingWithdrawal: {
308
+ shares: bigint;
309
+ timelockEndsAt: bigint;
310
+ canRedeemNow: boolean;
311
+ } | null;
312
+ }
313
+ /**
314
+ * Read the user's position across all chains of an omni vault.
315
+ *
316
+ * Discovers topology automatically, reads hub shares + pending withdrawal,
317
+ * then reads SHARE_OFT balances on each spoke chain in parallel.
318
+ *
319
+ * For local (single-chain) vaults, spokeShares will be empty and this
320
+ * behaves identically to getUserPosition.
321
+ *
322
+ * @param vault Vault address (same on all chains via CREATE3)
323
+ * @param user User wallet address
324
+ * @returns Aggregated position across all chains
325
+ */
326
+ declare function getUserPositionMultiChain(vault: Address, user: Address): Promise<MultiChainUserPosition>;
293
327
 
294
328
  declare const OMNI_FACTORY_ADDRESS: Address;
295
329
  interface VaultTopology {
@@ -539,4 +573,4 @@ declare function getOutboundRoutes(hubChainId: number, vault: Address): Promise<
539
573
  */
540
574
  declare function quoteRouteDepositFee(route: InboundRoute, hubChainId: number, amount: bigint, userAddress: Address): Promise<bigint>;
541
575
 
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 };
576
+ export { type AsyncRequestStatus as A, getVaultDistributionWithTopology as B, getVaultMetadata as C, type DepositBlockReason as D, getVaultStatus as E, getVaultSummary as F, getVaultTopology as G, isAsyncMode as H, type InboundRoute as I, isOnHubChain as J, previewDeposit as K, previewRedeem as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, quoteLzFee as P, quoteRouteDepositFee as Q, waitForTx as R, 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 MultiChainUserPosition as d, type OutboundRoute as e, type UserPosition as f, type VaultMetadata as g, type VaultMode as h, type VaultStatus as i, type VaultSummary as j, type VaultTopology as k, canDeposit as l, discoverVaultTopology as m, ensureAllowance as n, getAllVaultChainIds as o, getAsyncRequestStatus as p, getAsyncRequestStatusLabel as q, getFullVaultTopology as r, getInboundRoutes as s, getMaxWithdrawable as t, getOutboundRoutes as u, getUserBalances as v, getUserBalancesForRoutes as w, getUserPosition as x, getUserPositionMultiChain as y, getVaultDistribution as z };
@@ -290,6 +290,40 @@ type VaultSummary = VaultStatus & VaultMetadata;
290
290
  * @returns Merged VaultStatus and VaultMetadata
291
291
  */
292
292
  declare function getVaultSummary(publicClient: PublicClient, vault: Address): Promise<VaultSummary>;
293
+ interface MultiChainUserPosition {
294
+ /** Shares held directly on the hub vault (vault.balanceOf) */
295
+ hubShares: bigint;
296
+ /** Per-spoke SHARE_OFT balances: { [chainId]: bigint } */
297
+ spokeShares: Record<number, bigint>;
298
+ /** hubShares + sum of all spokeShares */
299
+ totalShares: bigint;
300
+ /** convertToAssets(totalShares) on the hub */
301
+ estimatedAssets: bigint;
302
+ /** Share price: convertToAssets(10^decimals) */
303
+ sharePrice: bigint;
304
+ /** Vault decimals */
305
+ decimals: number;
306
+ /** Pending async withdrawal request on hub, or null */
307
+ pendingWithdrawal: {
308
+ shares: bigint;
309
+ timelockEndsAt: bigint;
310
+ canRedeemNow: boolean;
311
+ } | null;
312
+ }
313
+ /**
314
+ * Read the user's position across all chains of an omni vault.
315
+ *
316
+ * Discovers topology automatically, reads hub shares + pending withdrawal,
317
+ * then reads SHARE_OFT balances on each spoke chain in parallel.
318
+ *
319
+ * For local (single-chain) vaults, spokeShares will be empty and this
320
+ * behaves identically to getUserPosition.
321
+ *
322
+ * @param vault Vault address (same on all chains via CREATE3)
323
+ * @param user User wallet address
324
+ * @returns Aggregated position across all chains
325
+ */
326
+ declare function getUserPositionMultiChain(vault: Address, user: Address): Promise<MultiChainUserPosition>;
293
327
 
294
328
  declare const OMNI_FACTORY_ADDRESS: Address;
295
329
  interface VaultTopology {
@@ -539,4 +573,4 @@ declare function getOutboundRoutes(hubChainId: number, vault: Address): Promise<
539
573
  */
540
574
  declare function quoteRouteDepositFee(route: InboundRoute, hubChainId: number, amount: bigint, userAddress: Address): Promise<bigint>;
541
575
 
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 };
576
+ export { type AsyncRequestStatus as A, getVaultDistributionWithTopology as B, getVaultMetadata as C, type DepositBlockReason as D, getVaultStatus as E, getVaultSummary as F, getVaultTopology as G, isAsyncMode as H, type InboundRoute as I, isOnHubChain as J, previewDeposit as K, previewRedeem as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, quoteLzFee as P, quoteRouteDepositFee as Q, waitForTx as R, 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 MultiChainUserPosition as d, type OutboundRoute as e, type UserPosition as f, type VaultMetadata as g, type VaultMode as h, type VaultStatus as i, type VaultSummary as j, type VaultTopology as k, canDeposit as l, discoverVaultTopology as m, ensureAllowance as n, getAllVaultChainIds as o, getAsyncRequestStatus as p, getAsyncRequestStatusLabel as q, getFullVaultTopology as r, getInboundRoutes as s, getMaxWithdrawable as t, getOutboundRoutes as u, getUserBalances as v, getUserBalancesForRoutes as w, getUserPosition as x, getUserPositionMultiChain as y, getVaultDistribution as z };
@@ -2956,6 +2956,115 @@ async function getVaultSummary(publicClient, vault) {
2956
2956
  ]);
2957
2957
  return { ...status, ...metadata };
2958
2958
  }
2959
+ var FACTORY_COMPOSER_ABI3 = [
2960
+ {
2961
+ type: "function",
2962
+ name: "vaultComposer",
2963
+ inputs: [{ name: "_vault", type: "address" }],
2964
+ outputs: [{ name: "", type: "address" }],
2965
+ stateMutability: "view"
2966
+ }
2967
+ ];
2968
+ var COMPOSER_SHARE_OFT_ABI = [
2969
+ {
2970
+ type: "function",
2971
+ name: "SHARE_OFT",
2972
+ inputs: [],
2973
+ outputs: [{ name: "", type: "address" }],
2974
+ stateMutability: "view"
2975
+ }
2976
+ ];
2977
+ async function getUserPositionMultiChain(vault, user) {
2978
+ const v = viem.getAddress(vault);
2979
+ const u = viem.getAddress(user);
2980
+ const topo = await discoverVaultTopology(vault);
2981
+ const hubClient = createChainClient(topo.hubChainId);
2982
+ if (!hubClient) throw new Error(`No public RPC for hub chainId ${topo.hubChainId}`);
2983
+ const [hubShares, decimals, withdrawalRequest] = await hubClient.multicall({
2984
+ contracts: [
2985
+ { address: v, abi: VAULT_ABI, functionName: "balanceOf", args: [u] },
2986
+ { address: v, abi: METADATA_ABI, functionName: "decimals" },
2987
+ { address: v, abi: VAULT_ABI, functionName: "getWithdrawalRequest", args: [u] }
2988
+ ],
2989
+ allowFailure: false
2990
+ });
2991
+ const [withdrawShares, timelockEndsAt] = withdrawalRequest;
2992
+ const spokeShares = {};
2993
+ if (topo.spokeChainIds.length > 0) {
2994
+ let hubShareOft = null;
2995
+ try {
2996
+ const composerAddress = await hubClient.readContract({
2997
+ address: OMNI_FACTORY_ADDRESS,
2998
+ abi: FACTORY_COMPOSER_ABI3,
2999
+ functionName: "vaultComposer",
3000
+ args: [v]
3001
+ });
3002
+ if (composerAddress !== "0x0000000000000000000000000000000000000000") {
3003
+ hubShareOft = await hubClient.readContract({
3004
+ address: composerAddress,
3005
+ abi: COMPOSER_SHARE_OFT_ABI,
3006
+ functionName: "SHARE_OFT"
3007
+ });
3008
+ }
3009
+ } catch {
3010
+ }
3011
+ if (hubShareOft) {
3012
+ const spokePromises = topo.spokeChainIds.map(async (spokeChainId) => {
3013
+ try {
3014
+ const spokeEid = CHAIN_ID_TO_EID[spokeChainId];
3015
+ if (!spokeEid) return { chainId: spokeChainId, balance: 0n };
3016
+ const spokeOftBytes32 = await hubClient.readContract({
3017
+ address: hubShareOft,
3018
+ abi: OFT_ABI,
3019
+ functionName: "peers",
3020
+ args: [spokeEid]
3021
+ });
3022
+ const spokeOft = viem.getAddress(`0x${spokeOftBytes32.slice(-40)}`);
3023
+ if (spokeOft === "0x0000000000000000000000000000000000000000") {
3024
+ return { chainId: spokeChainId, balance: 0n };
3025
+ }
3026
+ const spokeClient = createChainClient(spokeChainId);
3027
+ if (!spokeClient) return { chainId: spokeChainId, balance: 0n };
3028
+ const balance = await spokeClient.readContract({
3029
+ address: spokeOft,
3030
+ abi: ERC20_ABI,
3031
+ functionName: "balanceOf",
3032
+ args: [u]
3033
+ });
3034
+ return { chainId: spokeChainId, balance };
3035
+ } catch {
3036
+ return { chainId: spokeChainId, balance: 0n };
3037
+ }
3038
+ });
3039
+ const results = await Promise.all(spokePromises);
3040
+ for (const { chainId, balance } of results) {
3041
+ spokeShares[chainId] = balance;
3042
+ }
3043
+ }
3044
+ }
3045
+ const totalSpokeShares = Object.values(spokeShares).reduce((sum, b) => sum + b, 0n);
3046
+ const totalShares = hubShares + totalSpokeShares;
3047
+ const oneShare = 10n ** BigInt(decimals);
3048
+ const [estimatedAssets, sharePrice] = await Promise.all([
3049
+ totalShares === 0n ? Promise.resolve(0n) : hubClient.readContract({ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [totalShares] }),
3050
+ hubClient.readContract({ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [oneShare] })
3051
+ ]);
3052
+ const block = await hubClient.getBlock();
3053
+ const pendingWithdrawal = withdrawShares === 0n ? null : {
3054
+ shares: withdrawShares,
3055
+ timelockEndsAt,
3056
+ canRedeemNow: timelockEndsAt === 0n || block.timestamp >= timelockEndsAt
3057
+ };
3058
+ return {
3059
+ hubShares,
3060
+ spokeShares,
3061
+ totalShares,
3062
+ estimatedAssets,
3063
+ sharePrice,
3064
+ decimals,
3065
+ pendingWithdrawal
3066
+ };
3067
+ }
2959
3068
 
2960
3069
  // src/viem/distribution.ts
2961
3070
  async function getVaultDistribution(hubClient, vault, spokeClients) {
@@ -3072,6 +3181,7 @@ exports.getOutboundRoutes = getOutboundRoutes;
3072
3181
  exports.getUserBalances = getUserBalances;
3073
3182
  exports.getUserBalancesForRoutes = getUserBalancesForRoutes;
3074
3183
  exports.getUserPosition = getUserPosition;
3184
+ exports.getUserPositionMultiChain = getUserPositionMultiChain;
3075
3185
  exports.getVaultDistribution = getVaultDistribution;
3076
3186
  exports.getVaultDistributionWithTopology = getVaultDistributionWithTopology;
3077
3187
  exports.getVaultMetadata = getVaultMetadata;