@gauntlet-xyz/sdk 3.0.1 → 3.1.1

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 (117) hide show
  1. package/README.md +34 -3
  2. package/dist/api/activity.d.ts +3 -1
  3. package/dist/api/activity.d.ts.map +1 -1
  4. package/dist/api/activityRows.d.ts +11 -0
  5. package/dist/api/activityRows.d.ts.map +1 -0
  6. package/dist/api/caip.d.ts.map +1 -1
  7. package/dist/api/client.d.ts.map +1 -1
  8. package/dist/api/decimal.d.ts.map +1 -1
  9. package/dist/api/http.d.ts.map +1 -1
  10. package/dist/api/index.js +7 -8
  11. package/dist/api/positionHistory.d.ts.map +1 -1
  12. package/dist/attribution/index.d.ts +5 -2
  13. package/dist/attribution/index.d.ts.map +1 -1
  14. package/dist/{chunk-HC2BS7MK.js → chunk-JJOLVL5V.js} +113 -6
  15. package/dist/chunk-JJOLVL5V.js.map +7 -0
  16. package/dist/{chunk-S2TTA45N.js → chunk-JRSNLXFY.js} +2 -2
  17. package/dist/{chunk-SU6JAKIA.js → chunk-MEKISE2T.js} +131 -47
  18. package/dist/chunk-MEKISE2T.js.map +7 -0
  19. package/dist/{chunk-7TA2OJUK.js → chunk-YQXTLIJA.js} +209 -96
  20. package/dist/chunk-YQXTLIJA.js.map +7 -0
  21. package/dist/cjs/api/activity.d.ts +3 -1
  22. package/dist/cjs/api/activity.d.ts.map +1 -1
  23. package/dist/cjs/api/activity.js +14 -12
  24. package/dist/cjs/api/activity.js.map +2 -2
  25. package/dist/cjs/api/activityRows.d.ts +11 -0
  26. package/dist/cjs/api/activityRows.d.ts.map +1 -0
  27. package/dist/cjs/api/activityRows.js +139 -0
  28. package/dist/cjs/api/activityRows.js.map +7 -0
  29. package/dist/cjs/api/caip.d.ts.map +1 -1
  30. package/dist/cjs/api/caip.js +3 -1
  31. package/dist/cjs/api/caip.js.map +2 -2
  32. package/dist/cjs/api/client.d.ts.map +1 -1
  33. package/dist/cjs/api/client.js +29 -1
  34. package/dist/cjs/api/client.js.map +2 -2
  35. package/dist/cjs/api/decimal.d.ts.map +1 -1
  36. package/dist/cjs/api/decimal.js +1 -0
  37. package/dist/cjs/api/decimal.js.map +2 -2
  38. package/dist/cjs/api/http.d.ts.map +1 -1
  39. package/dist/cjs/api/http.js +1 -0
  40. package/dist/cjs/api/http.js.map +2 -2
  41. package/dist/cjs/api/positionHistory.d.ts.map +1 -1
  42. package/dist/cjs/api/positionHistory.js +17 -4
  43. package/dist/cjs/api/positionHistory.js.map +2 -2
  44. package/dist/cjs/attribution/index.d.ts +5 -2
  45. package/dist/cjs/attribution/index.d.ts.map +1 -1
  46. package/dist/cjs/attribution/index.js +3 -1
  47. package/dist/cjs/attribution/index.js.map +2 -2
  48. package/dist/cjs/evm/adapters/aera.d.ts.map +1 -1
  49. package/dist/cjs/evm/adapters/aera.js +16 -7
  50. package/dist/cjs/evm/adapters/aera.js.map +2 -2
  51. package/dist/cjs/evm/adapters/types.d.ts +1 -0
  52. package/dist/cjs/evm/adapters/types.d.ts.map +1 -1
  53. package/dist/cjs/evm/adapters/types.js.map +1 -1
  54. package/dist/cjs/evm/aeraContracts.d.ts.map +1 -1
  55. package/dist/cjs/evm/aeraContracts.js +21 -11
  56. package/dist/cjs/evm/aeraContracts.js.map +2 -2
  57. package/dist/cjs/evm/deposit.d.ts +3 -2
  58. package/dist/cjs/evm/deposit.d.ts.map +1 -1
  59. package/dist/cjs/evm/deposit.js +40 -10
  60. package/dist/cjs/evm/deposit.js.map +2 -2
  61. package/dist/cjs/evm/depositQuote.d.ts.map +1 -1
  62. package/dist/cjs/evm/depositQuote.js +1 -0
  63. package/dist/cjs/evm/depositQuote.js.map +2 -2
  64. package/dist/cjs/evm/depositReceiverApproval.d.ts.map +1 -1
  65. package/dist/cjs/evm/depositReceiverApproval.js +14 -9
  66. package/dist/cjs/evm/depositReceiverApproval.js.map +2 -2
  67. package/dist/cjs/evm/userCurrentBalance.d.ts +15 -1
  68. package/dist/cjs/evm/userCurrentBalance.d.ts.map +1 -1
  69. package/dist/cjs/evm/userCurrentBalance.js +94 -51
  70. package/dist/cjs/evm/userCurrentBalance.js.map +2 -2
  71. package/dist/cjs/evm/withdraw.d.ts +2 -0
  72. package/dist/cjs/evm/withdraw.d.ts.map +1 -1
  73. package/dist/cjs/evm/withdraw.js +14 -1
  74. package/dist/cjs/evm/withdraw.js.map +2 -2
  75. package/dist/cjs/evm/withdrawQuote.d.ts.map +1 -1
  76. package/dist/cjs/evm/withdrawQuote.js +1 -0
  77. package/dist/cjs/evm/withdrawQuote.js.map +2 -2
  78. package/dist/evm/adapters/aera.d.ts.map +1 -1
  79. package/dist/evm/adapters/types.d.ts +1 -0
  80. package/dist/evm/adapters/types.d.ts.map +1 -1
  81. package/dist/evm/aeraContracts.d.ts.map +1 -1
  82. package/dist/evm/deposit.d.ts +3 -2
  83. package/dist/evm/deposit.d.ts.map +1 -1
  84. package/dist/evm/depositQuote.d.ts.map +1 -1
  85. package/dist/evm/depositReceiverApproval.d.ts.map +1 -1
  86. package/dist/evm/index.js +6 -8
  87. package/dist/evm/userCurrentBalance.d.ts +15 -1
  88. package/dist/evm/userCurrentBalance.d.ts.map +1 -1
  89. package/dist/evm/withdraw.d.ts +2 -0
  90. package/dist/evm/withdraw.d.ts.map +1 -1
  91. package/dist/evm/withdrawQuote.d.ts.map +1 -1
  92. package/dist/index.js +11 -13
  93. package/dist/privy/index.js +2 -2
  94. package/package.json +1 -1
  95. package/src/api/activity.ts +18 -15
  96. package/src/api/activityRows.ts +143 -0
  97. package/src/api/caip.ts +3 -1
  98. package/src/api/client.ts +36 -1
  99. package/src/api/decimal.ts +1 -0
  100. package/src/api/http.ts +1 -0
  101. package/src/api/positionHistory.ts +20 -5
  102. package/src/attribution/index.ts +6 -2
  103. package/src/evm/adapters/aera.ts +26 -8
  104. package/src/evm/adapters/types.ts +1 -0
  105. package/src/evm/aeraContracts.ts +29 -14
  106. package/src/evm/deposit.ts +43 -12
  107. package/src/evm/depositQuote.ts +1 -0
  108. package/src/evm/depositReceiverApproval.ts +14 -9
  109. package/src/evm/userCurrentBalance.ts +144 -60
  110. package/src/evm/withdraw.ts +20 -1
  111. package/src/evm/withdrawQuote.ts +1 -0
  112. package/dist/chunk-7TA2OJUK.js.map +0 -7
  113. package/dist/chunk-HC2BS7MK.js.map +0 -7
  114. package/dist/chunk-STIV2CC4.js +0 -57
  115. package/dist/chunk-STIV2CC4.js.map +0 -7
  116. package/dist/chunk-SU6JAKIA.js.map +0 -7
  117. /package/dist/{chunk-S2TTA45N.js.map → chunk-JRSNLXFY.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"deposit.d.ts","sourceRoot":"","sources":["../../../src/evm/deposit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAGhD,OAAO,EAAoC,UAAU,EAAE,gCAAuB;AAsB9E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,UAAU,EAAE,CAAC,CAuGvB"}
1
+ {"version":3,"file":"deposit.d.ts","sourceRoot":"","sources":["../../../src/evm/deposit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAGhD,OAAO,EAAoC,UAAU,EAAE,gCAAuB;AAsB9E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,UAAU,EAAE,CAAC,CAqIvB"}
@@ -29,6 +29,7 @@ var import_vaults = require("./vaults");
29
29
  var import_constants = require("../constants");
30
30
  var import_operationMode = require("./operationMode");
31
31
  async function getDepositTx(client, params) {
32
+ params = structuredClone(params);
32
33
  const slippageBps = params.slippageBps ?? import_constants.DEFAULT_BPS;
33
34
  if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > Number(import_constants.MAX_BPS)) {
34
35
  throw new import_errors.InvalidSlippageBPSError(slippageBps);
@@ -70,7 +71,7 @@ async function getDepositTx(client, params) {
70
71
  modifiedDepositMode = (0, import_operationMode.resolveSyncOnlyOperationMode)(params.vaultId, requestedDepositMode);
71
72
  }
72
73
  const spender = protocol === "aera" && modifiedDepositMode === "async" ? aeraRuntime.provisioner.address : vault.vaultAddress;
73
- const { sufficient } = await adapter.checkAllowance({
74
+ const { sufficient, current } = await adapter.checkAllowance({
74
75
  publicClient,
75
76
  token: token.address,
76
77
  owner: account,
@@ -79,14 +80,43 @@ async function getDepositTx(client, params) {
79
80
  });
80
81
  const steps = [];
81
82
  if (!sufficient) {
82
- steps.push(
83
- adapter.buildApproval({
84
- token: token.address,
85
- spender,
86
- amount: params.amount,
87
- account
88
- })
89
- );
83
+ const approval = adapter.buildApproval({
84
+ token: token.address,
85
+ spender,
86
+ amount: params.amount,
87
+ account
88
+ });
89
+ if (current > 0n && params.amount > 0n) {
90
+ try {
91
+ await publicClient.estimateContractGas({
92
+ address: approval.address,
93
+ abi: approval.abi,
94
+ functionName: "approve",
95
+ args: approval.args,
96
+ account
97
+ });
98
+ } catch (approvalError) {
99
+ const reset = adapter.buildApproval({
100
+ token: token.address,
101
+ spender,
102
+ amount: 0n,
103
+ account
104
+ });
105
+ try {
106
+ await publicClient.estimateContractGas({
107
+ address: reset.address,
108
+ abi: reset.abi,
109
+ functionName: "approve",
110
+ args: reset.args,
111
+ account
112
+ });
113
+ } catch {
114
+ throw approvalError;
115
+ }
116
+ steps.push(reset);
117
+ }
118
+ }
119
+ steps.push(approval);
90
120
  }
91
121
  const depositSteps = await adapter.buildDeposit({
92
122
  vault,
@@ -103,7 +133,7 @@ async function getDepositTx(client, params) {
103
133
  minUnitsOut: params.minUnitsOut
104
134
  });
105
135
  steps.push(...depositSteps);
106
- return Promise.all(steps.map((step) => (0, import_attribution.encodeTransactionWithAttribution)(client, step)));
136
+ return Promise.all(steps.map((step) => (0, import_attribution.encodeTransactionWithAttribution)(client, step, chainId)));
107
137
  }
108
138
  // Annotate the CommonJS export names for ESM import in node:
109
139
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/evm/deposit.ts"],
4
- "sourcesContent": ["import type { Address } from 'viem';\nimport type { GauntletClient } from '../client';\nimport type { EvmTxStep } from './adapters/types';\nimport { getAdapter } from './adapters';\nimport { encodeTransactionWithAttribution, PreparedTx } from '../attribution';\nimport {\n AccountRequiredError,\n VaultNotFoundError,\n UnsupportedAssetError,\n InvalidSlippageBPSError,\n InvalidSyncDepositBoundError,\n} from '../errors';\nimport {\n resolveAeraRuntimeContracts,\n resolveAeraTokenModeSupport,\n type AeraRuntimeContracts,\n} from './aeraContracts';\nimport { resolveVault } from './vaults';\nimport { DEFAULT_BPS, MAX_BPS } from '../constants';\nimport {\n parseOperationMode,\n resolveOperationMode,\n resolveSyncOnlyOperationMode,\n type OperationMode,\n} from './operationMode';\n\nexport interface EvmDepositParams {\n vaultId: string;\n amount: bigint;\n // Required for multichain vaults, will default to base\n chainId?: number;\n // Required for multiasset vaults, not utilized yet\n assetSymbol?: string;\n /** Request async (queued) or sync deposit. Availability is read from live vault configuration. */\n depositMode?: string;\n // So a developer is able to specify a separate receiver than the tx sender\n receiver?: Address;\n /** Slippage tolerance in basis points (e.g. 100 = 1%). Defaults to 100. */\n slippageBps?: number;\n /** Solver tip passed to async Aera provisioner requests. Defaults to 0. */\n solverTip?: bigint;\n /** Maximum price age passed to async Aera provisioner requests. Defaults to 10 days. */\n maxPriceAge?: bigint;\n /** Caller-reviewed minimum output for an explicit Aera synchronous deposit. */\n minUnitsOut?: bigint;\n}\n\n/**\n * Builds the ordered list of EVM transactions required to deposit into a Gauntlet vault.\n *\n * Returns one or two transactions: an ERC-20 approval (only if the current allowance is\n * insufficient) followed by the deposit or async deposit request. Each transaction is\n * returned as a `PreparedTx` object ready to be signed and sent.\n *\n * @param client - A configured `GauntletClient` instance with an EVM public client and wallet.\n * @param params - Deposit parameters including the vault identifier, token amount, and optional\n * chain, asset symbol, deposit mode (`'sync'` | `'async'`), and receiver address.\n * @returns Ordered array of prepared transactions to execute in sequence.\n *\n * @throws {VaultNotFoundError} If the vault ID is not found in the manifest.\n * @throws {AccountRequiredError} If no wallet account is set on the client.\n * @throws {UnsupportedDepositModeError} If the requested deposit mode is not supported by the vault.\n * @throws {UnsupportedAssetError} If the specified asset symbol is not accepted by the vault.\n *\n * @example\n * ```ts\n * const txs = await getDepositTx(client, {\n * vaultId: 'baseUsdcPrime',\n * amount: 100_000_000n, // 100 USDC (6 decimals)\n * });\n * for (const tx of txs) {\n * await walletClient.sendTransaction(tx.tx);\n * }\n * ```\n */\nexport async function getDepositTx(\n client: GauntletClient,\n params: EvmDepositParams\n): Promise<PreparedTx[]> {\n const slippageBps = params.slippageBps ?? DEFAULT_BPS;\n if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > Number(MAX_BPS)) {\n throw new InvalidSlippageBPSError(slippageBps);\n }\n if (\n params.minUnitsOut !== undefined &&\n (typeof params.minUnitsOut !== 'bigint' || params.minUnitsOut <= 0n)\n ) {\n throw new InvalidSyncDepositBoundError();\n }\n\n const resolved = await resolveVault(client, params.vaultId, params.chainId);\n if (!resolved) throw new VaultNotFoundError(params.vaultId);\n\n const chainId = params.chainId ?? resolved.vault.chainId;\n\n const account = client.wallet?.account?.address;\n if (!account) throw new AccountRequiredError();\n\n const { vault, protocol } = resolved;\n\n const adapter = getAdapter(protocol);\n const publicClient = client.getPublicClient(chainId);\n const token =\n vault.supplyToken.length > 1\n ? vault.supplyToken.find((tInfo) => tInfo.symbol === params.assetSymbol)\n : vault.supplyToken[0];\n\n if (token === undefined) {\n throw new UnsupportedAssetError(params.assetSymbol ?? 'unknown', params.vaultId);\n }\n\n const requestedDepositMode = parseOperationMode(params.vaultId, params.depositMode);\n if (\n params.minUnitsOut !== undefined &&\n (protocol !== 'aera' || requestedDepositMode !== 'sync')\n ) {\n throw new InvalidSyncDepositBoundError();\n }\n let modifiedDepositMode: OperationMode;\n let aeraRuntime: AeraRuntimeContracts | undefined;\n\n if (protocol === 'aera') {\n aeraRuntime = await resolveAeraRuntimeContracts(publicClient, vault);\n const tokenModeSupport = await resolveAeraTokenModeSupport(\n publicClient,\n aeraRuntime,\n token.address,\n { includeSyncModes: requestedDepositMode !== 'async' }\n );\n modifiedDepositMode = resolveOperationMode(params.vaultId, requestedDepositMode, {\n async: tokenModeSupport.asyncDeposit,\n sync: tokenModeSupport.syncDeposit,\n });\n } else {\n modifiedDepositMode = resolveSyncOnlyOperationMode(params.vaultId, requestedDepositMode);\n }\n\n const spender =\n protocol === 'aera' && modifiedDepositMode === 'async'\n ? aeraRuntime!.provisioner.address\n : vault.vaultAddress;\n\n // NOTE: this could be moved to the buildDeposit level\n const { sufficient } = await adapter.checkAllowance({\n publicClient,\n token: token.address,\n owner: account,\n spender,\n amount: params.amount,\n });\n\n const steps: EvmTxStep[] = [];\n\n if (!sufficient) {\n steps.push(\n adapter.buildApproval({\n token: token.address,\n spender,\n amount: params.amount,\n account,\n })\n );\n }\n\n const depositSteps = await adapter.buildDeposit({\n vault,\n amount: params.amount,\n receiver: params.receiver ?? account,\n account,\n async: modifiedDepositMode === 'async',\n asset: token,\n publicClient,\n slippageBps,\n solverTip: params.solverTip,\n maxPriceAge: params.maxPriceAge,\n aeraRuntime,\n minUnitsOut: params.minUnitsOut,\n });\n steps.push(...depositSteps);\n\n return Promise.all(steps.map((step) => encodeTransactionWithAttribution(client, step)));\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Address } from 'viem';\nimport type { GauntletClient } from '../client';\nimport type { EvmTxStep } from './adapters/types';\nimport { getAdapter } from './adapters';\nimport { encodeTransactionWithAttribution, PreparedTx } from '../attribution';\nimport {\n AccountRequiredError,\n VaultNotFoundError,\n UnsupportedAssetError,\n InvalidSlippageBPSError,\n InvalidSyncDepositBoundError,\n} from '../errors';\nimport {\n resolveAeraRuntimeContracts,\n resolveAeraTokenModeSupport,\n type AeraRuntimeContracts,\n} from './aeraContracts';\nimport { resolveVault } from './vaults';\nimport { DEFAULT_BPS, MAX_BPS } from '../constants';\nimport {\n parseOperationMode,\n resolveOperationMode,\n resolveSyncOnlyOperationMode,\n type OperationMode,\n} from './operationMode';\n\nexport interface EvmDepositParams {\n vaultId: string;\n amount: bigint;\n // Required for multichain vaults, will default to base\n chainId?: number;\n // Required for multiasset vaults, not utilized yet\n assetSymbol?: string;\n /** Request async (queued) or sync deposit. Availability is read from live vault configuration. */\n depositMode?: string;\n // So a developer is able to specify a separate receiver than the tx sender\n receiver?: Address;\n /** Slippage tolerance in basis points (e.g. 100 = 1%). Defaults to 100. */\n slippageBps?: number;\n /** Solver tip passed to async Aera provisioner requests. Defaults to 0. */\n solverTip?: bigint;\n /** Maximum price age passed to async Aera provisioner requests. Defaults to 10 days. */\n maxPriceAge?: bigint;\n /** Caller-reviewed minimum output for an explicit Aera synchronous deposit. */\n minUnitsOut?: bigint;\n}\n\n/**\n * Builds the ordered list of EVM transactions required to deposit into a Gauntlet vault.\n *\n * Returns ordered transactions: ERC-20 approvals (if the allowance is insufficient),\n * followed by the deposit or async deposit request. Some tokens require an approval\n * of zero before a new nonzero approval. Each transaction is\n * returned as a `PreparedTx` object ready to be signed and sent.\n *\n * @param client - A configured `GauntletClient` instance with an EVM public client and wallet.\n * @param params - Deposit parameters including the vault identifier, token amount, and optional\n * chain, asset symbol, deposit mode (`'sync'` | `'async'`), and receiver address.\n * @returns Ordered array of prepared transactions to execute in sequence.\n *\n * @throws {VaultNotFoundError} If the vault ID is not found in the manifest.\n * @throws {AccountRequiredError} If no wallet account is set on the client.\n * @throws {UnsupportedDepositModeError} If the requested deposit mode is not supported by the vault.\n * @throws {UnsupportedAssetError} If the specified asset symbol is not accepted by the vault.\n *\n * @example\n * ```ts\n * const txs = await getDepositTx(client, {\n * vaultId: 'baseUsdcPrime',\n * amount: 100_000_000n, // 100 USDC (6 decimals)\n * });\n * for (const tx of txs) {\n * await walletClient.sendTransaction(tx.tx);\n * }\n * ```\n */\nexport async function getDepositTx(\n client: GauntletClient,\n params: EvmDepositParams\n): Promise<PreparedTx[]> {\n params = structuredClone(params);\n const slippageBps = params.slippageBps ?? DEFAULT_BPS;\n if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > Number(MAX_BPS)) {\n throw new InvalidSlippageBPSError(slippageBps);\n }\n if (\n params.minUnitsOut !== undefined &&\n (typeof params.minUnitsOut !== 'bigint' || params.minUnitsOut <= 0n)\n ) {\n throw new InvalidSyncDepositBoundError();\n }\n\n const resolved = await resolveVault(client, params.vaultId, params.chainId);\n if (!resolved) throw new VaultNotFoundError(params.vaultId);\n\n const chainId = params.chainId ?? resolved.vault.chainId;\n\n const account = client.wallet?.account?.address;\n if (!account) throw new AccountRequiredError();\n\n const { vault, protocol } = resolved;\n\n const adapter = getAdapter(protocol);\n const publicClient = client.getPublicClient(chainId);\n const token =\n vault.supplyToken.length > 1\n ? vault.supplyToken.find((tInfo) => tInfo.symbol === params.assetSymbol)\n : vault.supplyToken[0];\n\n if (token === undefined) {\n throw new UnsupportedAssetError(params.assetSymbol ?? 'unknown', params.vaultId);\n }\n\n const requestedDepositMode = parseOperationMode(params.vaultId, params.depositMode);\n if (\n params.minUnitsOut !== undefined &&\n (protocol !== 'aera' || requestedDepositMode !== 'sync')\n ) {\n throw new InvalidSyncDepositBoundError();\n }\n let modifiedDepositMode: OperationMode;\n let aeraRuntime: AeraRuntimeContracts | undefined;\n\n if (protocol === 'aera') {\n aeraRuntime = await resolveAeraRuntimeContracts(publicClient, vault);\n const tokenModeSupport = await resolveAeraTokenModeSupport(\n publicClient,\n aeraRuntime,\n token.address,\n { includeSyncModes: requestedDepositMode !== 'async' }\n );\n modifiedDepositMode = resolveOperationMode(params.vaultId, requestedDepositMode, {\n async: tokenModeSupport.asyncDeposit,\n sync: tokenModeSupport.syncDeposit,\n });\n } else {\n modifiedDepositMode = resolveSyncOnlyOperationMode(params.vaultId, requestedDepositMode);\n }\n\n const spender =\n protocol === 'aera' && modifiedDepositMode === 'async'\n ? aeraRuntime!.provisioner.address\n : vault.vaultAddress;\n\n // NOTE: this could be moved to the buildDeposit level\n const { sufficient, current } = await adapter.checkAllowance({\n publicClient,\n token: token.address,\n owner: account,\n spender,\n amount: params.amount,\n });\n\n const steps: EvmTxStep[] = [];\n\n if (!sufficient) {\n const approval = adapter.buildApproval({\n token: token.address,\n spender,\n amount: params.amount,\n account,\n });\n if (current > 0n && params.amount > 0n) {\n try {\n await publicClient.estimateContractGas({\n address: approval.address,\n abi: approval.abi,\n functionName: 'approve',\n args: approval.args,\n account,\n });\n } catch (approvalError) {\n const reset = adapter.buildApproval({\n token: token.address,\n spender,\n amount: 0n,\n account,\n });\n try {\n await publicClient.estimateContractGas({\n address: reset.address,\n abi: reset.abi,\n functionName: 'approve',\n args: reset.args,\n account,\n });\n } catch {\n throw approvalError;\n }\n steps.push(reset);\n }\n }\n steps.push(approval);\n }\n\n const depositSteps = await adapter.buildDeposit({\n vault,\n amount: params.amount,\n receiver: params.receiver ?? account,\n account,\n async: modifiedDepositMode === 'async',\n asset: token,\n publicClient,\n slippageBps,\n solverTip: params.solverTip,\n maxPriceAge: params.maxPriceAge,\n aeraRuntime,\n minUnitsOut: params.minUnitsOut,\n });\n steps.push(...depositSteps);\n\n return Promise.all(steps.map((step) => encodeTransactionWithAttribution(client, step, chainId)));\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"depositQuote.d.ts","sourceRoot":"","sources":["../../../src/evm/depositQuote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAmBhD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AA6CH,mEAAmE;AACnE,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAyB3B;AAED,+FAA+F;AAC/F,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAS1B"}
1
+ {"version":3,"file":"depositQuote.d.ts","sourceRoot":"","sources":["../../../src/evm/depositQuote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAmBhD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AA6CH,mEAAmE;AACnE,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CA0B3B;AAED,+FAA+F;AAC/F,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAS1B"}
@@ -57,6 +57,7 @@ async function resolveSyncDepositContext(client, params, readKind) {
57
57
  return { publicClient, vault, token, runtime };
58
58
  }
59
59
  async function getSyncDepositQuote(client, params) {
60
+ params = structuredClone(params);
60
61
  const slippageBps = params.slippageBps ?? import_constants.DEFAULT_BPS;
61
62
  if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > Number(import_constants.MAX_BPS)) {
62
63
  throw new import_errors.InvalidSlippageBPSError(slippageBps);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/evm/depositQuote.ts"],
4
- "sourcesContent": ["import type { GauntletClient } from '../client';\nimport { DEFAULT_BPS, MAX_BPS } from '../constants';\nimport {\n InvalidSlippageBPSError,\n InvalidSyncDepositBoundError,\n UnsupportedAssetError,\n UnsupportedFeatureError,\n VaultNotFoundError,\n} from '../errors';\nimport {\n applySlippageDown,\n resolveAeraRuntimeContracts,\n resolveAeraTokenModeSupport,\n} from './aeraContracts';\nimport { getSyncDepositFeeBps, getSyncDepositQuoteValues } from './aeraContracts/v2';\nimport { resolveOperationMode } from './operationMode';\nimport { ContractVersion } from './types';\nimport { resolveVault } from './vaults';\n\nexport type SyncDepositQuote = Readonly<{\n unitsOut: bigint;\n minUnitsOut: bigint;\n /** Deposit amount converted to the vault's numeraire, after the Instant Supply fee. */\n numeraireOut: bigint;\n /** Instant Supply fee applied to the deposited token amount, in basis points. */\n feeBps: bigint;\n /** Slippage tolerance used to derive `minUnitsOut`, in basis points. */\n slippageBps: number;\n}>;\n\nexport type SyncDepositQuoteParams = {\n vaultId: string;\n chainId?: number;\n assetSymbol?: string;\n amount: bigint;\n slippageBps?: number;\n};\n\nexport type SyncDepositRateParams = {\n vaultId: string;\n chainId?: number;\n assetSymbol?: string;\n};\n\nexport type SyncDepositRate = Readonly<{\n /** Instant Supply fee, in basis points. Independent of the deposit amount. */\n feeBps: bigint;\n}>;\n\nasync function resolveSyncDepositContext(\n client: GauntletClient,\n params: SyncDepositRateParams,\n readKind: 'quote' | 'rate'\n) {\n const resolved = await resolveVault(client, params.vaultId, params.chainId);\n if (!resolved) throw new VaultNotFoundError(params.vaultId, params.chainId);\n if (resolved.protocol !== 'aera') {\n throw new UnsupportedFeatureError(\n readKind === 'quote'\n ? 'Sync deposit quote is only available for Aera vaults'\n : 'Sync deposit rate is only available for Aera vaults'\n );\n }\n\n const { vault } = resolved;\n const token =\n vault.supplyToken.length > 1\n ? vault.supplyToken.find(({ symbol }) => symbol === params.assetSymbol)\n : vault.supplyToken[0];\n if (!token) throw new UnsupportedAssetError(params.assetSymbol ?? 'unknown', params.vaultId);\n\n const publicClient = client.getPublicClient(params.chainId ?? vault.chainId);\n const runtime = await resolveAeraRuntimeContracts(publicClient, vault);\n if (runtime.provisioner.version !== ContractVersion.V2) {\n throw new UnsupportedFeatureError(\n readKind === 'quote'\n ? 'Sync deposit quote requires an Aera V2 provisioner'\n : 'Sync deposit rate requires an Aera V2 provisioner'\n );\n }\n\n const tokenModeSupport = await resolveAeraTokenModeSupport(publicClient, runtime, token.address, {\n includeSyncModes: true,\n });\n resolveOperationMode(params.vaultId, 'sync', {\n async: tokenModeSupport.asyncDeposit,\n sync: tokenModeSupport.syncDeposit,\n });\n\n return { publicClient, vault, token, runtime };\n}\n\n/** Quotes an Aera synchronous deposit and its execution bounds. */\nexport async function getSyncDepositQuote(\n client: GauntletClient,\n params: SyncDepositQuoteParams\n): Promise<SyncDepositQuote> {\n const slippageBps = params.slippageBps ?? DEFAULT_BPS;\n if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > Number(MAX_BPS)) {\n throw new InvalidSlippageBPSError(slippageBps);\n }\n\n const { publicClient, vault, token, runtime } = await resolveSyncDepositContext(\n client,\n params,\n 'quote'\n );\n\n const { unitsOut, feeBps, numeraireOut } = await getSyncDepositQuoteValues(\n publicClient,\n runtime.provisioner.address,\n runtime.feeCalculator.address,\n runtime.feeCalculator.version,\n vault.vaultAddress,\n token.address,\n params.amount\n );\n const minUnitsOut = applySlippageDown(unitsOut, slippageBps);\n if (minUnitsOut <= 0n) throw new InvalidSyncDepositBoundError();\n\n return { unitsOut, minUnitsOut, numeraireOut, feeBps, slippageBps };\n}\n\n/** Reads the live Instant Supply fee for a vault token, without requiring a deposit amount. */\nexport async function getSyncDepositRate(\n client: GauntletClient,\n params: SyncDepositRateParams\n): Promise<SyncDepositRate> {\n const { publicClient, runtime, token } = await resolveSyncDepositContext(client, params, 'rate');\n\n const feeBps = await getSyncDepositFeeBps(\n publicClient,\n runtime.provisioner.address,\n token.address\n );\n return { feeBps };\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAAqC;AACrC,oBAMO;AACP,2BAIO;AACP,gBAAgE;AAChE,2BAAqC;AACrC,mBAAgC;AAChC,oBAA6B;AAgC7B,eAAe,0BACb,QACA,QACA,UACA;AACA,QAAM,WAAW,UAAM,4BAAa,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC1E,MAAI,CAAC,SAAU,OAAM,IAAI,iCAAmB,OAAO,SAAS,OAAO,OAAO;AAC1E,MAAI,SAAS,aAAa,QAAQ;AAChC,UAAM,IAAI;AAAA,MACR,aAAa,UACT,yDACA;AAAA,IACN;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,QACJ,MAAM,YAAY,SAAS,IACvB,MAAM,YAAY,KAAK,CAAC,EAAE,OAAO,MAAM,WAAW,OAAO,WAAW,IACpE,MAAM,YAAY,CAAC;AACzB,MAAI,CAAC,MAAO,OAAM,IAAI,oCAAsB,OAAO,eAAe,WAAW,OAAO,OAAO;AAE3F,QAAM,eAAe,OAAO,gBAAgB,OAAO,WAAW,MAAM,OAAO;AAC3E,QAAM,UAAU,UAAM,kDAA4B,cAAc,KAAK;AACrE,MAAI,QAAQ,YAAY,YAAY,6BAAgB,IAAI;AACtD,UAAM,IAAI;AAAA,MACR,aAAa,UACT,uDACA;AAAA,IACN;AAAA,EACF;AAEA,QAAM,mBAAmB,UAAM,kDAA4B,cAAc,SAAS,MAAM,SAAS;AAAA,IAC/F,kBAAkB;AAAA,EACpB,CAAC;AACD,iDAAqB,OAAO,SAAS,QAAQ;AAAA,IAC3C,OAAO,iBAAiB;AAAA,IACxB,MAAM,iBAAiB;AAAA,EACzB,CAAC;AAED,SAAO,EAAE,cAAc,OAAO,OAAO,QAAQ;AAC/C;AAGA,eAAsB,oBACpB,QACA,QAC2B;AAC3B,QAAM,cAAc,OAAO,eAAe;AAC1C,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,KAAK,cAAc,OAAO,wBAAO,GAAG;AACtF,UAAM,IAAI,sCAAwB,WAAW;AAAA,EAC/C;AAEA,QAAM,EAAE,cAAc,OAAO,OAAO,QAAQ,IAAI,MAAM;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,EAAE,UAAU,QAAQ,aAAa,IAAI,UAAM;AAAA,IAC/C;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,QAAQ,cAAc;AAAA,IACtB,QAAQ,cAAc;AAAA,IACtB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACA,QAAM,kBAAc,wCAAkB,UAAU,WAAW;AAC3D,MAAI,eAAe,GAAI,OAAM,IAAI,2CAA6B;AAE9D,SAAO,EAAE,UAAU,aAAa,cAAc,QAAQ,YAAY;AACpE;AAGA,eAAsB,mBACpB,QACA,QAC0B;AAC1B,QAAM,EAAE,cAAc,SAAS,MAAM,IAAI,MAAM,0BAA0B,QAAQ,QAAQ,MAAM;AAE/F,QAAM,SAAS,UAAM;AAAA,IACnB;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,MAAM;AAAA,EACR;AACA,SAAO,EAAE,OAAO;AAClB;",
4
+ "sourcesContent": ["import type { GauntletClient } from '../client';\nimport { DEFAULT_BPS, MAX_BPS } from '../constants';\nimport {\n InvalidSlippageBPSError,\n InvalidSyncDepositBoundError,\n UnsupportedAssetError,\n UnsupportedFeatureError,\n VaultNotFoundError,\n} from '../errors';\nimport {\n applySlippageDown,\n resolveAeraRuntimeContracts,\n resolveAeraTokenModeSupport,\n} from './aeraContracts';\nimport { getSyncDepositFeeBps, getSyncDepositQuoteValues } from './aeraContracts/v2';\nimport { resolveOperationMode } from './operationMode';\nimport { ContractVersion } from './types';\nimport { resolveVault } from './vaults';\n\nexport type SyncDepositQuote = Readonly<{\n unitsOut: bigint;\n minUnitsOut: bigint;\n /** Deposit amount converted to the vault's numeraire, after the Instant Supply fee. */\n numeraireOut: bigint;\n /** Instant Supply fee applied to the deposited token amount, in basis points. */\n feeBps: bigint;\n /** Slippage tolerance used to derive `minUnitsOut`, in basis points. */\n slippageBps: number;\n}>;\n\nexport type SyncDepositQuoteParams = {\n vaultId: string;\n chainId?: number;\n assetSymbol?: string;\n amount: bigint;\n slippageBps?: number;\n};\n\nexport type SyncDepositRateParams = {\n vaultId: string;\n chainId?: number;\n assetSymbol?: string;\n};\n\nexport type SyncDepositRate = Readonly<{\n /** Instant Supply fee, in basis points. Independent of the deposit amount. */\n feeBps: bigint;\n}>;\n\nasync function resolveSyncDepositContext(\n client: GauntletClient,\n params: SyncDepositRateParams,\n readKind: 'quote' | 'rate'\n) {\n const resolved = await resolveVault(client, params.vaultId, params.chainId);\n if (!resolved) throw new VaultNotFoundError(params.vaultId, params.chainId);\n if (resolved.protocol !== 'aera') {\n throw new UnsupportedFeatureError(\n readKind === 'quote'\n ? 'Sync deposit quote is only available for Aera vaults'\n : 'Sync deposit rate is only available for Aera vaults'\n );\n }\n\n const { vault } = resolved;\n const token =\n vault.supplyToken.length > 1\n ? vault.supplyToken.find(({ symbol }) => symbol === params.assetSymbol)\n : vault.supplyToken[0];\n if (!token) throw new UnsupportedAssetError(params.assetSymbol ?? 'unknown', params.vaultId);\n\n const publicClient = client.getPublicClient(params.chainId ?? vault.chainId);\n const runtime = await resolveAeraRuntimeContracts(publicClient, vault);\n if (runtime.provisioner.version !== ContractVersion.V2) {\n throw new UnsupportedFeatureError(\n readKind === 'quote'\n ? 'Sync deposit quote requires an Aera V2 provisioner'\n : 'Sync deposit rate requires an Aera V2 provisioner'\n );\n }\n\n const tokenModeSupport = await resolveAeraTokenModeSupport(publicClient, runtime, token.address, {\n includeSyncModes: true,\n });\n resolveOperationMode(params.vaultId, 'sync', {\n async: tokenModeSupport.asyncDeposit,\n sync: tokenModeSupport.syncDeposit,\n });\n\n return { publicClient, vault, token, runtime };\n}\n\n/** Quotes an Aera synchronous deposit and its execution bounds. */\nexport async function getSyncDepositQuote(\n client: GauntletClient,\n params: SyncDepositQuoteParams\n): Promise<SyncDepositQuote> {\n params = structuredClone(params);\n const slippageBps = params.slippageBps ?? DEFAULT_BPS;\n if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > Number(MAX_BPS)) {\n throw new InvalidSlippageBPSError(slippageBps);\n }\n\n const { publicClient, vault, token, runtime } = await resolveSyncDepositContext(\n client,\n params,\n 'quote'\n );\n\n const { unitsOut, feeBps, numeraireOut } = await getSyncDepositQuoteValues(\n publicClient,\n runtime.provisioner.address,\n runtime.feeCalculator.address,\n runtime.feeCalculator.version,\n vault.vaultAddress,\n token.address,\n params.amount\n );\n const minUnitsOut = applySlippageDown(unitsOut, slippageBps);\n if (minUnitsOut <= 0n) throw new InvalidSyncDepositBoundError();\n\n return { unitsOut, minUnitsOut, numeraireOut, feeBps, slippageBps };\n}\n\n/** Reads the live Instant Supply fee for a vault token, without requiring a deposit amount. */\nexport async function getSyncDepositRate(\n client: GauntletClient,\n params: SyncDepositRateParams\n): Promise<SyncDepositRate> {\n const { publicClient, runtime, token } = await resolveSyncDepositContext(client, params, 'rate');\n\n const feeBps = await getSyncDepositFeeBps(\n publicClient,\n runtime.provisioner.address,\n token.address\n );\n return { feeBps };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAAqC;AACrC,oBAMO;AACP,2BAIO;AACP,gBAAgE;AAChE,2BAAqC;AACrC,mBAAgC;AAChC,oBAA6B;AAgC7B,eAAe,0BACb,QACA,QACA,UACA;AACA,QAAM,WAAW,UAAM,4BAAa,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC1E,MAAI,CAAC,SAAU,OAAM,IAAI,iCAAmB,OAAO,SAAS,OAAO,OAAO;AAC1E,MAAI,SAAS,aAAa,QAAQ;AAChC,UAAM,IAAI;AAAA,MACR,aAAa,UACT,yDACA;AAAA,IACN;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,QACJ,MAAM,YAAY,SAAS,IACvB,MAAM,YAAY,KAAK,CAAC,EAAE,OAAO,MAAM,WAAW,OAAO,WAAW,IACpE,MAAM,YAAY,CAAC;AACzB,MAAI,CAAC,MAAO,OAAM,IAAI,oCAAsB,OAAO,eAAe,WAAW,OAAO,OAAO;AAE3F,QAAM,eAAe,OAAO,gBAAgB,OAAO,WAAW,MAAM,OAAO;AAC3E,QAAM,UAAU,UAAM,kDAA4B,cAAc,KAAK;AACrE,MAAI,QAAQ,YAAY,YAAY,6BAAgB,IAAI;AACtD,UAAM,IAAI;AAAA,MACR,aAAa,UACT,uDACA;AAAA,IACN;AAAA,EACF;AAEA,QAAM,mBAAmB,UAAM,kDAA4B,cAAc,SAAS,MAAM,SAAS;AAAA,IAC/F,kBAAkB;AAAA,EACpB,CAAC;AACD,iDAAqB,OAAO,SAAS,QAAQ;AAAA,IAC3C,OAAO,iBAAiB;AAAA,IACxB,MAAM,iBAAiB;AAAA,EACzB,CAAC;AAED,SAAO,EAAE,cAAc,OAAO,OAAO,QAAQ;AAC/C;AAGA,eAAsB,oBACpB,QACA,QAC2B;AAC3B,WAAS,gBAAgB,MAAM;AAC/B,QAAM,cAAc,OAAO,eAAe;AAC1C,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,KAAK,cAAc,OAAO,wBAAO,GAAG;AACtF,UAAM,IAAI,sCAAwB,WAAW;AAAA,EAC/C;AAEA,QAAM,EAAE,cAAc,OAAO,OAAO,QAAQ,IAAI,MAAM;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,EAAE,UAAU,QAAQ,aAAa,IAAI,UAAM;AAAA,IAC/C;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,QAAQ,cAAc;AAAA,IACtB,QAAQ,cAAc;AAAA,IACtB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACA,QAAM,kBAAc,wCAAkB,UAAU,WAAW;AAC3D,MAAI,eAAe,GAAI,OAAM,IAAI,2CAA6B;AAE9D,SAAO,EAAE,UAAU,aAAa,cAAc,QAAQ,YAAY;AACpE;AAGA,eAAsB,mBACpB,QACA,QAC0B;AAC1B,QAAM,EAAE,cAAc,SAAS,MAAM,IAAI,MAAM,0BAA0B,QAAQ,QAAQ,MAAM;AAE/F,QAAM,SAAS,UAAM;AAAA,IACnB;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,MAAM;AAAA,EACR;AACA,SAAO,EAAE,OAAO;AAClB;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"depositReceiverApproval.d.ts","sourceRoot":"","sources":["../../../src/evm/depositReceiverApproval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAuB;AAQjD,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gCAAgC,GACvC,OAAO,CAAC,UAAU,CAAC,CAwBrB"}
1
+ {"version":3,"file":"depositReceiverApproval.d.ts","sourceRoot":"","sources":["../../../src/evm/depositReceiverApproval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAuB;AAQjD,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gCAAgC,GACvC,OAAO,CAAC,UAAU,CAAC,CA6BrB"}
@@ -38,6 +38,7 @@ var provisionerV2 = __toESM(require("./aeraContracts/v2"), 1);
38
38
  var import_types = require("./types");
39
39
  var import_vaults = require("./vaults");
40
40
  async function getDepositReceiverApprovalTx(client, params) {
41
+ params = { ...params };
41
42
  const resolved = await (0, import_vaults.resolveVault)(client, params.vaultId, params.chainId);
42
43
  if (!resolved) throw new import_errors.VaultNotFoundError(params.vaultId);
43
44
  const chainId = params.chainId ?? resolved.vault.chainId;
@@ -49,15 +50,19 @@ async function getDepositReceiverApprovalTx(client, params) {
49
50
  if (runtime.provisioner.version !== import_types.ContractVersion.V2) {
50
51
  throw new import_errors.UnsupportedFeatureError("Aera: deposit receiver approval on V1");
51
52
  }
52
- return (0, import_attribution.encodeTransactionWithAttribution)(client, {
53
- type: "setDepositReceiverApproval",
54
- ...provisionerV2.setDepositReceiverApprovalTxRequest(
55
- runtime.provisioner.address,
56
- params.depositor,
57
- params.approved ?? true,
58
- receiver
59
- )
60
- });
53
+ return (0, import_attribution.encodeTransactionWithAttribution)(
54
+ client,
55
+ {
56
+ type: "setDepositReceiverApproval",
57
+ ...provisionerV2.setDepositReceiverApprovalTxRequest(
58
+ runtime.provisioner.address,
59
+ params.depositor,
60
+ params.approved ?? true,
61
+ receiver
62
+ )
63
+ },
64
+ chainId
65
+ );
61
66
  }
62
67
  // Annotate the CommonJS export names for ESM import in node:
63
68
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/evm/depositReceiverApproval.ts"],
4
- "sourcesContent": ["import type { Address } from 'viem';\nimport type { GauntletClient } from '../client';\nimport type { PreparedTx } from '../attribution';\nimport { encodeTransactionWithAttribution } from '../attribution';\nimport { AccountRequiredError, UnsupportedFeatureError, VaultNotFoundError } from '../errors';\nimport { resolveAeraRuntimeContracts } from './aeraContracts';\nimport * as provisionerV2 from './aeraContracts/v2';\nimport { ContractVersion } from './types';\nimport { resolveVault } from './vaults';\n\nexport interface EvmDepositReceiverApprovalParams {\n vaultId: string;\n depositor: Address;\n approved?: boolean;\n chainId?: number;\n}\n\n/**\n * Builds the V2 receiver-side approval transaction required before a depositor\n * can make sync deposits to a separate receiver.\n *\n * The wallet account on the client is the receiver and must sign this transaction.\n */\nexport async function getDepositReceiverApprovalTx(\n client: GauntletClient,\n params: EvmDepositReceiverApprovalParams\n): Promise<PreparedTx> {\n const resolved = await resolveVault(client, params.vaultId, params.chainId);\n if (!resolved) throw new VaultNotFoundError(params.vaultId);\n\n const chainId = params.chainId ?? resolved.vault.chainId;\n const receiver = client.wallet?.account?.address;\n if (!receiver) throw new AccountRequiredError();\n\n const { vault } = resolved;\n const publicClient = client.getPublicClient(chainId);\n const runtime = await resolveAeraRuntimeContracts(publicClient, vault);\n if (runtime.provisioner.version !== ContractVersion.V2) {\n throw new UnsupportedFeatureError('Aera: deposit receiver approval on V1');\n }\n\n return encodeTransactionWithAttribution(client, {\n type: 'setDepositReceiverApproval',\n ...provisionerV2.setDepositReceiverApprovalTxRequest(\n runtime.provisioner.address,\n params.depositor,\n params.approved ?? true,\n receiver\n ),\n });\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,yBAAiD;AACjD,oBAAkF;AAClF,2BAA4C;AAC5C,oBAA+B;AAC/B,mBAAgC;AAChC,oBAA6B;AAe7B,eAAsB,6BACpB,QACA,QACqB;AACrB,QAAM,WAAW,UAAM,4BAAa,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC1E,MAAI,CAAC,SAAU,OAAM,IAAI,iCAAmB,OAAO,OAAO;AAE1D,QAAM,UAAU,OAAO,WAAW,SAAS,MAAM;AACjD,QAAM,WAAW,OAAO,QAAQ,SAAS;AACzC,MAAI,CAAC,SAAU,OAAM,IAAI,mCAAqB;AAE9C,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,eAAe,OAAO,gBAAgB,OAAO;AACnD,QAAM,UAAU,UAAM,kDAA4B,cAAc,KAAK;AACrE,MAAI,QAAQ,YAAY,YAAY,6BAAgB,IAAI;AACtD,UAAM,IAAI,sCAAwB,uCAAuC;AAAA,EAC3E;AAEA,aAAO,qDAAiC,QAAQ;AAAA,IAC9C,MAAM;AAAA,IACN,GAAG,cAAc;AAAA,MACf,QAAQ,YAAY;AAAA,MACpB,OAAO;AAAA,MACP,OAAO,YAAY;AAAA,MACnB;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
4
+ "sourcesContent": ["import type { Address } from 'viem';\nimport type { GauntletClient } from '../client';\nimport type { PreparedTx } from '../attribution';\nimport { encodeTransactionWithAttribution } from '../attribution';\nimport { AccountRequiredError, UnsupportedFeatureError, VaultNotFoundError } from '../errors';\nimport { resolveAeraRuntimeContracts } from './aeraContracts';\nimport * as provisionerV2 from './aeraContracts/v2';\nimport { ContractVersion } from './types';\nimport { resolveVault } from './vaults';\n\nexport interface EvmDepositReceiverApprovalParams {\n vaultId: string;\n depositor: Address;\n approved?: boolean;\n chainId?: number;\n}\n\n/**\n * Builds the V2 receiver-side approval transaction required before a depositor\n * can make sync deposits to a separate receiver.\n *\n * The wallet account on the client is the receiver and must sign this transaction.\n */\nexport async function getDepositReceiverApprovalTx(\n client: GauntletClient,\n params: EvmDepositReceiverApprovalParams\n): Promise<PreparedTx> {\n params = { ...params };\n const resolved = await resolveVault(client, params.vaultId, params.chainId);\n if (!resolved) throw new VaultNotFoundError(params.vaultId);\n\n const chainId = params.chainId ?? resolved.vault.chainId;\n const receiver = client.wallet?.account?.address;\n if (!receiver) throw new AccountRequiredError();\n\n const { vault } = resolved;\n const publicClient = client.getPublicClient(chainId);\n const runtime = await resolveAeraRuntimeContracts(publicClient, vault);\n if (runtime.provisioner.version !== ContractVersion.V2) {\n throw new UnsupportedFeatureError('Aera: deposit receiver approval on V1');\n }\n\n return encodeTransactionWithAttribution(\n client,\n {\n type: 'setDepositReceiverApproval',\n ...provisionerV2.setDepositReceiverApprovalTxRequest(\n runtime.provisioner.address,\n params.depositor,\n params.approved ?? true,\n receiver\n ),\n },\n chainId\n );\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,yBAAiD;AACjD,oBAAkF;AAClF,2BAA4C;AAC5C,oBAA+B;AAC/B,mBAAgC;AAChC,oBAA6B;AAe7B,eAAsB,6BACpB,QACA,QACqB;AACrB,WAAS,EAAE,GAAG,OAAO;AACrB,QAAM,WAAW,UAAM,4BAAa,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC1E,MAAI,CAAC,SAAU,OAAM,IAAI,iCAAmB,OAAO,OAAO;AAE1D,QAAM,UAAU,OAAO,WAAW,SAAS,MAAM;AACjD,QAAM,WAAW,OAAO,QAAQ,SAAS;AACzC,MAAI,CAAC,SAAU,OAAM,IAAI,mCAAqB;AAE9C,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,eAAe,OAAO,gBAAgB,OAAO;AACnD,QAAM,UAAU,UAAM,kDAA4B,cAAc,KAAK;AACrE,MAAI,QAAQ,YAAY,YAAY,6BAAgB,IAAI;AACtD,UAAM,IAAI,sCAAwB,uCAAuC;AAAA,EAC3E;AAEA,aAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,GAAG,cAAc;AAAA,QACf,QAAQ,YAAY;AAAA,QACpB,OAAO;AAAA,QACP,OAAO,YAAY;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -4,8 +4,19 @@ export interface UserCurrentBalanceParams {
4
4
  vaultId: string;
5
5
  address: Address;
6
6
  chainId?: number;
7
+ /** Required for deployments that support multiple assets, ignored otherwise. */
8
+ assetSymbol?: string;
9
+ /**
10
+ * Scan from this block, including expired requests that still hold escrow.
11
+ * Requires `chainId` for a vault with more than one deployment.
12
+ */
13
+ fromBlock?: bigint;
7
14
  }
8
15
  export interface UserCurrentBalance {
16
+ /** Block used for balances, conversions, and request state. */
17
+ blockNumber: bigint;
18
+ /** First block included in the request scan. Older escrow is outside this result. */
19
+ fromBlock: bigint;
9
20
  /** Chain identifier, e.g. "base" */
10
21
  chain: string;
11
22
  /** EVM chain id of the deployment, e.g. 8453 */
@@ -30,7 +41,9 @@ export interface UserCurrentBalance {
30
41
  * - `pendingWithdraw` — vault units locked in a pending async redeem request (converted to tokens).
31
42
  *
32
43
  * Only supported for Aera multi-depositor vaults. Pending amounts are detected by scanning
33
- * the last ~3 days of provisioner events and cross-checking hash existence on-chain.
44
+ * the configured request lifetime, with a minimum of three days. Set `fromBlock` (with `chainId`
45
+ * on a multi-chain vault) for older escrow.
46
+ * All state reads use one block. The returned range identifies the scanned history.
34
47
  *
35
48
  * @param client - A configured `GauntletClient` instance with an EVM public client for each
36
49
  * chain the vault is deployed on.
@@ -41,6 +54,7 @@ export interface UserCurrentBalance {
41
54
  * @throws {VaultNotFoundError} If the vault ID is not found in the manifest.
42
55
  * @throws {UnsupportedProtocolError} If the vault is not an Aera multi-depositor vault.
43
56
  * @throws {ChainMismatchError} If `chainId` is specified but no deployment exists for that chain.
57
+ * @throws {UnsupportedAssetError} If a multi-asset deployment gets no matching `assetSymbol`.
44
58
  *
45
59
  * @example
46
60
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"userCurrentBalance.d.ts","sourceRoot":"","sources":["../../../src/evm/userCurrentBalance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAoDhD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAwKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAyB/B"}
1
+ {"version":3,"file":"userCurrentBalance.d.ts","sourceRoot":"","sources":["../../../src/evm/userCurrentBalance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAkB;AAmEhD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2ND;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA6B/B"}
@@ -29,6 +29,7 @@ var import_v2 = require("./aeraContracts/v2");
29
29
  var import_provisionerV2 = require("./abis/provisionerV2");
30
30
  var import_types = require("./types");
31
31
  var import_constants = require("../constants");
32
+ const LOG_CHUNK_CONCURRENCY = 16;
32
33
  const DEPOSIT_REQUESTED_V1_ABI = [
33
34
  {
34
35
  type: "event",
@@ -76,71 +77,105 @@ function dedupeByRequestHash(logs, hashKey) {
76
77
  return true;
77
78
  });
78
79
  }
79
- async function queryDeploymentBalance(client, deployment, address) {
80
+ async function requestScanStart(publicClient, chainId, blockNumber, days, cutoff) {
81
+ let span = (import_constants.BLOCKS_3_DAYS[chainId] ?? import_constants.DEFAULT_BLOCKS_3_DAYS) * BigInt(days) / 3n;
82
+ for (; ; ) {
83
+ if (span >= blockNumber) return 0n;
84
+ const start = blockNumber - span;
85
+ const block = await publicClient.getBlock({ blockNumber: start });
86
+ if (block.timestamp <= cutoff) return start;
87
+ span *= 2n;
88
+ }
89
+ }
90
+ async function mapInBatches(items, size, fn) {
91
+ const results = [];
92
+ for (let i = 0; i < items.length; i += size) {
93
+ results.push(...await Promise.all(items.slice(i, i + size).map(fn)));
94
+ }
95
+ return results;
96
+ }
97
+ async function queryDeploymentBalance(client, deployment, params) {
80
98
  const publicClient = client.getPublicClient(deployment.chainId);
81
- const token = deployment.supplyToken[0];
99
+ const { address } = params;
100
+ const token = deployment.supplyToken.length > 1 ? deployment.supplyToken.find((candidate) => candidate.symbol === params.assetSymbol) : deployment.supplyToken[0];
101
+ if (token === void 0)
102
+ throw new import_errors.UnsupportedAssetError(params.assetSymbol ?? "unknown", params.vaultId);
103
+ const snapshot = await publicClient.getBlock({ blockTag: "latest" });
104
+ if (snapshot.number === null) {
105
+ throw new import_errors.GauntletSDKError("The balance snapshot has no block number");
106
+ }
107
+ const blockNumber = snapshot.number;
108
+ const readOptions = { blockNumber };
109
+ const expirationDays = deployment.expirationDays ?? 3;
110
+ if (!Number.isSafeInteger(expirationDays) || expirationDays <= 0) {
111
+ throw new import_errors.GauntletSDKError("The request expiration must be a positive integer number of days");
112
+ }
113
+ const scanDays = Math.max(3, expirationDays);
114
+ const cutoff = snapshot.timestamp - BigInt(import_constants.DAY) * BigInt(scanDays);
115
+ const fromBlock = params.fromBlock ?? await requestScanStart(publicClient, deployment.chainId, blockNumber, scanDays, cutoff);
116
+ if (fromBlock < 0n || fromBlock > blockNumber) {
117
+ throw new import_errors.GauntletSDKError("The request scan range is invalid");
118
+ }
82
119
  const vaultContract = (0, import_aeraContracts.getMultiDepositorVault)(publicClient, deployment.vaultAddress);
83
120
  const [runtime, units] = await Promise.all([
84
- (0, import_aeraContracts.resolveAeraRuntimeContracts)(publicClient, deployment),
85
- vaultContract.read.balanceOf([address])
121
+ (0, import_aeraContracts.resolveAeraRuntimeContracts)(publicClient, deployment, readOptions),
122
+ vaultContract.read.balanceOf([address], readOptions)
86
123
  ]);
87
124
  const provisionerAddress = runtime.provisioner.address;
88
125
  const isV2 = runtime.provisioner.version === import_types.ContractVersion.V2;
89
- const unitsLockedUntilPromise = isV2 ? (0, import_v2.getUserUnitsRefundableUntil)(publicClient, provisionerAddress, address) : Promise.resolve(void 0);
126
+ const unitsLockedUntilPromise = isV2 ? (0, import_v2.getUserUnitsRefundableUntil)(publicClient, provisionerAddress, address, readOptions) : Promise.resolve(void 0);
90
127
  const balance = await (0, import_priceAndFeeCalculator.convertUnitsToToken)(
91
128
  publicClient,
92
129
  runtime.feeCalculator.address,
93
130
  runtime.feeCalculator.version,
94
131
  deployment.vaultAddress,
95
132
  token.address,
96
- units
133
+ units,
134
+ readOptions
97
135
  );
98
- const currentBlock = await publicClient.getBlockNumber();
99
- const lookback = import_constants.BLOCKS_3_DAYS[deployment.chainId] ?? import_constants.DEFAULT_BLOCKS_3_DAYS;
100
- const fromBlock = currentBlock > lookback ? currentBlock - lookback : 0n;
101
136
  const chunks = [];
102
- for (let cursor = fromBlock; cursor <= currentBlock; cursor += import_constants.LOG_PAGE_SIZE + 1n) {
103
- const end = cursor + import_constants.LOG_PAGE_SIZE <= currentBlock ? cursor + import_constants.LOG_PAGE_SIZE : currentBlock;
137
+ for (let cursor = fromBlock; cursor <= blockNumber; cursor += import_constants.LOG_PAGE_SIZE + 1n) {
138
+ const end = cursor + import_constants.LOG_PAGE_SIZE <= blockNumber ? cursor + import_constants.LOG_PAGE_SIZE : blockNumber;
104
139
  chunks.push([cursor, end]);
105
140
  }
106
141
  const [depositPages, redeemPages] = await Promise.all([
107
- Promise.all(
108
- chunks.map(
109
- ([from, to]) => isV2 ? publicClient.getContractEvents({
110
- address: provisionerAddress,
111
- abi: import_provisionerV2.provisionerV2Abi,
112
- eventName: "DepositRequested",
113
- args: { receiver: address },
114
- fromBlock: from,
115
- toBlock: to
116
- }) : publicClient.getContractEvents({
117
- address: provisionerAddress,
118
- abi: DEPOSIT_REQUESTED_V1_ABI,
119
- eventName: "DepositRequested",
120
- args: { user: address },
121
- fromBlock: from,
122
- toBlock: to
123
- })
124
- )
142
+ mapInBatches(
143
+ chunks,
144
+ LOG_CHUNK_CONCURRENCY,
145
+ ([from, to]) => isV2 ? publicClient.getContractEvents({
146
+ address: provisionerAddress,
147
+ abi: import_provisionerV2.provisionerV2Abi,
148
+ eventName: "DepositRequested",
149
+ args: { receiver: address, token: token.address },
150
+ fromBlock: from,
151
+ toBlock: to
152
+ }) : publicClient.getContractEvents({
153
+ address: provisionerAddress,
154
+ abi: DEPOSIT_REQUESTED_V1_ABI,
155
+ eventName: "DepositRequested",
156
+ args: { user: address, token: token.address },
157
+ fromBlock: from,
158
+ toBlock: to
159
+ })
125
160
  ),
126
- Promise.all(
127
- chunks.map(
128
- ([from, to]) => isV2 ? publicClient.getContractEvents({
129
- address: provisionerAddress,
130
- abi: import_provisionerV2.provisionerV2Abi,
131
- eventName: "RedeemRequested",
132
- args: { user: address },
133
- fromBlock: from,
134
- toBlock: to
135
- }) : publicClient.getContractEvents({
136
- address: provisionerAddress,
137
- abi: REDEEM_REQUESTED_V1_ABI,
138
- eventName: "RedeemRequested",
139
- args: { user: address },
140
- fromBlock: from,
141
- toBlock: to
142
- })
143
- )
161
+ mapInBatches(
162
+ chunks,
163
+ LOG_CHUNK_CONCURRENCY,
164
+ ([from, to]) => isV2 ? publicClient.getContractEvents({
165
+ address: provisionerAddress,
166
+ abi: import_provisionerV2.provisionerV2Abi,
167
+ eventName: "RedeemRequested",
168
+ args: { user: address, token: token.address },
169
+ fromBlock: from,
170
+ toBlock: to
171
+ }) : publicClient.getContractEvents({
172
+ address: provisionerAddress,
173
+ abi: REDEEM_REQUESTED_V1_ABI,
174
+ eventName: "RedeemRequested",
175
+ args: { user: address, token: token.address },
176
+ fromBlock: from,
177
+ toBlock: to
178
+ })
144
179
  )
145
180
  ]);
146
181
  const depositLogs = dedupeByRequestHash(depositPages.flat(), "depositRequestHash");
@@ -160,7 +195,8 @@ async function queryDeploymentBalance(client, deployment, address) {
160
195
  args: [log.args.redeemRequestHash]
161
196
  }))
162
197
  ],
163
- allowFailure: false
198
+ allowFailure: false,
199
+ blockNumber
164
200
  });
165
201
  const depositChecks = pendingChecks.slice(0, depositLogs.length);
166
202
  const redeemChecks = pendingChecks.slice(depositLogs.length);
@@ -182,10 +218,13 @@ async function queryDeploymentBalance(client, deployment, address) {
182
218
  runtime.feeCalculator.version,
183
219
  deployment.vaultAddress,
184
220
  token.address,
185
- pendingWithdrawUnits
221
+ pendingWithdrawUnits,
222
+ readOptions
186
223
  ) : 0n;
187
224
  const unitsLockedUntil = await unitsLockedUntilPromise;
188
225
  return {
226
+ blockNumber,
227
+ fromBlock,
189
228
  chain: import_constants.CHAIN_NAMES[deployment.chainId] ?? `chain-${deployment.chainId}`,
190
229
  chainId: deployment.chainId,
191
230
  token: token.address,
@@ -197,6 +236,7 @@ async function queryDeploymentBalance(client, deployment, address) {
197
236
  };
198
237
  }
199
238
  async function getUserCurrentBalance(client, params) {
239
+ params = { ...params };
200
240
  const manifest = await client.manifest;
201
241
  const vaultInfo = manifest.vaults.find((v) => v.vaultId === params.vaultId);
202
242
  if (!vaultInfo) throw new import_errors.VaultNotFoundError(params.vaultId);
@@ -214,9 +254,12 @@ async function getUserCurrentBalance(client, params) {
214
254
  evmDeployments.map((d) => `${d.chainId}`).join(", ")
215
255
  );
216
256
  }
217
- return [await queryDeploymentBalance(client, deployment, params.address)];
257
+ return [await queryDeploymentBalance(client, deployment, params)];
258
+ }
259
+ if (params.fromBlock !== void 0 && evmDeployments.length > 1) {
260
+ throw new import_errors.GauntletSDKError("fromBlock requires chainId for a vault with several deployments");
218
261
  }
219
- return Promise.all(evmDeployments.map((d) => queryDeploymentBalance(client, d, params.address)));
262
+ return Promise.all(evmDeployments.map((d) => queryDeploymentBalance(client, d, params)));
220
263
  }
221
264
  // Annotate the CommonJS export names for ESM import in node:
222
265
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/evm/userCurrentBalance.ts"],
4
- "sourcesContent": ["import { parseAbi, type Address } from 'viem';\nimport type { GauntletClient } from '../client';\nimport type { EvmVaultDeployment } from './types';\nimport { ChainMismatchError, UnsupportedProtocolError, VaultNotFoundError } from '../errors';\nimport { getMultiDepositorVault, resolveAeraRuntimeContracts } from './aeraContracts';\nimport { convertUnitsToToken } from './aeraContracts/priceAndFeeCalculator';\nimport { getUserUnitsRefundableUntil } from './aeraContracts/v2';\nimport { provisionerV2Abi } from './abis/provisionerV2';\nimport { ContractVersion } from './types';\nimport { BLOCKS_3_DAYS, CHAIN_NAMES, DEFAULT_BLOCKS_3_DAYS, LOG_PAGE_SIZE } from '../constants';\n\n// Inline as-const ABI items give viem full type inference for args and return types.\nconst DEPOSIT_REQUESTED_V1_ABI = [\n {\n type: 'event',\n name: 'DepositRequested',\n inputs: [\n { type: 'address', name: 'user', indexed: true },\n { type: 'address', name: 'token', indexed: true },\n { type: 'uint256', name: 'tokensIn', indexed: false },\n { type: 'uint256', name: 'minUnitsOut', indexed: false },\n { type: 'uint256', name: 'solverTip', indexed: false },\n { type: 'uint256', name: 'deadline', indexed: false },\n { type: 'uint256', name: 'maxPriceAge', indexed: false },\n { type: 'bool', name: 'isFixedPrice', indexed: false },\n { type: 'bytes32', name: 'depositRequestHash', indexed: false },\n ],\n },\n] as const;\n\nconst REDEEM_REQUESTED_V1_ABI = [\n {\n type: 'event',\n name: 'RedeemRequested',\n inputs: [\n { type: 'address', name: 'user', indexed: true },\n { type: 'address', name: 'token', indexed: true },\n { type: 'uint256', name: 'minTokensOut', indexed: false },\n { type: 'uint256', name: 'unitsIn', indexed: false },\n { type: 'uint256', name: 'solverTip', indexed: false },\n { type: 'uint256', name: 'deadline', indexed: false },\n { type: 'uint256', name: 'maxPriceAge', indexed: false },\n { type: 'bool', name: 'isFixedPrice', indexed: false },\n { type: 'bytes32', name: 'redeemRequestHash', indexed: false },\n ],\n },\n] as const;\n\nconst provisionerV1StateAbi = parseAbi([\n 'function asyncDepositHashes(bytes32 asyncDepositHash) view returns (bool exists)',\n 'function asyncRedeemHashes(bytes32 asyncRedeemHash) view returns (bool exists)',\n]);\n\nexport interface UserCurrentBalanceParams {\n vaultId: string;\n address: Address;\n chainId?: number;\n}\n\nexport interface UserCurrentBalance {\n /** Chain identifier, e.g. \"base\" */\n chain: string;\n /** EVM chain id of the deployment, e.g. 8453 */\n chainId: number;\n token: Address;\n decimals: number;\n /** Assets queued via async deposit, not yet earning */\n pendingDeposit: bigint;\n /** Assets actively earning in the vault */\n balance: bigint;\n /** Assets queued via async withdraw, not yet claimable */\n pendingWithdraw: bigint;\n /** Timestamp until which this account cannot redeem vault units. */\n unitsLockedUntil?: bigint;\n}\n\n// V2 legacy wrapper calls can emit both receiver-aware and legacy events for one request.\n// Keep one row per request hash before state checks and summing pending amounts.\nfunction dedupeByRequestHash<TLog extends { args: { [key: string]: unknown } }>(\n logs: TLog[],\n hashKey: 'depositRequestHash' | 'redeemRequestHash'\n): TLog[] {\n const seen = new Set<unknown>();\n\n return logs.filter((log) => {\n const hash = log.args[hashKey];\n // Drop malformed events and duplicates so one pending request cannot be counted twice.\n if (hash == null || seen.has(hash)) return false;\n seen.add(hash);\n return true;\n });\n}\n\nasync function queryDeploymentBalance(\n client: GauntletClient,\n deployment: EvmVaultDeployment,\n address: Address\n): Promise<UserCurrentBalance> {\n const publicClient = client.getPublicClient(deployment.chainId);\n const token = deployment.supplyToken[0];\n\n const vaultContract = getMultiDepositorVault(publicClient, deployment.vaultAddress);\n const [runtime, units] = await Promise.all([\n resolveAeraRuntimeContracts(publicClient, deployment),\n vaultContract.read.balanceOf([address]),\n ]);\n const provisionerAddress = runtime.provisioner.address;\n const isV2 = runtime.provisioner.version === ContractVersion.V2;\n const unitsLockedUntilPromise = isV2\n ? getUserUnitsRefundableUntil(publicClient, provisionerAddress, address)\n : Promise.resolve(undefined);\n\n const balance = await convertUnitsToToken(\n publicClient,\n runtime.feeCalculator.address,\n runtime.feeCalculator.version,\n deployment.vaultAddress,\n token.address,\n units\n );\n\n // Look back ~3 days for pending async requests\n const currentBlock = await publicClient.getBlockNumber();\n const lookback = BLOCKS_3_DAYS[deployment.chainId] ?? DEFAULT_BLOCKS_3_DAYS;\n const fromBlock = currentBlock > lookback ? currentBlock - lookback : 0n;\n\n // Compute block-range chunks to stay within the 10,000-block RPC limit, then fetch in parallel\n const chunks: [bigint, bigint][] = [];\n for (let cursor = fromBlock; cursor <= currentBlock; cursor += LOG_PAGE_SIZE + 1n) {\n const end = cursor + LOG_PAGE_SIZE <= currentBlock ? cursor + LOG_PAGE_SIZE : currentBlock;\n chunks.push([cursor, end]);\n }\n\n const [depositPages, redeemPages] = await Promise.all([\n Promise.all(\n chunks.map(([from, to]) =>\n isV2\n ? publicClient.getContractEvents({\n address: provisionerAddress,\n abi: provisionerV2Abi,\n eventName: 'DepositRequested',\n args: { receiver: address },\n fromBlock: from,\n toBlock: to,\n })\n : publicClient.getContractEvents({\n address: provisionerAddress,\n abi: DEPOSIT_REQUESTED_V1_ABI,\n eventName: 'DepositRequested',\n args: { user: address },\n fromBlock: from,\n toBlock: to,\n })\n )\n ),\n Promise.all(\n chunks.map(([from, to]) =>\n isV2\n ? publicClient.getContractEvents({\n address: provisionerAddress,\n abi: provisionerV2Abi,\n eventName: 'RedeemRequested',\n args: { user: address },\n fromBlock: from,\n toBlock: to,\n })\n : publicClient.getContractEvents({\n address: provisionerAddress,\n abi: REDEEM_REQUESTED_V1_ABI,\n eventName: 'RedeemRequested',\n args: { user: address },\n fromBlock: from,\n toBlock: to,\n })\n )\n ),\n ]);\n\n const depositLogs = dedupeByRequestHash(depositPages.flat(), 'depositRequestHash');\n const redeemLogs = dedupeByRequestHash(redeemPages.flat(), 'redeemRequestHash');\n\n // Check which requests are still pending on-chain via a single multicall\n const pendingChecks = await publicClient.multicall({\n contracts: [\n ...depositLogs.map((log) => ({\n address: provisionerAddress,\n abi: isV2 ? provisionerV2Abi : provisionerV1StateAbi,\n functionName: isV2 ? ('asyncRequestHashes' as const) : ('asyncDepositHashes' as const),\n args: [log.args.depositRequestHash!] as const,\n })),\n ...redeemLogs.map((log) => ({\n address: provisionerAddress,\n abi: isV2 ? provisionerV2Abi : provisionerV1StateAbi,\n functionName: isV2 ? ('asyncRequestHashes' as const) : ('asyncRedeemHashes' as const),\n args: [log.args.redeemRequestHash!] as const,\n })),\n ],\n allowFailure: false,\n });\n\n const depositChecks = pendingChecks.slice(0, depositLogs.length);\n const redeemChecks = pendingChecks.slice(depositLogs.length);\n\n let pendingDeposit = 0n;\n for (let i = 0; i < depositLogs.length; i++) {\n if (depositChecks[i]) {\n pendingDeposit += depositLogs[i].args.tokensIn ?? 0n;\n }\n }\n\n let pendingWithdrawUnits = 0n;\n for (let i = 0; i < redeemLogs.length; i++) {\n if (redeemChecks[i]) {\n pendingWithdrawUnits += redeemLogs[i].args.unitsIn ?? 0n;\n }\n }\n\n const pendingWithdraw =\n pendingWithdrawUnits > 0n\n ? await convertUnitsToToken(\n publicClient,\n runtime.feeCalculator.address,\n runtime.feeCalculator.version,\n deployment.vaultAddress,\n token.address,\n pendingWithdrawUnits\n )\n : 0n;\n const unitsLockedUntil = await unitsLockedUntilPromise;\n\n return {\n chain: CHAIN_NAMES[deployment.chainId] ?? `chain-${deployment.chainId}`,\n chainId: deployment.chainId,\n token: token.address,\n decimals: token.decimals,\n pendingDeposit,\n balance,\n pendingWithdraw,\n ...(unitsLockedUntil !== undefined ? { unitsLockedUntil } : {}),\n };\n}\n\n/**\n * Returns the current balance breakdown for a user across all EVM deployments of a vault.\n *\n * Queries the vault's on-chain state to split the user's position into three buckets:\n * - `balance` \u2014 assets actively earning inside the vault (converted from vault units to tokens).\n * - `pendingDeposit` \u2014 tokens submitted via async deposit but not yet processed by a solver.\n * - `pendingWithdraw` \u2014 vault units locked in a pending async redeem request (converted to tokens).\n *\n * Only supported for Aera multi-depositor vaults. Pending amounts are detected by scanning\n * the last ~3 days of provisioner events and cross-checking hash existence on-chain.\n *\n * @param client - A configured `GauntletClient` instance with an EVM public client for each\n * chain the vault is deployed on.\n * @param params - Query parameters including `vaultId`, the user `address`, and an optional\n * `chainId` to limit the query to a single deployment.\n * @returns One `UserCurrentBalance` entry per chain queried.\n *\n * @throws {VaultNotFoundError} If the vault ID is not found in the manifest.\n * @throws {UnsupportedProtocolError} If the vault is not an Aera multi-depositor vault.\n * @throws {ChainMismatchError} If `chainId` is specified but no deployment exists for that chain.\n *\n * @example\n * ```ts\n * const balances = await getUserCurrentBalance(client, {\n * vaultId: 'baseUsdcPrime',\n * address: '0xYourWalletAddress',\n * });\n * // [{ chain: 'base', chainId: 8453, token: '0x...', decimals: 6, balance: 100_000_000n, pendingDeposit: 0n, pendingWithdraw: 0n }]\n * ```\n */\nexport async function getUserCurrentBalance(\n client: GauntletClient,\n params: UserCurrentBalanceParams\n): Promise<UserCurrentBalance[]> {\n const manifest = await client.manifest;\n const vaultInfo = manifest.vaults.find((v) => v.vaultId === params.vaultId);\n if (!vaultInfo) throw new VaultNotFoundError(params.vaultId);\n\n const evmDeployments = vaultInfo.deployments.filter(\n (d): d is EvmVaultDeployment => d.chain === 'evm' && d.vaultType === 'multi-depositor'\n );\n\n if (vaultInfo.protocol !== 'aera' || evmDeployments.length === 0) {\n throw new UnsupportedProtocolError(vaultInfo.protocol);\n }\n\n if (params.chainId !== undefined) {\n const deployment = evmDeployments.find((d) => d.chainId === params.chainId);\n if (!deployment) {\n throw new ChainMismatchError(\n `${params.chainId}`,\n evmDeployments.map((d) => `${d.chainId}`).join(', ')\n );\n }\n return [await queryDeploymentBalance(client, deployment, params.address)];\n }\n\n return Promise.all(evmDeployments.map((d) => queryDeploymentBalance(client, d, params.address)));\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { parseAbi, type Address } from 'viem';\nimport type { GauntletClient } from '../client';\nimport type { EvmVaultDeployment } from './types';\nimport {\n ChainMismatchError,\n GauntletSDKError,\n UnsupportedAssetError,\n UnsupportedProtocolError,\n VaultNotFoundError,\n} from '../errors';\nimport { getMultiDepositorVault, resolveAeraRuntimeContracts } from './aeraContracts';\nimport { convertUnitsToToken } from './aeraContracts/priceAndFeeCalculator';\nimport { getUserUnitsRefundableUntil } from './aeraContracts/v2';\nimport { provisionerV2Abi } from './abis/provisionerV2';\nimport { ContractVersion } from './types';\nimport {\n BLOCKS_3_DAYS,\n CHAIN_NAMES,\n DAY,\n DEFAULT_BLOCKS_3_DAYS,\n LOG_PAGE_SIZE,\n} from '../constants';\n\n// Log chunks fetched at once per event type.\nconst LOG_CHUNK_CONCURRENCY = 16;\n\n// Inline as-const ABI items give viem full type inference for args and return types.\nconst DEPOSIT_REQUESTED_V1_ABI = [\n {\n type: 'event',\n name: 'DepositRequested',\n inputs: [\n { type: 'address', name: 'user', indexed: true },\n { type: 'address', name: 'token', indexed: true },\n { type: 'uint256', name: 'tokensIn', indexed: false },\n { type: 'uint256', name: 'minUnitsOut', indexed: false },\n { type: 'uint256', name: 'solverTip', indexed: false },\n { type: 'uint256', name: 'deadline', indexed: false },\n { type: 'uint256', name: 'maxPriceAge', indexed: false },\n { type: 'bool', name: 'isFixedPrice', indexed: false },\n { type: 'bytes32', name: 'depositRequestHash', indexed: false },\n ],\n },\n] as const;\n\nconst REDEEM_REQUESTED_V1_ABI = [\n {\n type: 'event',\n name: 'RedeemRequested',\n inputs: [\n { type: 'address', name: 'user', indexed: true },\n { type: 'address', name: 'token', indexed: true },\n { type: 'uint256', name: 'minTokensOut', indexed: false },\n { type: 'uint256', name: 'unitsIn', indexed: false },\n { type: 'uint256', name: 'solverTip', indexed: false },\n { type: 'uint256', name: 'deadline', indexed: false },\n { type: 'uint256', name: 'maxPriceAge', indexed: false },\n { type: 'bool', name: 'isFixedPrice', indexed: false },\n { type: 'bytes32', name: 'redeemRequestHash', indexed: false },\n ],\n },\n] as const;\n\nconst provisionerV1StateAbi = parseAbi([\n 'function asyncDepositHashes(bytes32 asyncDepositHash) view returns (bool exists)',\n 'function asyncRedeemHashes(bytes32 asyncRedeemHash) view returns (bool exists)',\n]);\n\nexport interface UserCurrentBalanceParams {\n vaultId: string;\n address: Address;\n chainId?: number;\n /** Required for deployments that support multiple assets, ignored otherwise. */\n assetSymbol?: string;\n /**\n * Scan from this block, including expired requests that still hold escrow.\n * Requires `chainId` for a vault with more than one deployment.\n */\n fromBlock?: bigint;\n}\n\nexport interface UserCurrentBalance {\n /** Block used for balances, conversions, and request state. */\n blockNumber: bigint;\n /** First block included in the request scan. Older escrow is outside this result. */\n fromBlock: bigint;\n /** Chain identifier, e.g. \"base\" */\n chain: string;\n /** EVM chain id of the deployment, e.g. 8453 */\n chainId: number;\n token: Address;\n decimals: number;\n /** Assets queued via async deposit, not yet earning */\n pendingDeposit: bigint;\n /** Assets actively earning in the vault */\n balance: bigint;\n /** Assets queued via async withdraw, not yet claimable */\n pendingWithdraw: bigint;\n /** Timestamp until which this account cannot redeem vault units. */\n unitsLockedUntil?: bigint;\n}\n\n// V2 legacy wrapper calls can emit both receiver-aware and legacy events for one request.\n// Keep one row per request hash before state checks and summing pending amounts.\nfunction dedupeByRequestHash<TLog extends { args: { [key: string]: unknown } }>(\n logs: TLog[],\n hashKey: 'depositRequestHash' | 'redeemRequestHash'\n): TLog[] {\n const seen = new Set<unknown>();\n\n return logs.filter((log) => {\n const hash = log.args[hashKey];\n // Drop malformed events and duplicates so one pending request cannot be counted twice.\n if (hash == null || seen.has(hash)) return false;\n seen.add(hash);\n return true;\n });\n}\n\n/** Step back by the expected block count, and widen until the block predates the cutoff. */\nasync function requestScanStart(\n publicClient: ReturnType<GauntletClient['getPublicClient']>,\n chainId: number,\n blockNumber: bigint,\n days: number,\n cutoff: bigint\n): Promise<bigint> {\n let span = ((BLOCKS_3_DAYS[chainId] ?? DEFAULT_BLOCKS_3_DAYS) * BigInt(days)) / 3n;\n for (;;) {\n if (span >= blockNumber) return 0n;\n const start = blockNumber - span;\n const block = await publicClient.getBlock({ blockNumber: start });\n if (block.timestamp <= cutoff) return start;\n span *= 2n;\n }\n}\n\nasync function mapInBatches<T, P extends Promise<unknown>>(\n items: T[],\n size: number,\n fn: (item: T) => P\n): Promise<Awaited<P>[]> {\n const results: Awaited<P>[] = [];\n for (let i = 0; i < items.length; i += size) {\n results.push(...(await Promise.all(items.slice(i, i + size).map(fn))));\n }\n return results;\n}\n\nasync function queryDeploymentBalance(\n client: GauntletClient,\n deployment: EvmVaultDeployment,\n params: UserCurrentBalanceParams\n): Promise<UserCurrentBalance> {\n const publicClient = client.getPublicClient(deployment.chainId);\n const { address } = params;\n const token =\n deployment.supplyToken.length > 1\n ? deployment.supplyToken.find((candidate) => candidate.symbol === params.assetSymbol)\n : deployment.supplyToken[0];\n if (token === undefined)\n throw new UnsupportedAssetError(params.assetSymbol ?? 'unknown', params.vaultId);\n const snapshot = await publicClient.getBlock({ blockTag: 'latest' });\n if (snapshot.number === null) {\n throw new GauntletSDKError('The balance snapshot has no block number');\n }\n const blockNumber = snapshot.number;\n const readOptions = { blockNumber };\n const expirationDays = deployment.expirationDays ?? 3;\n if (!Number.isSafeInteger(expirationDays) || expirationDays <= 0) {\n throw new GauntletSDKError('The request expiration must be a positive integer number of days');\n }\n const scanDays = Math.max(3, expirationDays);\n const cutoff = snapshot.timestamp - BigInt(DAY) * BigInt(scanDays);\n const fromBlock =\n params.fromBlock ??\n (await requestScanStart(publicClient, deployment.chainId, blockNumber, scanDays, cutoff));\n if (fromBlock < 0n || fromBlock > blockNumber) {\n throw new GauntletSDKError('The request scan range is invalid');\n }\n\n const vaultContract = getMultiDepositorVault(publicClient, deployment.vaultAddress);\n const [runtime, units] = await Promise.all([\n resolveAeraRuntimeContracts(publicClient, deployment, readOptions),\n vaultContract.read.balanceOf([address], readOptions),\n ]);\n const provisionerAddress = runtime.provisioner.address;\n const isV2 = runtime.provisioner.version === ContractVersion.V2;\n const unitsLockedUntilPromise = isV2\n ? getUserUnitsRefundableUntil(publicClient, provisionerAddress, address, readOptions)\n : Promise.resolve(undefined);\n\n const balance = await convertUnitsToToken(\n publicClient,\n runtime.feeCalculator.address,\n runtime.feeCalculator.version,\n deployment.vaultAddress,\n token.address,\n units,\n readOptions\n );\n\n // Compute block-range chunks to stay within the 10,000-block RPC limit, then fetch in bounded batches\n const chunks: [bigint, bigint][] = [];\n for (let cursor = fromBlock; cursor <= blockNumber; cursor += LOG_PAGE_SIZE + 1n) {\n const end = cursor + LOG_PAGE_SIZE <= blockNumber ? cursor + LOG_PAGE_SIZE : blockNumber;\n chunks.push([cursor, end]);\n }\n\n // Each map keeps LOG_CHUNK_CONCURRENCY queries in flight.\n const [depositPages, redeemPages] = await Promise.all([\n mapInBatches(chunks, LOG_CHUNK_CONCURRENCY, ([from, to]) =>\n isV2\n ? publicClient.getContractEvents({\n address: provisionerAddress,\n abi: provisionerV2Abi,\n eventName: 'DepositRequested',\n args: { receiver: address, token: token.address },\n fromBlock: from,\n toBlock: to,\n })\n : publicClient.getContractEvents({\n address: provisionerAddress,\n abi: DEPOSIT_REQUESTED_V1_ABI,\n eventName: 'DepositRequested',\n args: { user: address, token: token.address },\n fromBlock: from,\n toBlock: to,\n })\n ),\n mapInBatches(chunks, LOG_CHUNK_CONCURRENCY, ([from, to]) =>\n isV2\n ? publicClient.getContractEvents({\n address: provisionerAddress,\n abi: provisionerV2Abi,\n eventName: 'RedeemRequested',\n args: { user: address, token: token.address },\n fromBlock: from,\n toBlock: to,\n })\n : publicClient.getContractEvents({\n address: provisionerAddress,\n abi: REDEEM_REQUESTED_V1_ABI,\n eventName: 'RedeemRequested',\n args: { user: address, token: token.address },\n fromBlock: from,\n toBlock: to,\n })\n ),\n ]);\n\n const depositLogs = dedupeByRequestHash(depositPages.flat(), 'depositRequestHash');\n const redeemLogs = dedupeByRequestHash(redeemPages.flat(), 'redeemRequestHash');\n\n // Check which requests are still pending on-chain via a single multicall\n const pendingChecks = await publicClient.multicall({\n contracts: [\n ...depositLogs.map((log) => ({\n address: provisionerAddress,\n abi: isV2 ? provisionerV2Abi : provisionerV1StateAbi,\n functionName: isV2 ? ('asyncRequestHashes' as const) : ('asyncDepositHashes' as const),\n args: [log.args.depositRequestHash!] as const,\n })),\n ...redeemLogs.map((log) => ({\n address: provisionerAddress,\n abi: isV2 ? provisionerV2Abi : provisionerV1StateAbi,\n functionName: isV2 ? ('asyncRequestHashes' as const) : ('asyncRedeemHashes' as const),\n args: [log.args.redeemRequestHash!] as const,\n })),\n ],\n allowFailure: false,\n blockNumber,\n });\n\n const depositChecks = pendingChecks.slice(0, depositLogs.length);\n const redeemChecks = pendingChecks.slice(depositLogs.length);\n\n let pendingDeposit = 0n;\n for (let i = 0; i < depositLogs.length; i++) {\n if (depositChecks[i]) {\n pendingDeposit += depositLogs[i].args.tokensIn ?? 0n;\n }\n }\n\n let pendingWithdrawUnits = 0n;\n for (let i = 0; i < redeemLogs.length; i++) {\n if (redeemChecks[i]) {\n pendingWithdrawUnits += redeemLogs[i].args.unitsIn ?? 0n;\n }\n }\n\n const pendingWithdraw =\n pendingWithdrawUnits > 0n\n ? await convertUnitsToToken(\n publicClient,\n runtime.feeCalculator.address,\n runtime.feeCalculator.version,\n deployment.vaultAddress,\n token.address,\n pendingWithdrawUnits,\n readOptions\n )\n : 0n;\n const unitsLockedUntil = await unitsLockedUntilPromise;\n\n return {\n blockNumber,\n fromBlock,\n chain: CHAIN_NAMES[deployment.chainId] ?? `chain-${deployment.chainId}`,\n chainId: deployment.chainId,\n token: token.address,\n decimals: token.decimals,\n pendingDeposit,\n balance,\n pendingWithdraw,\n ...(unitsLockedUntil !== undefined ? { unitsLockedUntil } : {}),\n };\n}\n\n/**\n * Returns the current balance breakdown for a user across all EVM deployments of a vault.\n *\n * Queries the vault's on-chain state to split the user's position into three buckets:\n * - `balance` \u2014 assets actively earning inside the vault (converted from vault units to tokens).\n * - `pendingDeposit` \u2014 tokens submitted via async deposit but not yet processed by a solver.\n * - `pendingWithdraw` \u2014 vault units locked in a pending async redeem request (converted to tokens).\n *\n * Only supported for Aera multi-depositor vaults. Pending amounts are detected by scanning\n * the configured request lifetime, with a minimum of three days. Set `fromBlock` (with `chainId`\n * on a multi-chain vault) for older escrow.\n * All state reads use one block. The returned range identifies the scanned history.\n *\n * @param client - A configured `GauntletClient` instance with an EVM public client for each\n * chain the vault is deployed on.\n * @param params - Query parameters including `vaultId`, the user `address`, and an optional\n * `chainId` to limit the query to a single deployment.\n * @returns One `UserCurrentBalance` entry per chain queried.\n *\n * @throws {VaultNotFoundError} If the vault ID is not found in the manifest.\n * @throws {UnsupportedProtocolError} If the vault is not an Aera multi-depositor vault.\n * @throws {ChainMismatchError} If `chainId` is specified but no deployment exists for that chain.\n * @throws {UnsupportedAssetError} If a multi-asset deployment gets no matching `assetSymbol`.\n *\n * @example\n * ```ts\n * const balances = await getUserCurrentBalance(client, {\n * vaultId: 'baseUsdcPrime',\n * address: '0xYourWalletAddress',\n * });\n * // [{ chain: 'base', chainId: 8453, token: '0x...', decimals: 6, balance: 100_000_000n, pendingDeposit: 0n, pendingWithdraw: 0n }]\n * ```\n */\nexport async function getUserCurrentBalance(\n client: GauntletClient,\n params: UserCurrentBalanceParams\n): Promise<UserCurrentBalance[]> {\n params = { ...params };\n const manifest = await client.manifest;\n const vaultInfo = manifest.vaults.find((v) => v.vaultId === params.vaultId);\n if (!vaultInfo) throw new VaultNotFoundError(params.vaultId);\n\n const evmDeployments = vaultInfo.deployments.filter(\n (d): d is EvmVaultDeployment => d.chain === 'evm' && d.vaultType === 'multi-depositor'\n );\n\n if (vaultInfo.protocol !== 'aera' || evmDeployments.length === 0) {\n throw new UnsupportedProtocolError(vaultInfo.protocol);\n }\n\n if (params.chainId !== undefined) {\n const deployment = evmDeployments.find((d) => d.chainId === params.chainId);\n if (!deployment) {\n throw new ChainMismatchError(\n `${params.chainId}`,\n evmDeployments.map((d) => `${d.chainId}`).join(', ')\n );\n }\n return [await queryDeploymentBalance(client, deployment, params)];\n }\n if (params.fromBlock !== undefined && evmDeployments.length > 1) {\n throw new GauntletSDKError('fromBlock requires chainId for a vault with several deployments');\n }\n\n return Promise.all(evmDeployments.map((d) => queryDeploymentBalance(client, d, params)));\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }