@augustdigital/sdk 8.3.1 → 8.5.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.
Files changed (204) hide show
  1. package/lib/abis/ERC20_Bytes32.d.ts +4 -0
  2. package/lib/abis/ERC20_Bytes32.js +4 -0
  3. package/lib/abis/ERC4626.d.ts +1 -0
  4. package/lib/abis/ERC4626.js +1 -0
  5. package/lib/abis/ERC721.d.ts +1 -0
  6. package/lib/abis/ERC721.js +1 -0
  7. package/lib/abis/FeeOracle.js +1 -0
  8. package/lib/abis/LendingPool.js +1 -0
  9. package/lib/abis/LendingPoolV2.js +1 -0
  10. package/lib/abis/Multicall3.js +3 -0
  11. package/lib/abis/OFT.d.ts +20 -0
  12. package/lib/abis/OFT.js +20 -0
  13. package/lib/abis/SmartAccount.d.ts +1 -0
  14. package/lib/abis/SmartAccount.js +3 -0
  15. package/lib/abis/SwapRouter.d.ts +1 -0
  16. package/lib/abis/SwapRouter.js +1 -0
  17. package/lib/abis/UniversalSignatureValidator.js +3 -0
  18. package/lib/abis/index.d.ts +5 -0
  19. package/lib/abis/index.js +5 -0
  20. package/lib/adapters/evm/getters.d.ts +17 -2
  21. package/lib/adapters/evm/getters.js +35 -3
  22. package/lib/adapters/evm/index.d.ts +262 -0
  23. package/lib/adapters/evm/index.js +268 -1
  24. package/lib/adapters/evm/utils.d.ts +6 -0
  25. package/lib/adapters/evm/utils.js +7 -0
  26. package/lib/adapters/solana/constants.js +4 -1
  27. package/lib/adapters/solana/getters.d.ts +8 -0
  28. package/lib/adapters/solana/getters.js +21 -0
  29. package/lib/adapters/solana/idl/vault-idl.js +9 -0
  30. package/lib/adapters/solana/index.d.ts +55 -0
  31. package/lib/adapters/solana/index.js +57 -0
  32. package/lib/adapters/solana/utils.d.ts +28 -0
  33. package/lib/adapters/solana/utils.js +79 -4
  34. package/lib/adapters/solana/vault.actions.d.ts +19 -0
  35. package/lib/adapters/solana/vault.actions.js +47 -3
  36. package/lib/adapters/stellar/actions.d.ts +25 -0
  37. package/lib/adapters/stellar/actions.js +33 -0
  38. package/lib/adapters/stellar/constants.d.ts +26 -0
  39. package/lib/adapters/stellar/constants.js +29 -0
  40. package/lib/adapters/stellar/getters.d.ts +56 -0
  41. package/lib/adapters/stellar/getters.js +81 -0
  42. package/lib/adapters/stellar/index.d.ts +48 -0
  43. package/lib/adapters/stellar/index.js +48 -0
  44. package/lib/adapters/stellar/soroban.d.ts +20 -0
  45. package/lib/adapters/stellar/soroban.js +46 -0
  46. package/lib/adapters/stellar/submit.d.ts +12 -0
  47. package/lib/adapters/stellar/submit.js +19 -0
  48. package/lib/adapters/stellar/types.d.ts +27 -0
  49. package/lib/adapters/stellar/types.js +3 -0
  50. package/lib/adapters/stellar/utils.d.ts +10 -0
  51. package/lib/adapters/stellar/utils.js +10 -0
  52. package/lib/adapters/sui/getters.d.ts +6 -0
  53. package/lib/adapters/sui/getters.js +6 -0
  54. package/lib/adapters/sui/index.d.ts +15 -0
  55. package/lib/adapters/sui/index.js +15 -0
  56. package/lib/adapters/sui/transformer.d.ts +6 -0
  57. package/lib/adapters/sui/transformer.js +7 -0
  58. package/lib/adapters/sui/utils.d.ts +6 -0
  59. package/lib/adapters/sui/utils.js +6 -0
  60. package/lib/core/analytics/chain-name.d.ts +8 -0
  61. package/lib/core/analytics/chain-name.js +8 -0
  62. package/lib/core/analytics/constants.d.ts +4 -0
  63. package/lib/core/analytics/constants.js +4 -0
  64. package/lib/core/analytics/env.d.ts +25 -0
  65. package/lib/core/analytics/env.js +26 -0
  66. package/lib/core/analytics/index.d.ts +26 -0
  67. package/lib/core/analytics/index.js +35 -0
  68. package/lib/core/analytics/instrumentation.d.ts +26 -0
  69. package/lib/core/analytics/instrumentation.js +66 -2
  70. package/lib/core/analytics/method-taxonomy.d.ts +16 -0
  71. package/lib/core/analytics/method-taxonomy.js +18 -0
  72. package/lib/core/analytics/metrics.d.ts +23 -0
  73. package/lib/core/analytics/metrics.js +40 -0
  74. package/lib/core/analytics/sanitize.d.ts +38 -0
  75. package/lib/core/analytics/sanitize.js +46 -0
  76. package/lib/core/analytics/sentry-runtime.d.ts +11 -0
  77. package/lib/core/analytics/sentry-runtime.js +19 -0
  78. package/lib/core/analytics/sentry.d.ts +45 -0
  79. package/lib/core/analytics/sentry.js +115 -2
  80. package/lib/core/analytics/types.d.ts +27 -0
  81. package/lib/core/analytics/user-identity.d.ts +34 -0
  82. package/lib/core/analytics/user-identity.js +42 -0
  83. package/lib/core/analytics/version.d.ts +6 -1
  84. package/lib/core/analytics/version.js +6 -1
  85. package/lib/core/auth/verify.js +5 -0
  86. package/lib/core/base.class.d.ts +75 -0
  87. package/lib/core/base.class.js +56 -0
  88. package/lib/core/cache.d.ts +5 -0
  89. package/lib/core/cache.js +6 -0
  90. package/lib/core/constants/adapters.d.ts +15 -0
  91. package/lib/core/constants/adapters.js +28 -8
  92. package/lib/core/constants/core.d.ts +12 -1
  93. package/lib/core/constants/core.js +12 -0
  94. package/lib/core/constants/swap-router.d.ts +46 -0
  95. package/lib/core/constants/swap-router.js +50 -0
  96. package/lib/core/constants/vaults.d.ts +56 -0
  97. package/lib/core/constants/vaults.js +66 -1
  98. package/lib/core/constants/web3.d.ts +3 -0
  99. package/lib/core/constants/web3.js +18 -5
  100. package/lib/core/errors/index.d.ts +36 -0
  101. package/lib/core/errors/index.js +29 -0
  102. package/lib/core/fetcher.d.ts +134 -0
  103. package/lib/core/fetcher.js +191 -5
  104. package/lib/core/helpers/adapters.d.ts +9 -0
  105. package/lib/core/helpers/adapters.js +11 -0
  106. package/lib/core/helpers/chain-address.d.ts +10 -0
  107. package/lib/core/helpers/chain-address.js +11 -0
  108. package/lib/core/helpers/core.d.ts +42 -0
  109. package/lib/core/helpers/core.js +66 -1
  110. package/lib/core/helpers/explorer-link.d.ts +14 -0
  111. package/lib/core/helpers/explorer-link.js +14 -0
  112. package/lib/core/helpers/signer.d.ts +26 -0
  113. package/lib/core/helpers/signer.js +39 -0
  114. package/lib/core/helpers/swap-router.d.ts +32 -0
  115. package/lib/core/helpers/swap-router.js +32 -0
  116. package/lib/core/helpers/vault-version.d.ts +1 -0
  117. package/lib/core/helpers/vault-version.js +2 -0
  118. package/lib/core/helpers/vaults.d.ts +8 -0
  119. package/lib/core/helpers/vaults.js +22 -8
  120. package/lib/core/helpers/web3.d.ts +152 -0
  121. package/lib/core/helpers/web3.js +183 -6
  122. package/lib/core/logger/index.d.ts +55 -0
  123. package/lib/core/logger/index.js +19 -0
  124. package/lib/core/logger/slack.d.ts +3 -0
  125. package/lib/core/logger/slack.js +3 -0
  126. package/lib/core/vault-metadata.d.ts +6 -0
  127. package/lib/core/vault-metadata.js +6 -0
  128. package/lib/core/version-check.d.ts +52 -0
  129. package/lib/core/version-check.js +81 -0
  130. package/lib/evm/methods/crossChainVault.d.ts +90 -0
  131. package/lib/evm/methods/crossChainVault.js +186 -1
  132. package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
  133. package/lib/evm/methods/crossChainVaultRegistry.js +240 -0
  134. package/lib/evm/methods/index.d.ts +1 -0
  135. package/lib/evm/methods/index.js +1 -0
  136. package/lib/evm/types/crossChain.d.ts +202 -0
  137. package/lib/evm/types/crossChain.js +11 -0
  138. package/lib/index.d.ts +16 -0
  139. package/lib/index.js +19 -0
  140. package/lib/main.d.ts +288 -5
  141. package/lib/main.js +305 -0
  142. package/lib/modules/api/index.d.ts +1 -0
  143. package/lib/modules/api/index.js +6 -0
  144. package/lib/modules/api/main.d.ts +52 -0
  145. package/lib/modules/api/main.js +130 -0
  146. package/lib/modules/sub-accounts/fetcher.d.ts +15 -0
  147. package/lib/modules/sub-accounts/fetcher.js +15 -0
  148. package/lib/modules/sub-accounts/main.d.ts +33 -0
  149. package/lib/modules/sub-accounts/main.js +38 -0
  150. package/lib/modules/sub-accounts/utils.d.ts +3 -0
  151. package/lib/modules/sub-accounts/utils.js +3 -0
  152. package/lib/modules/vaults/adapter.helpers.d.ts +18 -0
  153. package/lib/modules/vaults/adapter.helpers.js +34 -0
  154. package/lib/modules/vaults/fetcher.d.ts +20 -0
  155. package/lib/modules/vaults/fetcher.js +40 -3
  156. package/lib/modules/vaults/getters.d.ts +295 -0
  157. package/lib/modules/vaults/getters.js +552 -12
  158. package/lib/modules/vaults/index.d.ts +12 -0
  159. package/lib/modules/vaults/index.js +12 -0
  160. package/lib/modules/vaults/main.d.ts +292 -4
  161. package/lib/modules/vaults/main.js +379 -7
  162. package/lib/modules/vaults/read.actions.d.ts +168 -0
  163. package/lib/modules/vaults/read.actions.js +143 -0
  164. package/lib/modules/vaults/types.d.ts +34 -0
  165. package/lib/modules/vaults/utils/call-data-decoder.d.ts +47 -0
  166. package/lib/modules/vaults/utils/call-data-decoder.js +56 -0
  167. package/lib/modules/vaults/utils/date-utils.d.ts +39 -0
  168. package/lib/modules/vaults/utils/date-utils.js +47 -1
  169. package/lib/modules/vaults/utils.d.ts +70 -0
  170. package/lib/modules/vaults/utils.js +108 -5
  171. package/lib/modules/vaults/write.actions.d.ts +363 -3
  172. package/lib/modules/vaults/write.actions.js +364 -2
  173. package/lib/polyfills.js +2 -0
  174. package/lib/sdk.d.ts +23705 -0
  175. package/lib/services/coingecko/fetcher.d.ts +13 -0
  176. package/lib/services/coingecko/fetcher.js +17 -0
  177. package/lib/services/debank/fetcher.d.ts +14 -0
  178. package/lib/services/debank/fetcher.js +12 -0
  179. package/lib/services/debank/utils.js +17 -0
  180. package/lib/services/layerzero/deposits.d.ts +11 -0
  181. package/lib/services/layerzero/deposits.js +34 -11
  182. package/lib/services/layerzero/redeems.d.ts +10 -0
  183. package/lib/services/layerzero/redeems.js +13 -0
  184. package/lib/services/layerzero/utils.d.ts +8 -0
  185. package/lib/services/layerzero/utils.js +11 -0
  186. package/lib/services/octavfi/fetcher.d.ts +7 -0
  187. package/lib/services/octavfi/fetcher.js +25 -0
  188. package/lib/services/octavfi/utils.d.ts +12 -0
  189. package/lib/services/octavfi/utils.js +44 -10
  190. package/lib/services/subgraph/fetcher.js +4 -2
  191. package/lib/services/subgraph/vaults.d.ts +12 -0
  192. package/lib/services/subgraph/vaults.js +43 -2
  193. package/lib/services/swap-quotes/index.d.ts +71 -0
  194. package/lib/services/swap-quotes/index.js +25 -0
  195. package/lib/services/swap-quotes/paraswap.d.ts +17 -0
  196. package/lib/services/swap-quotes/paraswap.js +14 -0
  197. package/lib/types/pools.d.ts +3 -0
  198. package/lib/types/typed-contract.d.ts +64 -0
  199. package/lib/types/vaults.d.ts +139 -2
  200. package/lib/types/vaults.js +10 -0
  201. package/lib/types/web3.d.ts +8 -0
  202. package/lib/types/web3.js +1 -0
  203. package/lib/types/webserver.d.ts +45 -0
  204. package/package.json +6 -5
@@ -1,4 +1,13 @@
1
1
  "use strict";
2
+ /**
3
+ * Cross-Chain Vault Methods
4
+ *
5
+ * Implements LayerZero OVault cross-chain deposit and redemption operations.
6
+ * These functions are generic — callers provide their own ICrossChainVaultConfig
7
+ * rather than relying on hardcoded vault addresses.
8
+ *
9
+ * @module evm/methods/crossChainVault
10
+ */
2
11
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
12
  if (k2 === undefined) k2 = k;
4
13
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -52,16 +61,46 @@ exports.getLayerZeroScanUrl = getLayerZeroScanUrl;
52
61
  const core_1 = require("../../core");
53
62
  const crossChain_1 = require("../types/crossChain");
54
63
  const OFT_1 = require("../../abis/OFT");
64
+ // ---------------------------------------------------------------------------
65
+ // Constants
66
+ // ---------------------------------------------------------------------------
67
+ /**
68
+ * lzReceive option hex for 500,000 gas.
69
+ * The Agora OFT has no enforced options for SEND_AND_CALL, so we must provide
70
+ * lzReceive gas explicitly or the executor reverts with Executor_ZeroLzReceiveGasProvided.
71
+ */
55
72
  const LZ_RECEIVE_OPTION_HEX = '010011010000000000000000000000000007a120';
73
+ /** Default fee buffer percentage applied to LayerZero native fees */
56
74
  const DEFAULT_FEE_BUFFER_PERCENT = 50;
75
+ /** Default slippage in basis points (1%) */
57
76
  const DEFAULT_SLIPPAGE_BPS = 100;
77
+ /** Default gas buffer for deposits (1.5x) */
58
78
  const DEFAULT_DEPOSIT_GAS_BUFFER_PERCENT = 150;
79
+ /** Default gas buffer for redeems (2x) */
59
80
  const DEFAULT_REDEEM_GAS_BUFFER_PERCENT = 200;
81
+ /** Default minimum gas limit for redeem operations */
60
82
  const DEFAULT_MIN_REDEEM_GAS = 5000000n;
83
+ /** Default hub lzCompose gas limit */
61
84
  const DEFAULT_HUB_LZ_COMPOSE_GAS_LIMIT = 2000000n;
85
+ // ---------------------------------------------------------------------------
86
+ // Mutex for SDK monkey-patches
87
+ //
88
+ // Multi-asset and hub-redeem flows mutate the shared `OVaultSyncMessageBuilder`
89
+ // — module-level bindings inside the SDK mean a shallow clone is unsafe, so we
90
+ // serialize patched calls. The timeout THROWS rather than silently racing
91
+ // concurrent callers' patches.
92
+ // ---------------------------------------------------------------------------
62
93
  const PATCH_LOCK_TIMEOUT_MS = 30000;
63
94
  let patchLock = Promise.resolve();
95
+ // ---------------------------------------------------------------------------
96
+ // Internal helpers
97
+ // ---------------------------------------------------------------------------
98
+ /**
99
+ * Try available previewRedeem signatures, falling back to 1:1 if the vault
100
+ * does not expose a working preview function.
101
+ */
64
102
  async function redeemPreview(publicClient, vaultAddress, shares) {
103
+ // 1. previewRedemption(uint256, bool) — multi-asset vault
65
104
  try {
66
105
  const result = await publicClient.readContract({
67
106
  address: vaultAddress,
@@ -73,7 +112,9 @@ async function redeemPreview(publicClient, vaultAddress, shares) {
73
112
  return assetsAfterFee;
74
113
  }
75
114
  catch {
115
+ /* try next */
76
116
  }
117
+ // 2. Standard ERC4626: previewRedeem(uint256)
77
118
  try {
78
119
  return (await publicClient.readContract({
79
120
  address: vaultAddress,
@@ -83,18 +124,30 @@ async function redeemPreview(publicClient, vaultAddress, shares) {
83
124
  }));
84
125
  }
85
126
  catch {
127
+ /* try next */
86
128
  }
129
+ // 3. Fallback: 1:1 ratio. Slippage protects against discrepancy.
87
130
  return shares;
88
131
  }
132
+ /**
133
+ * Wraps generateOVaultInputs with monkey-patches for:
134
+ * 1. REDEEM from hub — skip quoteOFT (reverts for same-chain)
135
+ * 2. Multi-asset DEPOSIT — previewDeposit(address, uint256)
136
+ * 3. Multi-asset REDEEM — try previewRedeem variants, fallback to 1:1
137
+ * 4. Multi-asset composed messages — add lzReceive gas to SEND_AND_CALL
138
+ */
89
139
  async function generateOVaultInputsWithOverride(input, config, hubPublicClient, ovaultSdk) {
90
140
  const OVaultSyncMessageBuilder = ovaultSdk.OVaultSyncMessageBuilder;
91
141
  const OVaultSyncOperations = ovaultSdk.OVaultSyncOperations;
92
142
  const isRedeemFromHub = input.operation === OVaultSyncOperations.REDEEM &&
93
143
  input.srcEid === input.hubEid;
94
144
  const isMultiAsset = !!config.multiAsset;
145
+ // Fast path — no patches needed
95
146
  if (!isMultiAsset && !isRedeemFromHub) {
96
147
  return OVaultSyncMessageBuilder.generateOVaultInputs(input);
97
148
  }
149
+ // Serialize: wait for the prior holder or REJECT on timeout (silent races
150
+ // produced wrong cross-chain quotes).
98
151
  const prev = patchLock;
99
152
  let unlock;
100
153
  patchLock = new Promise((r) => {
@@ -124,11 +177,15 @@ async function generateOVaultInputsWithOverride(input, config, hubPublicClient,
124
177
  const origBuildApproval = Builder.buildApproval;
125
178
  try {
126
179
  if (isRedeemFromHub) {
180
+ // Patch 1a: skip quoteOFT (reverts for same-chain calls).
127
181
  Builder.getOutputAmount = async () => input.amount;
182
+ // Patch 1b: skip SDK's allowance check — multi-asset vault contracts
183
+ // may not implement ERC20. Caller handles approval directly.
128
184
  Builder.buildApproval = async () => undefined;
129
185
  }
130
186
  if (isMultiAsset) {
131
187
  const { hubAssetAddress } = config.multiAsset;
188
+ // Patch 2/3: Multi-asset quoteOVaultOutput
132
189
  Builder.quoteOVaultOutput = async (quoteInput) => {
133
190
  const getOutputAmount = Builder.getOutputAmount;
134
191
  const sourceAmount = await getOutputAmount({
@@ -158,6 +215,7 @@ async function generateOVaultInputsWithOverride(input, config, hubPublicClient,
158
215
  minDstAmount: outputAmount - slippageAmount,
159
216
  };
160
217
  };
218
+ // Patch 4: Ensure lzReceive gas in extraOptions for composed messages
161
219
  Builder.buildSendParams = async (spInput) => {
162
220
  const origFn = origBuildSendParams;
163
221
  const result = await origFn.call(Builder, spInput);
@@ -184,9 +242,23 @@ async function generateOVaultInputsWithOverride(input, config, hubPublicClient,
184
242
  unlock();
185
243
  }
186
244
  }
245
+ // ---------------------------------------------------------------------------
246
+ // Public API: Build
247
+ // ---------------------------------------------------------------------------
248
+ /**
249
+ * Build LayerZero OVault transaction inputs for cross-chain deposits and
250
+ * redemptions. Does NOT execute the transaction.
251
+ *
252
+ * Overridable defaults on `props`: `slippageBps` = 100 (range 1–10000),
253
+ * `feeBufferPercent` = 50% (added to LZ `nativeFee`),
254
+ * `hubLzComposeGasLimit` = 2_000_000n (multi-asset composed messages).
255
+ *
256
+ * @returns Transaction inputs or `{ success: false, error }`.
257
+ */
187
258
  async function buildCrossChainVaultTx(props) {
188
259
  try {
189
260
  const { config } = props;
261
+ // Validate slippage at the public boundary (BPS, not decimal)
190
262
  const slippageBps = props.slippageBps ?? DEFAULT_SLIPPAGE_BPS;
191
263
  if (slippageBps < 1 || slippageBps > 10000) {
192
264
  return {
@@ -194,6 +266,7 @@ async function buildCrossChainVaultTx(props) {
194
266
  error: `Slippage must be between 1 and 10000 basis points (got ${slippageBps})`,
195
267
  };
196
268
  }
269
+ // Validate chains
197
270
  const hubChain = props.hubChain;
198
271
  const sourceChain = props.sourceChain;
199
272
  if (!hubChain || !sourceChain) {
@@ -202,6 +275,8 @@ async function buildCrossChainVaultTx(props) {
202
275
  error: 'Hub chain and source chain are required',
203
276
  };
204
277
  }
278
+ // Reject unknown chain IDs up front so a typo can't fall through to
279
+ // `|| hub` and route shares to a chain the user didn't pick.
205
280
  const supportedChains = [
206
281
  config.hubChainId,
207
282
  ...Object.keys(config.layerZeroEids.spokes).map((k) => Number(k)),
@@ -230,6 +305,7 @@ async function buildCrossChainVaultTx(props) {
230
305
  return config.layerZeroEids.hub;
231
306
  return config.layerZeroEids.spokes[chainId];
232
307
  };
308
+ // Determine source and destination EIDs based on operation
233
309
  let srcEid;
234
310
  let dstEid;
235
311
  let tokenAddress;
@@ -266,7 +342,9 @@ async function buildCrossChainVaultTx(props) {
266
342
  error: `Invalid operation: ${props.operation}`,
267
343
  };
268
344
  }
345
+ // Normalize amount
269
346
  const normalizedAmount = (0, core_1.toNormalizedBn)(props.amount, props.decimals);
347
+ // Build LayerZero OVault inputs
270
348
  const input = {
271
349
  srcEid,
272
350
  hubEid: config.layerZeroEids.hub,
@@ -286,10 +364,12 @@ async function buildCrossChainVaultTx(props) {
286
364
  oftAddress,
287
365
  hubLzComposeGasLimit: props.hubLzComposeGasLimit ?? DEFAULT_HUB_LZ_COMPOSE_GAS_LIMIT,
288
366
  };
367
+ // Create a minimal public client for hub chain reads (multi-asset patches)
289
368
  const hubRpc = hubChain?.rpcUrls;
290
369
  const hubRpcUrl = hubRpc?.default?.http?.[0];
291
370
  let hubPublicClient;
292
371
  try {
372
+ // Dynamic import to keep viem optional at the module level
293
373
  const viem = await Promise.resolve().then(() => __importStar(require('viem')));
294
374
  hubPublicClient = viem.createPublicClient({
295
375
  chain: hubChain,
@@ -297,19 +377,25 @@ async function buildCrossChainVaultTx(props) {
297
377
  });
298
378
  }
299
379
  catch {
380
+ // If viem is not available, provide a stub that will fail on multi-asset only
300
381
  hubPublicClient = {
301
382
  readContract: async () => {
302
383
  throw new Error('viem is required for multi-asset vault operations. Install viem as a peer dependency.');
303
384
  },
304
385
  };
305
386
  }
387
+ // Generate OVault transaction inputs (with monkey-patches for multi-asset)
306
388
  const inputs = await generateOVaultInputsWithOverride(input, config, hubPublicClient, props.ovaultSdk);
389
+ // Apply fee buffer to LZ fees (post-hoc to avoid SDK double-compounding)
307
390
  const feeBufferPercent = props.feeBufferPercent ?? DEFAULT_FEE_BUFFER_PERCENT;
308
391
  const rawNativeFee = inputs.messageFee.nativeFee;
309
392
  const rawMessageValue = inputs.messageValue;
310
393
  const feeBuffer = (rawNativeFee * BigInt(feeBufferPercent)) / 100n;
311
394
  inputs.messageFee.nativeFee = rawNativeFee + feeBuffer;
312
395
  inputs.messageValue = rawMessageValue + feeBuffer;
396
+ // Patch fee into txArgs in place for OFT.send(); warn if the LayerZero
397
+ // SDK ever returns a different entry-point name (silent no-op would
398
+ // underpay the LZ fee).
313
399
  if (inputs.contractFunctionName === 'send') {
314
400
  const sendFee = inputs.txArgs[1];
315
401
  sendFee.nativeFee = inputs.messageFee.nativeFee;
@@ -348,6 +434,14 @@ async function buildCrossChainVaultTx(props) {
348
434
  };
349
435
  }
350
436
  }
437
+ // ---------------------------------------------------------------------------
438
+ // Public API: Quote
439
+ // ---------------------------------------------------------------------------
440
+ /**
441
+ * Estimate fees and expected shares for a cross-chain deposit. The returned
442
+ * quote carries `quotedAt`/`expiresAt`; re-quote via {@link isQuoteStale}
443
+ * before submitting.
444
+ */
351
445
  async function quoteCrossChainDeposit(props) {
352
446
  const result = await buildCrossChainVaultTx({
353
447
  ovaultSdk: props.ovaultSdk,
@@ -374,6 +468,11 @@ async function quoteCrossChainDeposit(props) {
374
468
  expiresAt: quotedAt + crossChain_1.CROSS_CHAIN_QUOTE_TTL_MS,
375
469
  };
376
470
  }
471
+ /**
472
+ * Estimate fees and expected assets for a cross-chain redeem. The returned
473
+ * quote carries `quotedAt`/`expiresAt`; re-quote via {@link isQuoteStale}
474
+ * before submitting.
475
+ */
377
476
  async function quoteCrossChainRedeem(props) {
378
477
  const result = await buildCrossChainVaultTx({
379
478
  ovaultSdk: props.ovaultSdk,
@@ -400,6 +499,14 @@ async function quoteCrossChainRedeem(props) {
400
499
  expiresAt: quotedAt + crossChain_1.CROSS_CHAIN_QUOTE_TTL_MS,
401
500
  };
402
501
  }
502
+ // ---------------------------------------------------------------------------
503
+ // Public API: Approval
504
+ // ---------------------------------------------------------------------------
505
+ /**
506
+ * Returns `true` when the wallet's ERC-20 allowance is insufficient for the
507
+ * cross-chain operation. On RPC failure also returns `true` (defensive
508
+ * default — better a redundant approval than a downstream revert).
509
+ */
403
510
  async function needsCrossChainApproval(tokenAddress, spenderAddress, walletAddress, amount, publicClient) {
404
511
  try {
405
512
  const allowance = (await publicClient.readContract({
@@ -411,9 +518,15 @@ async function needsCrossChainApproval(tokenAddress, spenderAddress, walletAddre
411
518
  return allowance < amount;
412
519
  }
413
520
  catch {
521
+ // If we can't check allowance, assume approval is needed
414
522
  return true;
415
523
  }
416
524
  }
525
+ /**
526
+ * Execute a token approval for a cross-chain operation.
527
+ *
528
+ * @returns Transaction hash of the approval
529
+ */
417
530
  async function approveCrossChain(tokenAddress, spenderAddress, amount, walletClient, publicClient) {
418
531
  if (!walletClient.account) {
419
532
  throw new Error('Wallet not ready — please reconnect your wallet');
@@ -433,6 +546,18 @@ async function approveCrossChain(tokenAddress, spenderAddress, amount, walletCli
433
546
  }
434
547
  return hash;
435
548
  }
549
+ // ---------------------------------------------------------------------------
550
+ // Public API: Execute
551
+ // ---------------------------------------------------------------------------
552
+ /**
553
+ * Execute a cross-chain deposit via LayerZero OVault. Validates the source
554
+ * chain, ensures approval, estimates gas with a buffer, and waits for the
555
+ * on-chain receipt. Defaults: `slippageBps` 100, `feeBufferPercent` 50,
556
+ * `gasBufferPercent` 150 — all overridable on the request.
557
+ *
558
+ * @throws Error on unsupported chain, approval revert, gas-estimation
559
+ * failure, or on-chain revert.
560
+ */
436
561
  async function crossChainVaultDeposit(props) {
437
562
  if (props.userChainId !== props.config.hubChainId &&
438
563
  !props.config.spokeChainIds.includes(props.userChainId)) {
@@ -440,6 +565,7 @@ async function crossChainVaultDeposit(props) {
440
565
  }
441
566
  const walletClient = props.walletClient;
442
567
  const publicClient = props.publicClient;
568
+ // 1. Build transaction inputs
443
569
  const result = await buildCrossChainVaultTx({
444
570
  ovaultSdk: props.ovaultSdk,
445
571
  config: props.config,
@@ -458,6 +584,7 @@ async function crossChainVaultDeposit(props) {
458
584
  throw new Error(result.error || 'Failed to build transaction');
459
585
  }
460
586
  const txInputs = result.data;
587
+ // 2. Check and execute approval if needed
461
588
  if (!props.skipApprovalCheck) {
462
589
  const tokenAddr = txInputs.approval?.tokenAddress ??
463
590
  props.config.contracts.assetToken[props.userChainId];
@@ -469,6 +596,7 @@ async function crossChainVaultDeposit(props) {
469
596
  await approveCrossChain(tokenAddr, spenderAddr, approvalAmount, walletClient, publicClient);
470
597
  }
471
598
  }
599
+ // 3. Estimate gas with buffer
472
600
  if (!walletClient.account) {
473
601
  throw new Error('Wallet not ready — please reconnect your wallet');
474
602
  }
@@ -488,6 +616,7 @@ async function crossChainVaultDeposit(props) {
488
616
  catch (estimateErr) {
489
617
  throw new Error(`Gas estimation failed for cross-chain deposit. Ensure you have sufficient native tokens for the LayerZero fee (${txInputs.messageFee.nativeFee.toString()} wei). Original error: ${estimateErr instanceof Error ? estimateErr.message : String(estimateErr)}`);
490
618
  }
619
+ // 4. Execute the transaction
491
620
  const hash = await walletClient.writeContract({
492
621
  account: walletClient.account,
493
622
  address: txInputs.contractAddress,
@@ -497,6 +626,7 @@ async function crossChainVaultDeposit(props) {
497
626
  value: txInputs.messageValue,
498
627
  gas: gasLimit,
499
628
  });
629
+ // 5. Wait for confirmation
500
630
  const receipt = await publicClient.waitForTransactionReceipt({
501
631
  hash: hash,
502
632
  });
@@ -508,13 +638,21 @@ async function crossChainVaultDeposit(props) {
508
638
  success: true,
509
639
  };
510
640
  }
641
+ /**
642
+ * Execute a cross-chain redemption via LayerZero OVault. User must be on the
643
+ * hub chain. Defaults: `slippageBps` 100, `feeBufferPercent` 50,
644
+ * `gasBufferPercent` 200 (compose calls under-estimate on mainnet),
645
+ * `minGasLimit` 5_000_000n — all overridable on the request.
646
+ */
511
647
  async function crossChainVaultRedeem(props) {
648
+ // 1. Validate: redemptions must be from hub chain
512
649
  if (props.userChainId !== props.config.hubChainId) {
513
650
  throw new Error(`Redemptions must be executed from hub chain (${props.config.hubChainId}). ` +
514
651
  `Please switch to the hub chain first.`);
515
652
  }
516
653
  const walletClient = props.walletClient;
517
654
  const publicClient = props.publicClient;
655
+ // 2. Build transaction inputs
518
656
  const result = await buildCrossChainVaultTx({
519
657
  ovaultSdk: props.ovaultSdk,
520
658
  config: props.config,
@@ -533,12 +671,14 @@ async function crossChainVaultRedeem(props) {
533
671
  throw new Error(result.error || 'Failed to build transaction');
534
672
  }
535
673
  const txInputs = result.data;
674
+ // 3. Check and execute approval if needed
536
675
  if (!props.skipApprovalCheck && txInputs.approval) {
537
676
  const approvalNeeded = await needsCrossChainApproval(txInputs.approval.tokenAddress, txInputs.approval.spender, props.walletAddress, txInputs.approval.amount, publicClient);
538
677
  if (approvalNeeded) {
539
678
  await approveCrossChain(txInputs.approval.tokenAddress, txInputs.approval.spender, txInputs.approval.amount, walletClient, publicClient);
540
679
  }
541
680
  }
681
+ // 4. Estimate gas with buffer
542
682
  if (!walletClient.account) {
543
683
  throw new Error('Wallet account not available');
544
684
  }
@@ -560,6 +700,7 @@ async function crossChainVaultRedeem(props) {
560
700
  catch (estimateErr) {
561
701
  throw new Error(`Gas estimation failed for cross-chain redeem. Ensure you have sufficient native tokens for the LayerZero fee (${txInputs.messageFee.nativeFee.toString()} wei). Original error: ${estimateErr instanceof Error ? estimateErr.message : String(estimateErr)}`);
562
702
  }
703
+ // 5. Execute the transaction
563
704
  const hash = await walletClient.writeContract({
564
705
  account: walletClient.account,
565
706
  address: txInputs.contractAddress,
@@ -569,6 +710,7 @@ async function crossChainVaultRedeem(props) {
569
710
  value: txInputs.messageValue,
570
711
  gas: gasLimit,
571
712
  });
713
+ // 6. Wait for confirmation
572
714
  const receipt = await publicClient.waitForTransactionReceipt({
573
715
  hash: hash,
574
716
  });
@@ -580,9 +722,18 @@ async function crossChainVaultRedeem(props) {
580
722
  success: true,
581
723
  };
582
724
  }
725
+ // ---------------------------------------------------------------------------
726
+ // Public API: Error Classification
727
+ // ---------------------------------------------------------------------------
728
+ /**
729
+ * Check if an error indicates a missing LayerZero peer configuration.
730
+ */
583
731
  function isNoPeerError(errStr) {
584
732
  return errStr.includes('0xf6ff4fb7') || errStr.includes('NoPeer');
585
733
  }
734
+ /**
735
+ * Classify a cross-chain contract error into a known error type.
736
+ */
586
737
  function classifyCrossChainError(error) {
587
738
  const err = error;
588
739
  const msg = err?.message ?? String(error);
@@ -609,13 +760,30 @@ function classifyCrossChainError(error) {
609
760
  return 'network';
610
761
  return 'unknown';
611
762
  }
763
+ // ---------------------------------------------------------------------------
764
+ // Public API: Utility helpers
765
+ // ---------------------------------------------------------------------------
766
+ /**
767
+ * Check if a user can deposit from their current chain.
768
+ */
612
769
  function canDepositFromChain(config, userChainId) {
613
770
  return (userChainId === config.hubChainId ||
614
771
  config.spokeChainIds.includes(userChainId));
615
772
  }
773
+ /**
774
+ * Check if a user can redeem from their current chain (must be hub).
775
+ */
616
776
  function canRedeemFromChain(config, userChainId) {
617
777
  return userChainId === config.hubChainId;
618
778
  }
779
+ /**
780
+ * Check if an operation is cross-chain (needs LayerZero).
781
+ *
782
+ * An operation is cross-chain when:
783
+ * - The user's chain differs from the hub chain, OR
784
+ * - The destination chain differs from the hub chain
785
+ * (e.g. deposit from hub but receive shares on a spoke)
786
+ */
619
787
  function isCrossChainOperation(config, userChainId, destinationChainId) {
620
788
  if (userChainId !== config.hubChainId)
621
789
  return true;
@@ -624,10 +792,20 @@ function isCrossChainOperation(config, userChainId, destinationChainId) {
624
792
  return true;
625
793
  return false;
626
794
  }
795
+ /**
796
+ * Get all chain IDs that a vault supports (hub + all spokes).
797
+ */
627
798
  function getAvailableChains(config) {
628
799
  return [config.hubChainId, ...config.spokeChainIds];
629
800
  }
801
+ /**
802
+ * Format a cross-chain error into a user-friendly message.
803
+ *
804
+ * Mirrors the `classifyCrossChainDepositError` from upshift-app but is
805
+ * generic enough for any SDK consumer.
806
+ */
630
807
  function formatCrossChainError(errMsg) {
808
+ // If the error already contains specific gas fee info, show it directly
631
809
  if (errMsg.includes('Cross-chain fee is') ||
632
810
  errMsg.includes('Gas estimation failed'))
633
811
  return errMsg;
@@ -642,17 +820,24 @@ function formatCrossChainError(errMsg) {
642
820
  if (lower.includes('user rejected'))
643
821
  return 'Transaction cancelled by user.';
644
822
  if (lower.includes('hub chain'))
645
- return errMsg;
823
+ return errMsg; // Already descriptive
646
824
  if (errMsg.includes('reverted'))
647
825
  return 'Transaction reverted on-chain. This may be due to insufficient gas or a contract error.';
648
826
  return 'Cross-chain transaction failed. Please try again.';
649
827
  }
828
+ /**
829
+ * Get the LayerZero Scan URL for tracking a cross-chain message.
830
+ */
650
831
  function getLayerZeroScanUrl(txHash, testnet = false) {
651
832
  const baseUrl = testnet
652
833
  ? 'https://testnet.layerzeroscan.com'
653
834
  : 'https://layerzeroscan.com';
654
835
  return `${baseUrl}/tx/${txHash}`;
655
836
  }
837
+ /**
838
+ * Well-known LayerZero Endpoint IDs for common chains.
839
+ * SDK consumers can use these when building their ICrossChainVaultConfig.
840
+ */
656
841
  exports.LAYERZERO_ENDPOINT_IDS = {
657
842
  ETHEREUM: 30101,
658
843
  ARBITRUM: 30110,
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Cross-Chain Vault Registry
3
+ *
4
+ * Address-keyed registry of August's LayerZero OVault deployments plus the
5
+ * resolver helpers that turn a vault address into the
6
+ * {@link ICrossChainVaultConfig} consumed by `buildCrossChainVaultTx`,
7
+ * `crossChainVaultDeposit`, and `quoteCrossChainDeposit`.
8
+ *
9
+ * This is the cross-chain analogue of the SwapRouter registry
10
+ * (`VAULTS_USING_SWAP_ROUTER` / `getSwapRouterAddress`): consumers resolve a
11
+ * full config by vault address instead of hand-assembling the per-chain
12
+ * contract maps and LayerZero EIDs. Without it, every consuming app would
13
+ * re-encode the same address book.
14
+ *
15
+ * Addresses are ported verbatim from upshift-app `src/config/ovault.ts` and
16
+ * cross-checked against the read-side `LAYERZERO_VAULTS` registry in
17
+ * `services/layerzero/deposits.ts`. Verify against the deployed contracts
18
+ * before adding or editing an entry — a wrong address silently routes funds
19
+ * to the wrong chain.
20
+ *
21
+ * Return convention (deliberate, mirrors the SwapRouter helpers): lookups that
22
+ * resolve a single optional value (`getCrossChainVaultConfig`,
23
+ * `getOVaultChains`) return `undefined` for an unregistered vault, while
24
+ * list-returning helpers (`getWithdrawDestinationChains`) return `[]` so
25
+ * callers can iterate without a null-check.
26
+ *
27
+ * @module evm/methods/crossChainVaultRegistry
28
+ */
29
+ import type { IAddress } from '../../types';
30
+ import type { ICrossChainVaultConfig } from '../types/crossChain';
31
+ /**
32
+ * August's LayerZero OVault deployments, keyed by lowercase hub-chain vault
33
+ * address. Resolve entries with {@link getCrossChainVaultConfig} rather than
34
+ * indexing directly — the helper handles address-casing for you.
35
+ *
36
+ * @see {@link getCrossChainVaultConfig} for the typed, case-insensitive lookup.
37
+ */
38
+ export declare const CROSS_CHAIN_VAULT_CONFIGS: Readonly<Record<string, ICrossChainVaultConfig>>;
39
+ /**
40
+ * Resolve the full cross-chain config for a vault. Address comparison is
41
+ * case-insensitive.
42
+ *
43
+ * @param vault - Hub-chain vault contract address.
44
+ * @returns The {@link ICrossChainVaultConfig} to pass to
45
+ * `crossChainVaultDeposit` / `quoteCrossChainDeposit`, or `undefined` when
46
+ * the vault is not a registered OVault deployment.
47
+ * @example
48
+ * ```ts
49
+ * const config = getCrossChainVaultConfig('0xE9B725010A9E419412ed67d0fA5f3A5f40159D32');
50
+ * if (config) await quoteCrossChainDeposit({ config, ...rest });
51
+ * ```
52
+ */
53
+ export declare function getCrossChainVaultConfig(vault: IAddress): ICrossChainVaultConfig | undefined;
54
+ /**
55
+ * Whether a vault is a registered LayerZero OVault and should route deposits
56
+ * through the cross-chain flow. Address comparison is case-insensitive.
57
+ *
58
+ * @param vault - Vault contract address.
59
+ * @returns `true` when the vault has an entry in
60
+ * {@link CROSS_CHAIN_VAULT_CONFIGS}.
61
+ */
62
+ export declare function isCrossChainVault(vault: IAddress): boolean;
63
+ /**
64
+ * Get the hub and spoke chain IDs a vault is deployed across — the set of
65
+ * chains a user can deposit from.
66
+ *
67
+ * @param vault - Vault contract address.
68
+ * @returns `{ hub, spokes }` chain IDs, or `undefined` when the vault is not a
69
+ * registered OVault deployment.
70
+ */
71
+ export declare function getOVaultChains(vault: IAddress): {
72
+ hub: number;
73
+ spokes: number[];
74
+ } | undefined;
75
+ /**
76
+ * Whether a vault's receipt token is hub-only (no cross-chain withdraw).
77
+ * The deposit UI must not offer a spoke share destination for these vaults.
78
+ *
79
+ * @param vault - Vault contract address.
80
+ * @returns `true` for vaults whose shares cannot leave the hub chain
81
+ * (AUGUST-6300).
82
+ */
83
+ export declare function isHubOnlyReceipt(vault: IAddress): boolean;
84
+ /**
85
+ * Chains a user can receive the underlying asset on when withdrawing.
86
+ * Hub-only-receipt vaults redeem to the hub chain only (AUGUST-6300); all
87
+ * other OVault vaults can redeem to the hub or any spoke.
88
+ *
89
+ * @param vault - Vault contract address.
90
+ * @returns Destination chain IDs, or an empty array when the vault is not a
91
+ * registered OVault deployment.
92
+ */
93
+ export declare function getWithdrawDestinationChains(vault: IAddress): number[];