@owney/sdk 0.7.25-beta.16 → 0.7.25-beta.18

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.
package/dist/index.cjs CHANGED
@@ -1574,6 +1574,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
1574
1574
  earningsRefreshes = /* @__PURE__ */ new Map();
1575
1575
  earningsSnapshot = null;
1576
1576
  earningsGeneration = 0;
1577
+ balanceSnapshots = /* @__PURE__ */ new WeakMap();
1577
1578
  constructor(apiKey, rpcUrls, referralSource) {
1578
1579
  this.rpcUrls = resolveRpcUrls(rpcUrls);
1579
1580
  this.sdk = new import_sdk.ZyfaiSDK({
@@ -1777,7 +1778,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
1777
1778
  * chain/account switch fires the provider's `accountsChanged` →
1778
1779
  * `disconnectAccount` (nulls walletClient + authenticatedUserId) while our
1779
1780
  * own `connectAuth` guard still believes this chain is connected and
1780
- * early-returns. Without this, authenticated calls (depositFunds,
1781
+ * early-returns. Without this, authenticated calls (sendDeposit,
1781
1782
  * withdrawFunds) fail with "No account connected".
1782
1783
  */
1783
1784
  async ensureConnected(state, chainId) {
@@ -2399,7 +2400,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2399
2400
  return { txHash, smartWallet, amount, evidence: evidence2 };
2400
2401
  }
2401
2402
  await this.ensureWalletDeployed(this.getAddress(), validChainId);
2402
- const raw2 = await this.sdk.depositFunds(
2403
+ const raw2 = await this.sdk.sendDeposit(
2403
2404
  this.getAddress(),
2404
2405
  validChainId,
2405
2406
  amount,
@@ -2415,7 +2416,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2415
2416
  intendedAmount: amount,
2416
2417
  txHash: raw2.txHash,
2417
2418
  transfer: "unknown",
2418
- registration: "unknown",
2419
+ registration: raw2.registration ? "confirmed" : "unknown",
2419
2420
  delivery: "not-applicable"
2420
2421
  };
2421
2422
  notifyFunding(onProgress, evidence);
@@ -2723,10 +2724,37 @@ var ZyfaiAgent = class _ZyfaiAgent {
2723
2724
  }
2724
2725
  async getBalances(state, chainId) {
2725
2726
  const requestedAt = Date.now();
2727
+ const generation = this.earningsGeneration;
2726
2728
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
2727
2729
  const raw2 = await this.sdk.getPortfolio(this.getAddress());
2728
2730
  const balance = mapBalances(raw2, validChainId, smartWallet);
2729
- return { ...balance, readMetadata: balance.readMetadata?.map((read2) => ({ ...read2, requestedAt })) };
2731
+ const reads = balance.readMetadata?.map((read2) => ({ ...read2, requestedAt })) ?? [];
2732
+ for (const asset of SupportedAssets.filter((item) => item.chainId === chainId)) {
2733
+ if (!reads.some((read2) => read2.chainId === chainId && read2.asset === asset.symbol) && hasEmptyWithdrawalSnapshot(raw2, chainId, asset.symbol)) {
2734
+ reads.push({ chainId, asset: asset.symbol, requestedAt, fetchedAt: Date.now(), positionsStatus: "available" });
2735
+ }
2736
+ }
2737
+ const result = { ...balance, readMetadata: reads };
2738
+ for (const read2 of reads) this.balanceSnapshots.set(read2, { raw: raw2, generation, owner: state.walletAddress.toLowerCase() });
2739
+ return result;
2740
+ }
2741
+ async verifyWithdrawalBalance(state, evidence, balance) {
2742
+ const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
2743
+ const snapshot = read2 && this.balanceSnapshots.get(read2);
2744
+ const asset = SupportedAssets.find((item) => item.chainId === evidence.chainId && item.symbol === evidence.token);
2745
+ if (!snapshot || snapshot.generation !== this.earningsGeneration || snapshot.owner !== state.walletAddress.toLowerCase() || !read2 || !asset || !evidence.txHash || !evidence.blockNumber || !balance.smartWallet || balance.smartWallet.toLowerCase() !== evidence.agentWallet?.toLowerCase() || !hasEmptyWithdrawalSnapshot(snapshot.raw, evidence.chainId, evidence.token)) return void 0;
2746
+ const client = this.getPublicClient(evidence.chainId);
2747
+ const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
2748
+ if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
2749
+ const idle = await client.readContract({
2750
+ address: asset.address,
2751
+ abi: import_viem4.erc20Abi,
2752
+ functionName: "balanceOf",
2753
+ args: [balance.smartWallet],
2754
+ blockNumber
2755
+ });
2756
+ if (idle !== 0n || snapshot.generation !== this.earningsGeneration || this.connectedAddress?.toLowerCase() !== snapshot.owner || this.connectedChainId !== evidence.chainId) return void 0;
2757
+ return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
2730
2758
  }
2731
2759
  earningsKey(state, chainId, smartWallet) {
2732
2760
  return JSON.stringify([
@@ -2925,7 +2953,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2925
2953
  };
2926
2954
 
2927
2955
  // src/agents/yieldseeker/yieldseeker.agent.ts
2928
- var import_viem11 = require("viem");
2956
+ var import_viem12 = require("viem");
2929
2957
  var import_chains4 = require("viem/chains");
2930
2958
 
2931
2959
  // src/lib/chain-guard.ts
@@ -3709,6 +3737,7 @@ function mapYieldseekerBalances(contexts) {
3709
3737
  chainId: context.agent.chainId,
3710
3738
  asset: context.asset,
3711
3739
  fetchedAt: context.fetchedAt,
3740
+ requestedAt: context.requestedAt,
3712
3741
  readVersion: context.readVersion,
3713
3742
  providerUpdatedAt: context.snapshot.updatedDate,
3714
3743
  snapshotId: String(context.snapshot.agentWalletSnapshotId),
@@ -4086,13 +4115,59 @@ function mapYieldseekerAgentApy(options, days) {
4086
4115
  };
4087
4116
  }
4088
4117
 
4089
- // src/agents/yieldseeker/yieldseeker.wallet-version.ts
4118
+ // src/lib/remaining-vault-balance.ts
4090
4119
  var import_viem9 = require("viem");
4120
+ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber) {
4121
+ const addresses = [...new Set(vaults.map((value) => value.toLowerCase()))];
4122
+ if (addresses.length > 64) return void 0;
4123
+ const batches = [];
4124
+ for (let index = 0; index < addresses.length; index += 10) batches.push(addresses.slice(index, index + 10));
4125
+ const values = await Promise.all(batches.map(async (batch) => {
4126
+ const balances = await client.multicall({
4127
+ blockNumber,
4128
+ allowFailure: true,
4129
+ contracts: batch.map((address) => ({
4130
+ address: (0, import_viem9.getAddress)(address),
4131
+ abi: import_viem9.erc20Abi,
4132
+ functionName: "balanceOf",
4133
+ args: [wallet]
4134
+ }))
4135
+ });
4136
+ if (balances.length !== batch.length) return void 0;
4137
+ const funded = [];
4138
+ for (let index = 0; index < batch.length; index++) {
4139
+ const result = balances[index];
4140
+ if (result?.status !== "success" || typeof result.result !== "bigint" || result.result < 0n) return void 0;
4141
+ if (result.result > 0n) funded.push({ address: (0, import_viem9.getAddress)(batch[index]), shares: result.result });
4142
+ }
4143
+ if (!funded.length) return 0n;
4144
+ const valuations = await client.multicall({
4145
+ blockNumber,
4146
+ allowFailure: true,
4147
+ contracts: funded.flatMap(({ address, shares }) => [
4148
+ { address, abi: import_viem9.erc4626Abi, functionName: "asset" },
4149
+ { address, abi: import_viem9.erc4626Abi, functionName: "convertToAssets", args: [shares] }
4150
+ ])
4151
+ });
4152
+ if (valuations.length !== funded.length * 2) return void 0;
4153
+ let total = 0n;
4154
+ for (let index = 0; index < funded.length; index++) {
4155
+ const underlying = valuations[index * 2], value = valuations[index * 2 + 1];
4156
+ if (underlying?.status !== "success" || typeof underlying.result !== "string" || underlying.result.toLowerCase() !== asset.toLowerCase() || value?.status !== "success" || typeof value.result !== "bigint" || value.result < 0n) return void 0;
4157
+ total += value.result;
4158
+ }
4159
+ return total;
4160
+ }));
4161
+ return values.some((value) => value === void 0) ? void 0 : values.reduce((sum, value) => sum + value, 0n);
4162
+ }
4163
+
4164
+ // src/agents/yieldseeker/yieldseeker.wallet-version.ts
4165
+ var import_viem10 = require("viem");
4091
4166
  var YIELDSEEKER_FACTORY = "0x9c7410a0faCAC60850C46eE5b58B518daec95130";
4092
4167
  var YIELDSEEKER_V1_IMPLEMENTATION = "0x32403455357589523435dB18b414057D7cE05051";
4093
4168
  var YIELDSEEKER_V2_IMPLEMENTATION = "0x613Db9c924ADB7A7A90c11b02Cce20c913E3Fe50";
4094
4169
  var ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
4095
- var walletAbi = (0, import_viem9.parseAbi)([
4170
+ var walletAbi = (0, import_viem10.parseAbi)([
4096
4171
  "function owner() view returns (address)",
4097
4172
  "function ownerAgentIndex() view returns (uint256)",
4098
4173
  "function baseAsset() view returns (address)",
@@ -4100,7 +4175,7 @@ var walletAbi = (0, import_viem9.parseAbi)([
4100
4175
  "function upgradeToLatest()",
4101
4176
  "event Upgraded(address indexed implementation)"
4102
4177
  ]);
4103
- var factoryAbi = (0, import_viem9.parseAbi)([
4178
+ var factoryAbi = (0, import_viem10.parseAbi)([
4104
4179
  "function userWallets(address owner, uint256 index) view returns (address)",
4105
4180
  "function agentWalletImplementation() view returns (address)"
4106
4181
  ]);
@@ -4108,9 +4183,9 @@ function yieldseekerOwnerPath(code) {
4108
4183
  return !code || code === "0x" || /^0xef0100[0-9a-f]{40}$/i.test(code) ? "eoa" : "smart";
4109
4184
  }
4110
4185
  async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNumber) {
4111
- const agentWallet = (0, import_viem9.getAddress)(wallet);
4112
- const expectedOwner = (0, import_viem9.getAddress)(owner);
4113
- const expectedAsset = (0, import_viem9.getAddress)(asset);
4186
+ const agentWallet = (0, import_viem10.getAddress)(wallet);
4187
+ const expectedOwner = (0, import_viem10.getAddress)(owner);
4188
+ const expectedAsset = (0, import_viem10.getAddress)(asset);
4114
4189
  const [code, ownerCode, slot, actualOwner, index, actualAsset, actualFactory, latest] = await Promise.all([
4115
4190
  client.getBytecode({ address: agentWallet, blockNumber }),
4116
4191
  client.getBytecode({ address: expectedOwner, blockNumber }),
@@ -4124,7 +4199,7 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
4124
4199
  if (!code || code === "0x" || !slot || /^0x0+$/.test(slot)) {
4125
4200
  throw new Error("Yieldseeker wallet is not a deployed ERC1967 proxy");
4126
4201
  }
4127
- const implementation = (0, import_viem9.getAddress)(`0x${slot.slice(-40)}`);
4202
+ const implementation = (0, import_viem10.getAddress)(`0x${slot.slice(-40)}`);
4128
4203
  const mapped = await client.readContract({
4129
4204
  address: YIELDSEEKER_FACTORY,
4130
4205
  abi: factoryAbi,
@@ -4132,8 +4207,8 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
4132
4207
  args: [expectedOwner, index],
4133
4208
  blockNumber
4134
4209
  });
4135
- const verified = (0, import_viem9.isAddressEqual)(actualOwner, expectedOwner) && (0, import_viem9.isAddressEqual)(actualAsset, expectedAsset) && (0, import_viem9.isAddressEqual)(actualFactory, YIELDSEEKER_FACTORY) && (0, import_viem9.isAddressEqual)(mapped, agentWallet);
4136
- const version = !verified ? "unknown" : (0, import_viem9.isAddressEqual)(implementation, YIELDSEEKER_V2_IMPLEMENTATION) ? "v2" : (0, import_viem9.isAddressEqual)(implementation, YIELDSEEKER_V1_IMPLEMENTATION) ? "v1" : "unknown";
4210
+ const verified = (0, import_viem10.isAddressEqual)(actualOwner, expectedOwner) && (0, import_viem10.isAddressEqual)(actualAsset, expectedAsset) && (0, import_viem10.isAddressEqual)(actualFactory, YIELDSEEKER_FACTORY) && (0, import_viem10.isAddressEqual)(mapped, agentWallet);
4211
+ const version = !verified ? "unknown" : (0, import_viem10.isAddressEqual)(implementation, YIELDSEEKER_V2_IMPLEMENTATION) ? "v2" : (0, import_viem10.isAddressEqual)(implementation, YIELDSEEKER_V1_IMPLEMENTATION) ? "v1" : "unknown";
4137
4212
  return {
4138
4213
  agentWallet,
4139
4214
  owner: actualOwner,
@@ -4142,13 +4217,13 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
4142
4217
  implementation,
4143
4218
  version,
4144
4219
  verified,
4145
- upgradeAvailable: version === "v1" && (0, import_viem9.isAddressEqual)(latest, YIELDSEEKER_V2_IMPLEMENTATION)
4220
+ upgradeAvailable: version === "v1" && (0, import_viem10.isAddressEqual)(latest, YIELDSEEKER_V2_IMPLEMENTATION)
4146
4221
  };
4147
4222
  }
4148
4223
  var YIELDSEEKER_UPGRADE_ABI = walletAbi;
4149
4224
 
4150
4225
  // src/agents/yieldseeker/yieldseeker.sponsored-withdraw.ts
4151
- var import_viem10 = require("viem");
4226
+ var import_viem11 = require("viem");
4152
4227
  var import_account_abstraction2 = require("viem/account-abstraction");
4153
4228
  var import_accounts = require("viem/accounts");
4154
4229
  var import_chains3 = require("viem/chains");
@@ -4198,6 +4273,14 @@ function sponsorError(message, safeToFallback, details = {}) {
4198
4273
  "yieldseeker"
4199
4274
  );
4200
4275
  }
4276
+ function assertIntentFresh(expiresAt) {
4277
+ if (!Number.isFinite(expiresAt) || Date.now() + 5e3 >= expiresAt * 1e3)
4278
+ throw sponsorError(
4279
+ "The withdrawal sponsorship request expired. Please try again.",
4280
+ true,
4281
+ { failureCode: "SPONSOR_INTENT_EXPIRED" }
4282
+ );
4283
+ }
4201
4284
  function providerReason(value) {
4202
4285
  if (typeof value !== "string") return void 0;
4203
4286
  return value.replace(/https?:\/\/\S+/gi, "[url]").replace(/0x[0-9a-fA-F]{40,}/g, "[hex]").replace(/[A-Za-z0-9_+=\/-]{48,}/g, "[token]").slice(0, 300);
@@ -4227,7 +4310,7 @@ function rpcDiagnostics(data) {
4227
4310
  details.revertName = data.revertName;
4228
4311
  if (typeof data?.aaCode === "string" && /^AA[0-9]{2}$/.test(data.aaCode)) details.aaCode = data.aaCode;
4229
4312
  if (typeof data?.panicCode === "string" && /^0x[0-9a-fA-F]{1,2}$/.test(data.panicCode)) {
4230
- const panicCode = (0, import_viem10.toHex)(BigInt(data.panicCode));
4313
+ const panicCode = (0, import_viem11.toHex)(BigInt(data.panicCode));
4231
4314
  if (["0x0", "0x1", "0x11", "0x12", "0x21", "0x22", "0x31", "0x32", "0x41", "0x51"].includes(panicCode))
4232
4315
  details.panicCode = panicCode;
4233
4316
  }
@@ -4447,14 +4530,14 @@ async function submitEoa(input) {
4447
4530
  throw sponsorError("Base did not return EIP-1559 gas fees.", true);
4448
4531
  let operation = {
4449
4532
  sender: input.agentWallet,
4450
- nonce: (0, import_viem10.toHex)(nonce),
4533
+ nonce: (0, import_viem11.toHex)(nonce),
4451
4534
  initCode: "0x",
4452
4535
  callData: input.callData,
4453
- callGasLimit: (0, import_viem10.toHex)(3e5),
4454
- verificationGasLimit: (0, import_viem10.toHex)(3e5),
4455
- preVerificationGas: (0, import_viem10.toHex)(6e4),
4456
- maxFeePerGas: (0, import_viem10.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
4457
- maxPriorityFeePerGas: (0, import_viem10.toHex)(fees.maxPriorityFeePerGas),
4536
+ callGasLimit: (0, import_viem11.toHex)(3e5),
4537
+ verificationGasLimit: (0, import_viem11.toHex)(3e5),
4538
+ preVerificationGas: (0, import_viem11.toHex)(6e4),
4539
+ maxFeePerGas: (0, import_viem11.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
4540
+ maxPriorityFeePerGas: (0, import_viem11.toHex)(fees.maxPriorityFeePerGas),
4458
4541
  paymasterAndData: "0x",
4459
4542
  signature: "0x"
4460
4543
  };
@@ -4462,7 +4545,7 @@ async function submitEoa(input) {
4462
4545
  const stub = await rpc(
4463
4546
  input.rpcUrl,
4464
4547
  "pm_getPaymasterStubData",
4465
- [operation, ENTRY_POINT_V06, (0, import_viem10.toHex)(8453), {}],
4548
+ [operation, ENTRY_POINT_V06, (0, import_viem11.toHex)(8453), {}],
4466
4549
  "prepare"
4467
4550
  );
4468
4551
  if (!stub.paymasterAndData?.startsWith("0x"))
@@ -4477,7 +4560,7 @@ async function submitEoa(input) {
4477
4560
  const final = await rpc(
4478
4561
  input.rpcUrl,
4479
4562
  "pm_getPaymasterData",
4480
- [operation, ENTRY_POINT_V06, (0, import_viem10.toHex)(8453), {}],
4563
+ [operation, ENTRY_POINT_V06, (0, import_viem11.toHex)(8453), {}],
4481
4564
  "prepare"
4482
4565
  );
4483
4566
  if (!final.paymasterAndData?.startsWith("0x"))
@@ -4486,14 +4569,16 @@ async function submitEoa(input) {
4486
4569
  }
4487
4570
  const userOpHash = operationHash(operation);
4488
4571
  await assertOwnerSession(input.state, input.owner);
4489
- const wallet = (0, import_viem10.createWalletClient)({
4572
+ assertIntentFresh(input.expiresAt);
4573
+ const wallet = (0, import_viem11.createWalletClient)({
4490
4574
  account: input.owner,
4491
4575
  chain: import_chains3.base,
4492
- transport: (0, import_viem10.custom)(input.state.provider)
4576
+ transport: (0, import_viem11.custom)(input.state.provider)
4493
4577
  });
4494
4578
  const signature = await wallet.signMessage({ message: { raw: userOpHash } });
4495
4579
  operation = { ...operation, signature };
4496
4580
  await assertOwnerSession(input.state, input.owner);
4581
+ assertIntentFresh(input.expiresAt);
4497
4582
  const userOperation = {
4498
4583
  sender: operation.sender,
4499
4584
  nonce: operation.nonce,
@@ -4566,12 +4651,13 @@ async function submitSmart(input) {
4566
4651
  } catch {
4567
4652
  throw sponsorError("This account cannot check paymaster support on Base.", true);
4568
4653
  }
4569
- const supportsPaymaster = capabilities?.[(0, import_viem10.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
4654
+ const supportsPaymaster = capabilities?.[(0, import_viem11.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
4570
4655
  if (supportsPaymaster !== true)
4571
4656
  throw sponsorError("This account cannot use a paymaster on Base.", true);
4572
4657
  await assertOwnerSession(input.state, input.owner);
4573
4658
  let sent;
4574
- const requestedId = (0, import_viem10.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
4659
+ assertIntentFresh(input.expiresAt);
4660
+ const requestedId = (0, import_viem11.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
4575
4661
  savePending(input.onPending, { callsId: requestedId }, true);
4576
4662
  await checkpoint(input.onBeforeSubmission, { callsId: requestedId });
4577
4663
  try {
@@ -4580,7 +4666,7 @@ async function submitSmart(input) {
4580
4666
  params: [{
4581
4667
  version: "2.0.0",
4582
4668
  from: input.owner,
4583
- chainId: (0, import_viem10.toHex)(8453),
4669
+ chainId: (0, import_viem11.toHex)(8453),
4584
4670
  id: requestedId,
4585
4671
  atomicRequired: false,
4586
4672
  calls: [{ to: input.agentWallet, value: "0x0", data: input.callData }],
@@ -4655,7 +4741,7 @@ async function submitSmart(input) {
4655
4741
  );
4656
4742
  }
4657
4743
  async function submitYieldseekerSponsoredWithdrawal(input) {
4658
- const owner = (0, import_viem10.getAddress)(input.state.walletAddress);
4744
+ const owner = (0, import_viem11.getAddress)(input.state.walletAddress);
4659
4745
  const { intent, rpcUrl } = await requestIntent({
4660
4746
  apiKey: input.apiKey,
4661
4747
  routingApiBaseUrl: input.routingApiBaseUrl,
@@ -4669,11 +4755,12 @@ async function submitYieldseekerSponsoredWithdrawal(input) {
4669
4755
  action: "withdraw",
4670
4756
  refreshYieldseekerSignature: input.refreshYieldseekerSignature
4671
4757
  });
4672
- const args = { ...input, owner, rpcUrl };
4758
+ assertIntentFresh(intent.expiresAt);
4759
+ const args = { ...input, owner, rpcUrl, expiresAt: intent.expiresAt };
4673
4760
  return intent.ownerPath === "eoa" ? submitEoa(args) : submitSmart(args);
4674
4761
  }
4675
4762
  async function submitYieldseekerSponsoredUpgrade(input) {
4676
- const owner = (0, import_viem10.getAddress)(input.state.walletAddress);
4763
+ const owner = (0, import_viem11.getAddress)(input.state.walletAddress);
4677
4764
  const { intent, rpcUrl } = await requestIntent({
4678
4765
  apiKey: input.apiKey,
4679
4766
  routingApiBaseUrl: input.routingApiBaseUrl,
@@ -4689,7 +4776,8 @@ async function submitYieldseekerSponsoredUpgrade(input) {
4689
4776
  });
4690
4777
  if (intent.ownerPath !== "smart")
4691
4778
  throw sponsorError("V1 upgrade sponsorship requires a Base Account owner.", true);
4692
- return submitSmart({ ...input, owner, rpcUrl });
4779
+ assertIntentFresh(intent.expiresAt);
4780
+ return submitSmart({ ...input, owner, rpcUrl, expiresAt: intent.expiresAt });
4693
4781
  }
4694
4782
 
4695
4783
  // src/agents/yieldseeker/yieldseeker.agent.ts
@@ -4790,6 +4878,8 @@ var YieldseekerAgent = class {
4790
4878
  transactionExecutor;
4791
4879
  unwindReceiptWaiter;
4792
4880
  agentContexts = /* @__PURE__ */ new Map();
4881
+ balanceContexts = /* @__PURE__ */ new WeakMap();
4882
+ balanceVaults = /* @__PURE__ */ new Map();
4793
4883
  users = /* @__PURE__ */ new Map();
4794
4884
  pendingAgents = /* @__PURE__ */ new Map();
4795
4885
  pendingWalletContexts = /* @__PURE__ */ new Map();
@@ -4835,8 +4925,8 @@ var YieldseekerAgent = class {
4835
4925
  if (useCachedV2 && cached && Date.now() - cached.at < 15 * 6e4) return { ...cached.status };
4836
4926
  const status = await readYieldseekerWalletStatus(
4837
4927
  this.getReceiptClient(),
4838
- (0, import_viem11.getAddress)(context.wallet.walletAddress),
4839
- (0, import_viem11.getAddress)(state.walletAddress),
4928
+ (0, import_viem12.getAddress)(context.wallet.walletAddress),
4929
+ (0, import_viem12.getAddress)(state.walletAddress),
4840
4930
  YIELDSEEKER_ASSET_METADATA[asset].address
4841
4931
  );
4842
4932
  this.rememberWalletStatus(key2, status);
@@ -4866,12 +4956,12 @@ var YieldseekerAgent = class {
4866
4956
  const pendingKey2 = `owney.yieldseeker.upgrade:${before.owner.toLowerCase()}:${before.agentWallet.toLowerCase()}`;
4867
4957
  const confirmUpgrade = async (hash, receipt2) => {
4868
4958
  this.withdrawalVersionCache.delete(versionKey);
4869
- const upgradeTopic = (0, import_viem11.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
4959
+ const upgradeTopic = (0, import_viem12.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
4870
4960
  const lastUpgrade = receipt2?.logs.filter((log) => log.address.toLowerCase() === before.agentWallet.toLowerCase() && log.topics[0] === upgradeTopic).at(-1);
4871
4961
  const expectedUpgrade = (() => {
4872
4962
  if (!lastUpgrade || lastUpgrade.removed) return false;
4873
4963
  try {
4874
- const event = (0, import_viem11.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
4964
+ const event = (0, import_viem12.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
4875
4965
  return event.args.implementation.toLowerCase() === YIELDSEEKER_V2_IMPLEMENTATION.toLowerCase();
4876
4966
  } catch {
4877
4967
  return false;
@@ -4989,7 +5079,7 @@ var YieldseekerAgent = class {
4989
5079
  { version: before.version },
4990
5080
  this.id
4991
5081
  );
4992
- const data = (0, import_viem11.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
5082
+ const data = (0, import_viem12.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
4993
5083
  let txHash;
4994
5084
  let receipt;
4995
5085
  if (gasMode === "sponsored") {
@@ -5032,7 +5122,7 @@ var YieldseekerAgent = class {
5032
5122
  }
5033
5123
  } else {
5034
5124
  txHash = await this.submitTransaction(state, chainId, {
5035
- from: (0, import_viem11.getAddress)(state.walletAddress),
5125
+ from: (0, import_viem12.getAddress)(state.walletAddress),
5036
5126
  to: before.agentWallet,
5037
5127
  data,
5038
5128
  value: "0",
@@ -5055,6 +5145,7 @@ var YieldseekerAgent = class {
5055
5145
  }
5056
5146
  this.users.clear();
5057
5147
  this.agentContexts.clear();
5148
+ this.balanceVaults.clear();
5058
5149
  this.pendingAgents.clear();
5059
5150
  this.pendingWalletContexts.clear();
5060
5151
  this.readCache.clear();
@@ -5118,12 +5209,12 @@ var YieldseekerAgent = class {
5118
5209
  } else {
5119
5210
  try {
5120
5211
  txHash = await this.submitTransaction(state, chainId, {
5121
- from: (0, import_viem11.getAddress)(state.walletAddress),
5212
+ from: (0, import_viem12.getAddress)(state.walletAddress),
5122
5213
  to: YIELDSEEKER_ASSET_METADATA[asset].address,
5123
- data: (0, import_viem11.encodeFunctionData)({
5124
- abi: import_viem11.erc20Abi,
5214
+ data: (0, import_viem12.encodeFunctionData)({
5215
+ abi: import_viem12.erc20Abi,
5125
5216
  functionName: "transfer",
5126
- args: [(0, import_viem11.getAddress)(context.wallet.walletAddress), BigInt(amount)]
5217
+ args: [(0, import_viem12.getAddress)(context.wallet.walletAddress), BigInt(amount)]
5127
5218
  }),
5128
5219
  value: "0",
5129
5220
  chainId
@@ -5257,7 +5348,7 @@ var YieldseekerAgent = class {
5257
5348
  );
5258
5349
  const positionsRead = this.readWithdrawalPositions(state, chainId, context);
5259
5350
  const metadata = YIELDSEEKER_ASSET_METADATA[asset];
5260
- const agentWallet = (0, import_viem11.getAddress)(context.wallet.walletAddress);
5351
+ const agentWallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
5261
5352
  const readOwnerFunds = async (blockNumber) => {
5262
5353
  const feeTracker = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5263
5354
  address: agentWallet,
@@ -5266,18 +5357,18 @@ var YieldseekerAgent = class {
5266
5357
  blockNumber
5267
5358
  }), chainId, "eth_call", this.id);
5268
5359
  this.assertSession(generation, chainId, asset);
5269
- if (!(0, import_viem11.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
5360
+ if (!(0, import_viem12.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
5270
5361
  throw this.invalidResponse("wallet fee tracker");
5271
5362
  const [idle2, fees] = await Promise.all([
5272
5363
  withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5273
5364
  address: metadata.address,
5274
- abi: import_viem11.erc20Abi,
5365
+ abi: import_viem12.erc20Abi,
5275
5366
  functionName: "balanceOf",
5276
5367
  args: [agentWallet],
5277
5368
  blockNumber
5278
5369
  }), chainId, "eth_call", this.id),
5279
5370
  withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5280
- address: (0, import_viem11.getAddress)(feeTracker),
5371
+ address: (0, import_viem12.getAddress)(feeTracker),
5281
5372
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
5282
5373
  functionName: "getFeesOwed",
5283
5374
  args: [agentWallet],
@@ -5319,13 +5410,13 @@ var YieldseekerAgent = class {
5319
5410
  let active = true;
5320
5411
  const checks = this.readVaultLiquidity(values.map((position2) => position2.yieldOption), agentWallet, blockNumber).catch(() => []);
5321
5412
  const reads = values.map(async (position2, index) => {
5322
- const address = (0, import_viem11.getAddress)(position2.yieldOption.address);
5413
+ const address = (0, import_viem12.getAddress)(position2.yieldOption.address);
5323
5414
  try {
5324
5415
  const group = (await checks).slice(index * 3, index * 3 + 3);
5325
5416
  if (!active || group.length !== 3 || group.some((value) => value.status !== "success")) return null;
5326
5417
  this.assertSession(generation, chainId, asset);
5327
5418
  const [underlying, shares, withdrawable] = group.map((value) => value.result);
5328
- if (typeof underlying !== "string" || !(0, import_viem11.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n || typeof withdrawable !== "bigint" || withdrawable < 0n) return null;
5419
+ if (typeof underlying !== "string" || !(0, import_viem12.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n || typeof withdrawable !== "bigint" || withdrawable < 0n) return null;
5329
5420
  const verified = { ...position2, assetsRaw: shares.toString(), withdrawableAssetsRaw: withdrawable.toString() };
5330
5421
  if (shares > 0n && withdrawable === 0n) {
5331
5422
  let positiveValue = false;
@@ -5333,7 +5424,7 @@ var YieldseekerAgent = class {
5333
5424
  try {
5334
5425
  const value = await this.getReceiptClient().readContract({
5335
5426
  address,
5336
- abi: import_viem11.erc4626Abi,
5427
+ abi: import_viem12.erc4626Abi,
5337
5428
  functionName,
5338
5429
  args: [shares],
5339
5430
  blockNumber
@@ -5546,14 +5637,14 @@ var YieldseekerAgent = class {
5546
5637
  delta: maxSettlementBasis.delta - payout,
5547
5638
  expectedNetDeposits: maxSettlementBasis.expectedNetDeposits - payout
5548
5639
  } : this.snapshotMovement(state, chainId, context, -payout);
5549
- const account = (0, import_viem11.getAddress)(state.walletAddress);
5640
+ const account = (0, import_viem12.getAddress)(state.walletAddress);
5550
5641
  let receipt;
5551
5642
  const base6 = { agentId: this.id, chainId, token: asset, walletAddress: state.walletAddress, agentWallet: context.wallet.walletAddress, intendedAmount: amount === void 0 ? "MAX" : payout.toString(), transfer: "pending", registration: "not-applicable", delivery: "pending" };
5552
- const data = amount === void 0 ? (0, import_viem11.encodeFunctionData)({
5643
+ const data = amount === void 0 ? (0, import_viem12.encodeFunctionData)({
5553
5644
  abi: YIELDSEEKER_AGENT_WALLET_ABI,
5554
5645
  functionName: "withdrawAllAssetToUser",
5555
5646
  args: [account, metadata.address]
5556
- }) : (0, import_viem11.encodeFunctionData)({
5647
+ }) : (0, import_viem12.encodeFunctionData)({
5557
5648
  abi: YIELDSEEKER_AGENT_WALLET_ABI,
5558
5649
  functionName: "withdrawAssetToUser",
5559
5650
  args: [account, metadata.address, payout]
@@ -5569,7 +5660,7 @@ var YieldseekerAgent = class {
5569
5660
  refreshYieldseekerSignature: (rejected) => this.auth.refreshToken(state, chainId, rejected),
5570
5661
  userId: context.user.userId,
5571
5662
  agentId: context.agent.agentId,
5572
- agentWallet: (0, import_viem11.getAddress)(context.wallet.walletAddress),
5663
+ agentWallet: (0, import_viem12.getAddress)(context.wallet.walletAddress),
5573
5664
  asset: metadata.address,
5574
5665
  callData: data,
5575
5666
  onPending: (pending) => notifyFunding(onProgress, { ...base6, ...pending }),
@@ -5584,7 +5675,7 @@ var YieldseekerAgent = class {
5584
5675
  onOwnerTransferAttempted?.();
5585
5676
  txHash = await this.submitTransaction(state, chainId, {
5586
5677
  from: account,
5587
- to: (0, import_viem11.getAddress)(context.wallet.walletAddress),
5678
+ to: (0, import_viem12.getAddress)(context.wallet.walletAddress),
5588
5679
  data,
5589
5680
  value: "0",
5590
5681
  chainId
@@ -5692,17 +5783,17 @@ var YieldseekerAgent = class {
5692
5783
  return proof.available;
5693
5784
  }
5694
5785
  async readVaultLiquidity(options, wallet, blockNumber) {
5695
- const owner = (0, import_viem11.getAddress)(wallet);
5786
+ const owner = (0, import_viem12.getAddress)(wallet);
5696
5787
  const batches = Array.from({ length: Math.ceil(options.length / YIELDSEEKER_VAULTS_PER_RPC_BATCH) }, (_, index) => options.slice(index * YIELDSEEKER_VAULTS_PER_RPC_BATCH, (index + 1) * YIELDSEEKER_VAULTS_PER_RPC_BATCH));
5697
5788
  const results = await Promise.all(batches.map((batch) => this.getReceiptClient().multicall({
5698
5789
  blockNumber,
5699
5790
  allowFailure: true,
5700
5791
  contracts: batch.flatMap((option) => {
5701
- const address = (0, import_viem11.getAddress)(option.address);
5792
+ const address = (0, import_viem12.getAddress)(option.address);
5702
5793
  return [
5703
- { address, abi: import_viem11.erc4626Abi, functionName: "asset" },
5704
- { address, abi: import_viem11.erc20Abi, functionName: "balanceOf", args: [owner] },
5705
- { address, abi: import_viem11.erc4626Abi, functionName: "maxWithdraw", args: [owner] }
5794
+ { address, abi: import_viem12.erc4626Abi, functionName: "asset" },
5795
+ { address, abi: import_viem12.erc20Abi, functionName: "balanceOf", args: [owner] },
5796
+ { address, abi: import_viem12.erc4626Abi, functionName: "maxWithdraw", args: [owner] }
5706
5797
  ];
5707
5798
  })
5708
5799
  })));
@@ -5713,7 +5804,7 @@ var YieldseekerAgent = class {
5713
5804
  const seen = /* @__PURE__ */ new Set();
5714
5805
  for (const value of values) {
5715
5806
  const option = value?.yieldOption;
5716
- if (!option || typeof option.address !== "string" || !(0, import_viem11.isAddress)(option.address) || seen.has(option.address.toLowerCase()) || option.chainId !== void 0 && option.chainId !== chainId || option.assetAddress !== void 0 && (typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== underlying) || typeof value.assetsRaw !== "string" || !/^\d+$/.test(value.assetsRaw) || typeof value.withdrawableAssetsRaw !== "string" || !/^\d+$/.test(value.withdrawableAssetsRaw))
5807
+ if (!option || typeof option.address !== "string" || !(0, import_viem12.isAddress)(option.address) || seen.has(option.address.toLowerCase()) || option.chainId !== void 0 && option.chainId !== chainId || option.assetAddress !== void 0 && (typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== underlying) || typeof value.assetsRaw !== "string" || !/^\d+$/.test(value.assetsRaw) || typeof value.withdrawableAssetsRaw !== "string" || !/^\d+$/.test(value.withdrawableAssetsRaw))
5717
5808
  throw this.invalidResponse("yield positions");
5718
5809
  seen.add(option.address.toLowerCase());
5719
5810
  }
@@ -5726,7 +5817,7 @@ var YieldseekerAgent = class {
5726
5817
  const historic = this.readCache.get(`historic:${key2}`)?.value?.position;
5727
5818
  const receivedAssets = new Set((historic?.movements ?? []).filter((movement) => movement.chainId === chainId && movement.agentWalletId === context.wallet.agentWalletId && movement.toAddress?.toLowerCase() === context.wallet.walletAddress.toLowerCase()).filter((movement) => typeof movement.assetAddress === "string").map((movement) => movement.assetAddress.toLowerCase()));
5728
5819
  for (const option of this.yieldOptions.get(context.asset)?.value ?? []) {
5729
- if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0, import_viem11.isAddress)(option.address) || !receivedAssets.has(option.address.toLowerCase()) || hints.has(option.address.toLowerCase())) continue;
5820
+ if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0, import_viem12.isAddress)(option.address) || !receivedAssets.has(option.address.toLowerCase()) || hints.has(option.address.toLowerCase())) continue;
5730
5821
  hints.set(option.address.toLowerCase(), {
5731
5822
  yieldOption: option,
5732
5823
  assetsRaw: "0",
@@ -5778,7 +5869,7 @@ var YieldseekerAgent = class {
5778
5869
  const read2 = async () => {
5779
5870
  const client = this.getReceiptClient();
5780
5871
  const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
5781
- const wallet = (0, import_viem11.getAddress)(context.wallet.walletAddress);
5872
+ const wallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
5782
5873
  assertReadCurrent();
5783
5874
  if (typeof blockNumber !== "bigint") throw unavailable();
5784
5875
  const indexedPositions = this.validateWithdrawalPositions(positions ?? [], chainId, context.asset);
@@ -5792,7 +5883,7 @@ var YieldseekerAgent = class {
5792
5883
  this.readVaultLiquidity(options, wallet, blockNumber),
5793
5884
  client.readContract({
5794
5885
  address: metadata.address,
5795
- abi: import_viem11.erc20Abi,
5886
+ abi: import_viem12.erc20Abi,
5796
5887
  functionName: "balanceOf",
5797
5888
  args: [wallet],
5798
5889
  blockNumber
@@ -5804,10 +5895,10 @@ var YieldseekerAgent = class {
5804
5895
  blockNumber
5805
5896
  })
5806
5897
  ]);
5807
- if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem11.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
5898
+ if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem12.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
5808
5899
  assertReadCurrent();
5809
5900
  const fees = await client.readContract({
5810
- address: (0, import_viem11.getAddress)(feeTracker),
5901
+ address: (0, import_viem12.getAddress)(feeTracker),
5811
5902
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
5812
5903
  functionName: "getFeesOwed",
5813
5904
  args: [wallet],
@@ -5818,15 +5909,21 @@ var YieldseekerAgent = class {
5818
5909
  const verifiedVaults = [];
5819
5910
  let deployed = 0n;
5820
5911
  const collect = (options2, results) => {
5912
+ assertReadCurrent();
5913
+ const known = this.balanceVaults.get(contextKey) ?? /* @__PURE__ */ new Set();
5914
+ this.balanceVaults.set(contextKey, known);
5821
5915
  let valid2 = true;
5822
5916
  options2.forEach((option, index) => {
5823
5917
  const group = results.slice(index * 3, index * 3 + 3);
5918
+ const shareProbe = group[1];
5919
+ if (shareProbe?.status === "success" && typeof shareProbe.result === "bigint" && shareProbe.result > 0n)
5920
+ known.add(option.address.toLowerCase());
5824
5921
  if (group.length !== 3 || group.some((value) => value.status !== "success")) {
5825
5922
  valid2 = false;
5826
5923
  return;
5827
5924
  }
5828
5925
  const [underlying, shares, withdrawable] = group.map((value) => value.result);
5829
- if (typeof underlying !== "string" || !(0, import_viem11.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n || typeof withdrawable !== "bigint" || withdrawable < 0n || shares === 0n && withdrawable > 0n) {
5926
+ if (typeof underlying !== "string" || !(0, import_viem12.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n || typeof withdrawable !== "bigint" || withdrawable < 0n || shares === 0n && withdrawable > 0n) {
5830
5927
  valid2 = false;
5831
5928
  return;
5832
5929
  }
@@ -5870,7 +5967,7 @@ var YieldseekerAgent = class {
5870
5967
  assertReadCurrent();
5871
5968
  const eligible = /* @__PURE__ */ new Map();
5872
5969
  for (const option of catalog ?? []) {
5873
- if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem11.isAddress)(option.address))
5970
+ if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem12.isAddress)(option.address))
5874
5971
  eligible.set(option.address.toLowerCase(), option);
5875
5972
  }
5876
5973
  const extra = [...eligible].filter(([address]) => !candidates.has(address)).map(([, option]) => option);
@@ -5899,7 +5996,59 @@ var YieldseekerAgent = class {
5899
5996
  async getBalances(state, chainId, asset) {
5900
5997
  this.assertChain(chainId);
5901
5998
  if (asset !== void 0) this.assertAsset(asset);
5902
- return mapYieldseekerBalances(await this.loadPortfolio(state, chainId, { asset, allowMissingPositions: true }));
5999
+ const contexts = await this.loadPortfolio(state, chainId, { asset, allowMissingPositions: true });
6000
+ const balance = mapYieldseekerBalances(contexts);
6001
+ for (const context of contexts) {
6002
+ const read2 = balance.readMetadata.find((item) => item.asset === context.asset);
6003
+ this.balanceContexts.set(read2, { context, generation: this.readGeneration });
6004
+ const key2 = this.contextKey(state, chainId, context.asset);
6005
+ const known = this.balanceVaults.get(key2) ?? /* @__PURE__ */ new Set();
6006
+ for (const position2 of context.positions) known.add(position2.yieldOption.address.toLowerCase());
6007
+ this.balanceVaults.set(key2, known);
6008
+ }
6009
+ return balance;
6010
+ }
6011
+ async verifyWithdrawalBalance(state, evidence, balance) {
6012
+ this.assertAsset(evidence.token);
6013
+ this.assertChain(evidence.chainId);
6014
+ const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
6015
+ const cached = read2 && this.balanceContexts.get(read2);
6016
+ const context = cached?.generation === this.readGeneration ? cached.context : void 0;
6017
+ if (!context || context.positionsUnavailable || !read2 || !evidence.blockNumber || !evidence.txHash || context.wallet.walletAddress.toLowerCase() !== evidence.agentWallet?.toLowerCase()) return void 0;
6018
+ const key2 = this.contextKey(state, evidence.chainId, evidence.token);
6019
+ const generation = this.readGeneration, version = this.portfolioVersion(key2);
6020
+ if (read2.readVersion !== version) return void 0;
6021
+ const wallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
6022
+ const asset = YIELDSEEKER_ASSET_METADATA[evidence.token];
6023
+ const client = this.getReceiptClient();
6024
+ const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
6025
+ if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
6026
+ const vaults = [...this.balanceVaults.get(key2) ?? []];
6027
+ const [invested, idle, tracker] = await Promise.all([
6028
+ remainingVaultBalance(client, wallet, asset.address, vaults, blockNumber),
6029
+ client.readContract({ address: asset.address, abi: import_viem12.erc20Abi, functionName: "balanceOf", args: [wallet], blockNumber }),
6030
+ client.readContract({ address: wallet, abi: YIELDSEEKER_AGENT_WALLET_ABI, functionName: "feeTracker", blockNumber })
6031
+ ]);
6032
+ if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0, import_viem12.isAddress)(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
6033
+ const fees = await client.readContract({
6034
+ address: tracker,
6035
+ abi: YIELDSEEKER_FEE_TRACKER_ABI,
6036
+ functionName: "getFeesOwed",
6037
+ args: [wallet],
6038
+ blockNumber
6039
+ });
6040
+ this.assertSession(generation, evidence.chainId, evidence.token);
6041
+ if (version !== this.portfolioVersion(key2) || typeof fees !== "bigint" || fees < 0n) return void 0;
6042
+ const total = idle + invested > fees ? idle + invested - fees : 0n;
6043
+ const displayed = balance.assetBalances?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
6044
+ if (!displayed || !evidence.confirmedAmount || !/^\d+$/.test(evidence.confirmedAmount)) return void 0;
6045
+ const amount = (0, import_viem12.parseUnits)(displayed.amount, asset.decimals);
6046
+ if (amount < 0n) return void 0;
6047
+ const displayUnit = evidence.token === "USDC" ? 5000n : 500000000000n;
6048
+ const movementUnit = BigInt(evidence.confirmedAmount) / 1000n;
6049
+ const tolerance = movementUnit < displayUnit ? movementUnit : displayUnit;
6050
+ if ((total > amount ? total - amount : amount - total) > tolerance) return void 0;
6051
+ return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
5903
6052
  }
5904
6053
  invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS) {
5905
6054
  this.assertAsset(asset);
@@ -5939,9 +6088,9 @@ var YieldseekerAgent = class {
5939
6088
  if (!context) return void 0;
5940
6089
  const idle = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5941
6090
  address: YIELDSEEKER_ASSET_METADATA[asset].address,
5942
- abi: import_viem11.erc20Abi,
6091
+ abi: import_viem12.erc20Abi,
5943
6092
  functionName: "balanceOf",
5944
- args: [(0, import_viem11.getAddress)(context.wallet.walletAddress)]
6093
+ args: [(0, import_viem12.getAddress)(context.wallet.walletAddress)]
5945
6094
  }), chainId, "eth_call", this.id);
5946
6095
  this.assertSession(generation, chainId, asset);
5947
6096
  if (typeof idle !== "bigint" || idle < 0n) throw this.invalidResponse("wallet deposit balance");
@@ -5977,7 +6126,7 @@ var YieldseekerAgent = class {
5977
6126
  );
5978
6127
  const vaultAddresses = new Set(
5979
6128
  catalog.flat().filter(
5980
- (yieldOption) => yieldOption.chainId === chainId && (0, import_viem11.isAddress)(yieldOption.address)
6129
+ (yieldOption) => yieldOption.chainId === chainId && (0, import_viem12.isAddress)(yieldOption.address)
5981
6130
  ).map((yieldOption) => yieldOption.address.toLowerCase())
5982
6131
  );
5983
6132
  return mapYieldseekerHistory(contexts, {
@@ -6053,11 +6202,13 @@ var YieldseekerAgent = class {
6053
6202
  const pending = this.pendingReads.get(key2);
6054
6203
  if (pending) return pending;
6055
6204
  const generation = this.readGeneration;
6205
+ const requestedAt = Date.now();
6056
6206
  const request = Promise.resolve().then(read2).then((value) => {
6057
6207
  if (this.readGeneration === generation && this.pendingReads.get(key2) === request) {
6058
6208
  this.readCache.set(key2, {
6059
6209
  expiresAt: Date.now() + ttlMs,
6060
6210
  fetchedAt: Date.now(),
6211
+ requestedAt,
6061
6212
  value
6062
6213
  });
6063
6214
  }
@@ -6104,7 +6255,7 @@ var YieldseekerAgent = class {
6104
6255
  `/users/${user.userId}/agents/${agent.agentId}/wallet`
6105
6256
  ).then((walletResponse) => {
6106
6257
  this.assertSession(generation, chainId, asset);
6107
- if (!walletResponse?.agentWallet || !(0, import_viem11.isAddress)(walletResponse.agentWallet.walletAddress)) {
6258
+ if (!walletResponse?.agentWallet || !(0, import_viem12.isAddress)(walletResponse.agentWallet.walletAddress)) {
6108
6259
  throw this.invalidResponse("agent wallet");
6109
6260
  }
6110
6261
  const context = {
@@ -6134,7 +6285,7 @@ var YieldseekerAgent = class {
6134
6285
  this.users.set(key2, persisted);
6135
6286
  return persisted;
6136
6287
  }
6137
- const walletAddress = (0, import_viem11.getAddress)(state.walletAddress);
6288
+ const walletAddress = (0, import_viem12.getAddress)(state.walletAddress);
6138
6289
  const generation = this.readGeneration;
6139
6290
  let user = null;
6140
6291
  try {
@@ -6426,6 +6577,7 @@ var YieldseekerAgent = class {
6426
6577
  ...context,
6427
6578
  snapshot: snapshot.agentSnapshot,
6428
6579
  fetchedAt: this.readCache.get(`snapshot:${contextKey}`)?.fetchedAt,
6580
+ requestedAt: this.readCache.get(`snapshot:${contextKey}`)?.requestedAt,
6429
6581
  readVersion: version,
6430
6582
  positionsUnavailable,
6431
6583
  ...portfolioParts
@@ -6517,7 +6669,7 @@ var YieldseekerAgent = class {
6517
6669
  this.agentPath(context, "deploy"),
6518
6670
  { method: "POST", body: {} }
6519
6671
  );
6520
- if (!deployed?.agentWallet || !(0, import_viem11.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
6672
+ if (!deployed?.agentWallet || !(0, import_viem12.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
6521
6673
  throw this.invalidResponse("agent deployment", {
6522
6674
  reason: "Deploy did not return the expected Agent Wallet."
6523
6675
  });
@@ -6625,15 +6777,15 @@ var YieldseekerAgent = class {
6625
6777
  return hash2;
6626
6778
  }
6627
6779
  this.assertTransaction(transaction, state, chainId);
6628
- const account = (0, import_viem11.getAddress)(state.walletAddress);
6629
- const walletClient = (0, import_viem11.createWalletClient)({
6780
+ const account = (0, import_viem12.getAddress)(state.walletAddress);
6781
+ const walletClient = (0, import_viem12.createWalletClient)({
6630
6782
  account,
6631
6783
  chain: import_chains4.base,
6632
- transport: (0, import_viem11.custom)(state.provider)
6784
+ transport: (0, import_viem12.custom)(state.provider)
6633
6785
  });
6634
- const walletChainClient = (0, import_viem11.createPublicClient)({
6786
+ const walletChainClient = (0, import_viem12.createPublicClient)({
6635
6787
  chain: import_chains4.base,
6636
- transport: (0, import_viem11.custom)(state.provider)
6788
+ transport: (0, import_viem12.custom)(state.provider)
6637
6789
  });
6638
6790
  await ensureWalletOnChain(
6639
6791
  walletChainClient,
@@ -6643,7 +6795,7 @@ var YieldseekerAgent = class {
6643
6795
  const hash = await walletClient.sendTransaction({
6644
6796
  account,
6645
6797
  chain: import_chains4.base,
6646
- to: (0, import_viem11.getAddress)(transaction.to),
6798
+ to: (0, import_viem12.getAddress)(transaction.to),
6647
6799
  data: transaction.data,
6648
6800
  value: BigInt(transaction.value)
6649
6801
  });
@@ -6747,12 +6899,12 @@ var YieldseekerAgent = class {
6747
6899
  return receipt;
6748
6900
  }
6749
6901
  assertTransaction(transaction, state, chainId) {
6750
- if (!transaction || typeof transaction.from !== "string" || !(0, import_viem11.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem11.isAddress)(transaction.to) || typeof transaction.data !== "string" || !/^0x[a-fA-F0-9]*$/.test(transaction.data) || typeof transaction.value !== "string" || !/^[0-9]+$/.test(transaction.value) || transaction.chainId !== chainId || (0, import_viem11.getAddress)(transaction.from) !== (0, import_viem11.getAddress)(state.walletAddress)) {
6902
+ if (!transaction || typeof transaction.from !== "string" || !(0, import_viem12.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem12.isAddress)(transaction.to) || typeof transaction.data !== "string" || !/^0x[a-fA-F0-9]*$/.test(transaction.data) || typeof transaction.value !== "string" || !/^[0-9]+$/.test(transaction.value) || transaction.chainId !== chainId || (0, import_viem12.getAddress)(transaction.from) !== (0, import_viem12.getAddress)(state.walletAddress)) {
6751
6903
  throw this.invalidResponse("transaction");
6752
6904
  }
6753
6905
  }
6754
6906
  assertAgent(agent) {
6755
- if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem11.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
6907
+ if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem12.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
6756
6908
  throw this.invalidResponse("agent");
6757
6909
  }
6758
6910
  }
@@ -6906,7 +7058,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
6906
7058
  }
6907
7059
 
6908
7060
  // src/lib/helpers/withdraw-helper.ts
6909
- var import_viem12 = require("viem");
7061
+ var import_viem13 = require("viem");
6910
7062
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
6911
7063
  const target = asset.toUpperCase();
6912
7064
  return agents.map((agent) => {
@@ -6914,7 +7066,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
6914
7066
  const tokenBalance = agentBalance?.tokens.find(
6915
7067
  (t) => t.chainId === chainId && t.asset.toUpperCase() === target
6916
7068
  );
6917
- let balance = tokenBalance ? (0, import_viem12.parseUnits)(tokenBalance.amount, decimals) : 0n;
7069
+ let balance = tokenBalance ? (0, import_viem13.parseUnits)(tokenBalance.amount, decimals) : 0n;
6918
7070
  if (agent.balanceComposition === "tokens-plus-positions") {
6919
7071
  const chainNameById = {
6920
7072
  1: "ETHEREUM",
@@ -6926,14 +7078,14 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
6926
7078
  const positionChain = position2.chain.trim().toUpperCase();
6927
7079
  const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
6928
7080
  if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
6929
- balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0, import_viem12.parseUnits)(position2.amount, decimals);
7081
+ balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0, import_viem13.parseUnits)(position2.amount, decimals);
6930
7082
  }
6931
7083
  }
6932
7084
  const assetTotal = agentBalance?.assetBalances?.find(
6933
7085
  (t) => t.chainId === chainId && t.asset.toUpperCase() === target
6934
7086
  );
6935
7087
  if (assetTotal) {
6936
- const total = (0, import_viem12.parseUnits)(assetTotal.amount, decimals);
7088
+ const total = (0, import_viem13.parseUnits)(assetTotal.amount, decimals);
6937
7089
  if (total < balance) balance = total > 0n ? total : 0n;
6938
7090
  }
6939
7091
  return { agent, balance };
@@ -7092,14 +7244,14 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
7092
7244
  }
7093
7245
 
7094
7246
  // src/client.ts
7095
- var import_viem16 = require("viem");
7247
+ var import_viem17 = require("viem");
7096
7248
  var import_chains5 = require("viem/chains");
7097
7249
 
7098
7250
  // src/lib/sponsored-token-batch.ts
7099
- var import_viem14 = require("viem");
7251
+ var import_viem15 = require("viem");
7100
7252
 
7101
7253
  // src/lib/permit2-batch.ts
7102
- var import_viem13 = require("viem");
7254
+ var import_viem14 = require("viem");
7103
7255
  var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
7104
7256
  var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
7105
7257
  var ERC2612_PERMIT_TYPES = {
@@ -7111,7 +7263,7 @@ var ERC2612_PERMIT_TYPES = {
7111
7263
  { name: "deadline", type: "uint256" }
7112
7264
  ]
7113
7265
  };
7114
- var ERC2612_READ_ABI = (0, import_viem13.parseAbi)([
7266
+ var ERC2612_READ_ABI = (0, import_viem14.parseAbi)([
7115
7267
  "function name() view returns (string)",
7116
7268
  "function version() view returns (string)",
7117
7269
  "function nonces(address owner) view returns (uint256)"
@@ -7149,7 +7301,7 @@ var PERMIT_BATCH_TYPES = {
7149
7301
  { name: "amount", type: "uint256" }
7150
7302
  ]
7151
7303
  };
7152
- var PERMIT2_BATCH_ABI = (0, import_viem13.parseAbi)([
7304
+ var PERMIT2_BATCH_ABI = (0, import_viem14.parseAbi)([
7153
7305
  "struct TokenPermissions { address token; uint256 amount; }",
7154
7306
  "struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
7155
7307
  "struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
@@ -7192,14 +7344,14 @@ var planOf = (transfers) => JSON.stringify(
7192
7344
  amount: BigInt(t.amount).toString()
7193
7345
  }))
7194
7346
  );
7195
- var pendingKey = (i) => `owney.token-batch.v1:${(0, import_viem14.keccak256)((0, import_viem14.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
7347
+ var pendingKey = (i) => `owney.token-batch.v1:${(0, import_viem15.keccak256)((0, import_viem15.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
7196
7348
  function pendingTokenBatch(i) {
7197
7349
  try {
7198
7350
  const saved = read(pendingKey(i));
7199
7351
  if (!saved) return;
7200
7352
  const body = JSON.parse(saved);
7201
- if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem14.isAddressEqual)(body.from, i.owner) || !(0, import_viem14.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
7202
- return { txHash: (0, import_viem14.keccak256)(body.serializedTransaction), transfers: body.transfers.map(({ to, amount }) => ({ to, amount })) };
7353
+ if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem15.isAddressEqual)(body.from, i.owner) || !(0, import_viem15.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
7354
+ return { txHash: (0, import_viem15.keccak256)(body.serializedTransaction), transfers: body.transfers.map(({ to, amount }) => ({ to, amount })) };
7203
7355
  } catch {
7204
7356
  return;
7205
7357
  }
@@ -7244,14 +7396,47 @@ async function execute(i, key2, plan) {
7244
7396
  const send = async (initial) => {
7245
7397
  let body = initial;
7246
7398
  save(key2, body);
7399
+ const rejectedPreparation = (error) => !body.serializedTransaction && error instanceof OwneyError && typeof error.details?.statusCode === "number" && error.details.statusCode >= 400 && error.details.statusCode < 500 && ![408, 429].includes(error.details.statusCode);
7247
7400
  try {
7401
+ const post = () => postSponsorBatchTransfer({ apiKey: i.apiKey, baseUrl: i.baseUrl, body });
7402
+ const pendingError = (phase, txHash) => new OwneyError(
7403
+ "DEPOSIT_IN_PROGRESS",
7404
+ phase === "approval" ? "Deposit approval is awaiting confirmation. Retry the same amount to continue it." : "Deposit is awaiting confirmation. Its transaction is still being checked.",
7405
+ { sponsorPending: true, phase, txHash, safeToFallback: false }
7406
+ );
7407
+ const assertReceipt = (receipt, phase) => {
7408
+ if (receipt.status !== "success") throw new OwneyError(
7409
+ "SPONSOR_REQUEST_FAILED",
7410
+ `Sponsored ${phase} transaction reverted. Please retry.`,
7411
+ { notSubmitted: true, safeToFallback: false }
7412
+ );
7413
+ };
7414
+ const waitForConfirmation = async (phase, hash2) => {
7415
+ let receipt;
7416
+ try {
7417
+ receipt = await i.pub.waitForTransactionReceipt({ hash: hash2, confirmations: 1, timeout: 9e4, checkReplacement: false });
7418
+ } catch {
7419
+ receipt = await i.pub.getTransactionReceipt({ hash: hash2 }).catch(() => void 0);
7420
+ }
7421
+ if (!receipt) throw pendingError(phase, hash2);
7422
+ assertReceipt(receipt, phase);
7423
+ };
7424
+ const postSigned = async (phase, hash2) => {
7425
+ try {
7426
+ return await post();
7427
+ } catch (error) {
7428
+ if (rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true) throw error;
7429
+ await waitForConfirmation(phase, hash2);
7430
+ return void 0;
7431
+ }
7432
+ };
7248
7433
  if (body.erc2612Permit && !body.serializedPermitTransaction) {
7249
7434
  const preparedPermit = await postSponsorBatchTransfer({
7250
7435
  apiKey: i.apiKey,
7251
7436
  baseUrl: i.baseUrl,
7252
7437
  body
7253
7438
  });
7254
- if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem14.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
7439
+ if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem15.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
7255
7440
  throw new Error(
7256
7441
  "Sponsorship API did not return a valid prepared permit transaction."
7257
7442
  );
@@ -7262,12 +7447,18 @@ async function execute(i, key2, plan) {
7262
7447
  save(key2, body);
7263
7448
  }
7264
7449
  if (!body.serializedTransaction) {
7265
- const prepared = await postSponsorBatchTransfer({
7266
- apiKey: i.apiKey,
7267
- baseUrl: i.baseUrl,
7268
- body
7269
- });
7270
- if (!prepared.serializedTransaction || (0, import_viem14.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
7450
+ const permitHash = body.serializedPermitTransaction ? (0, import_viem15.keccak256)(body.serializedPermitTransaction) : void 0;
7451
+ let prepared = permitHash ? await postSigned("approval", permitHash) : await post();
7452
+ if (prepared?.status === "pending") {
7453
+ if (!permitHash || prepared.phase !== "approval" || prepared.txHash !== permitHash)
7454
+ throw new Error("Sponsorship approval does not match the pending transaction.");
7455
+ await waitForConfirmation("approval", permitHash);
7456
+ prepared = void 0;
7457
+ }
7458
+ if (!prepared) prepared = await post();
7459
+ if (prepared.status === "pending" && permitHash && prepared.phase === "approval" && prepared.txHash === permitHash)
7460
+ throw pendingError("approval", permitHash);
7461
+ if (!prepared.serializedTransaction || (0, import_viem15.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
7271
7462
  throw new Error(
7272
7463
  "Sponsorship API did not return a valid prepared transaction."
7273
7464
  );
@@ -7278,22 +7469,33 @@ async function execute(i, key2, plan) {
7278
7469
  save(key2, body);
7279
7470
  }
7280
7471
  try {
7281
- i.onSubmitted?.((0, import_viem14.keccak256)(body.serializedTransaction));
7472
+ i.onSubmitted?.((0, import_viem15.keccak256)(body.serializedTransaction));
7282
7473
  } catch {
7283
7474
  }
7284
- const result = await postSponsorBatchTransfer({
7285
- apiKey: i.apiKey,
7286
- baseUrl: i.baseUrl,
7287
- body
7288
- });
7289
- if (result.txHash !== (0, import_viem14.keccak256)(body.serializedTransaction))
7290
- throw new Error(
7291
- "Sponsorship receipt does not match the pending transaction."
7292
- );
7475
+ const hash = (0, import_viem15.keccak256)(body.serializedTransaction);
7476
+ const existing = await i.pub.getTransactionReceipt({ hash }).catch(() => void 0);
7477
+ if (existing) {
7478
+ assertReceipt(existing, "deposit");
7479
+ void post().catch(() => void 0);
7480
+ clear(key2);
7481
+ return hash;
7482
+ }
7483
+ let result = await postSigned("deposit", hash);
7484
+ if (result?.status === "pending" && result.phase === "approval" && body.serializedPermitTransaction && result.txHash === (0, import_viem15.keccak256)(body.serializedPermitTransaction)) {
7485
+ await waitForConfirmation("approval", result.txHash);
7486
+ result = await postSigned("deposit", hash);
7487
+ if (result?.status === "pending" && result.phase === "approval" && result.txHash === (0, import_viem15.keccak256)(body.serializedPermitTransaction)) throw pendingError("approval", result.txHash);
7488
+ }
7489
+ if (result) {
7490
+ if (result.txHash !== hash || result.status === "pending" && result.phase !== "deposit")
7491
+ throw new Error("Sponsorship receipt does not match the pending transaction.");
7492
+ if (result.status === "pending") await waitForConfirmation("deposit", hash);
7493
+ }
7494
+ if (!result || result.status === "pending") void post().catch(() => void 0);
7293
7495
  clear(key2);
7294
- return result.txHash;
7496
+ return hash;
7295
7497
  } catch (error) {
7296
- if (!body.serializedTransaction || error instanceof OwneyError && error.details?.notSubmitted === true)
7498
+ if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
7297
7499
  clear(key2);
7298
7500
  throw error;
7299
7501
  }
@@ -7303,7 +7505,7 @@ async function execute(i, key2, plan) {
7303
7505
  throw new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit changed. Check its status before depositing again.");
7304
7506
  if (saved) {
7305
7507
  const previous = JSON.parse(saved);
7306
- if (previous.chainId !== i.chainId || !(0, import_viem14.isAddressEqual)(previous.from, i.owner) || !(0, import_viem14.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
7508
+ if (previous.chainId !== i.chainId || !(0, import_viem15.isAddressEqual)(previous.from, i.owner) || !(0, import_viem15.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
7307
7509
  throw new Error(
7308
7510
  "Retry the previous token deposit and agent split first to reconcile its status."
7309
7511
  );
@@ -7320,7 +7522,7 @@ async function execute(i, key2, plan) {
7320
7522
  "DEPOSIT_INSUFFICIENT_BALANCE",
7321
7523
  "Insufficient token balance for this deposit."
7322
7524
  );
7323
- if (allowance < total && (i.chainId !== 8453 || !(0, import_viem14.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
7525
+ if (allowance < total && (i.chainId !== 8453 || !(0, import_viem15.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
7324
7526
  throw new OwneyError(
7325
7527
  "PERMIT2_APPROVAL_REQUIRED",
7326
7528
  "token deposits need a one-time Permit2 approval."
@@ -7499,7 +7701,7 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
7499
7701
  }
7500
7702
 
7501
7703
  // src/lib/sponsored-calls-deposit.ts
7502
- var import_viem15 = require("viem");
7704
+ var import_viem16 = require("viem");
7503
7705
  var DEFAULT_POLL_INTERVAL_MS = 1500;
7504
7706
  var DEFAULT_MAX_POLLS = 30;
7505
7707
  async function paymasterSupported(provider, owner, chainId) {
@@ -7507,7 +7709,7 @@ async function paymasterSupported(provider, owner, chainId) {
7507
7709
  method: "wallet_getCapabilities",
7508
7710
  params: [owner]
7509
7711
  });
7510
- const forChain = caps?.[(0, import_viem15.toHex)(chainId)] ?? caps?.[String(chainId)];
7712
+ const forChain = caps?.[(0, import_viem16.toHex)(chainId)] ?? caps?.[String(chainId)];
7511
7713
  return Boolean(forChain?.paymasterService?.supported);
7512
7714
  }
7513
7715
  function makeSponsoredCallsCallback(deps) {
@@ -7544,8 +7746,8 @@ function makeSponsoredCallsCallback(deps) {
7544
7746
  const calls = transfers.map((transfer) => ({
7545
7747
  to: token,
7546
7748
  value: "0x0",
7547
- data: (0, import_viem15.encodeFunctionData)({
7548
- abi: import_viem15.erc20Abi,
7749
+ data: (0, import_viem16.encodeFunctionData)({
7750
+ abi: import_viem16.erc20Abi,
7549
7751
  functionName: "transfer",
7550
7752
  args: [transfer.to, BigInt(transfer.amount)]
7551
7753
  })
@@ -7577,7 +7779,7 @@ function makeSponsoredCallsCallback(deps) {
7577
7779
  url.searchParams.append("owneyIntent", intent);
7578
7780
  paymasterUrl = url.toString();
7579
7781
  }
7580
- const requestedId = (0, import_viem15.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
7782
+ const requestedId = (0, import_viem16.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
7581
7783
  const progress = (id, transfer) => {
7582
7784
  try {
7583
7785
  deps.onCallsProgress?.(id, transfers, transfer);
@@ -7594,7 +7796,7 @@ function makeSponsoredCallsCallback(deps) {
7594
7796
  version: "2.0.0",
7595
7797
  id: requestedId,
7596
7798
  from: deps.ownerAddress,
7597
- chainId: (0, import_viem15.toHex)(chainId),
7799
+ chainId: (0, import_viem16.toHex)(chainId),
7598
7800
  atomicRequired: transfers.length > 1,
7599
7801
  calls,
7600
7802
  capabilities: {
@@ -7746,6 +7948,7 @@ var OwneySDK = class {
7746
7948
  cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
7747
7949
  agentReads = new AgentReads();
7748
7950
  recoveredFundingReads = /* @__PURE__ */ new Set();
7951
+ fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
7749
7952
  activationChecks = /* @__PURE__ */ new Map();
7750
7953
  readAgent(agent, method, fetch2, params = null) {
7751
7954
  const key2 = JSON.stringify([
@@ -7791,6 +7994,7 @@ var OwneySDK = class {
7791
7994
  }
7792
7995
  this.agentReads.clearInFlight();
7793
7996
  this.activationChecks.clear();
7997
+ this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
7794
7998
  this.state = { provider, walletAddress, chainId: null };
7795
7999
  this.cachedSponsoredCallback = null;
7796
8000
  this.cachedWethSponsoredCallback = null;
@@ -7802,6 +8006,7 @@ var OwneySDK = class {
7802
8006
  */
7803
8007
  async disconnect() {
7804
8008
  this.state = null;
8009
+ this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
7805
8010
  for (const agent of this.agents.values()) {
7806
8011
  await agent.disconnect();
7807
8012
  }
@@ -7876,14 +8081,14 @@ var OwneySDK = class {
7876
8081
  // PublicClient/WalletClient param types — structurally identical at
7877
8082
  // runtime, but the two share a name TS treats as unrelated.
7878
8083
  getPublicClient: (cid) => this.getPaidRpcClient(cid),
7879
- getWalletChainClient: (cid) => (0, import_viem16.createPublicClient)({
8084
+ getWalletChainClient: (cid) => (0, import_viem17.createPublicClient)({
7880
8085
  chain: VIEM_CHAIN2[cid],
7881
- transport: (0, import_viem16.custom)(provider)
8086
+ transport: (0, import_viem17.custom)(provider)
7882
8087
  }),
7883
- getWalletClient: (cid) => (0, import_viem16.createWalletClient)({
8088
+ getWalletClient: (cid) => (0, import_viem17.createWalletClient)({
7884
8089
  account: owner,
7885
8090
  chain: VIEM_CHAIN2[cid],
7886
- transport: (0, import_viem16.custom)(provider)
8091
+ transport: (0, import_viem17.custom)(provider)
7887
8092
  })
7888
8093
  });
7889
8094
  if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedSponsoredCallback = callback;
@@ -7931,14 +8136,14 @@ var OwneySDK = class {
7931
8136
  // PublicClient/WalletClient param types — structurally identical at
7932
8137
  // runtime, but the two share a name TS treats as unrelated.
7933
8138
  getPublicClient: (cid) => this.getPaidRpcClient(cid),
7934
- getWalletChainClient: (cid) => (0, import_viem16.createPublicClient)({
8139
+ getWalletChainClient: (cid) => (0, import_viem17.createPublicClient)({
7935
8140
  chain: VIEM_CHAIN2[cid],
7936
- transport: (0, import_viem16.custom)(provider)
8141
+ transport: (0, import_viem17.custom)(provider)
7937
8142
  }),
7938
- getWalletClient: (cid) => (0, import_viem16.createWalletClient)({
8143
+ getWalletClient: (cid) => (0, import_viem17.createWalletClient)({
7939
8144
  account: owner,
7940
8145
  chain: VIEM_CHAIN2[cid],
7941
- transport: (0, import_viem16.custom)(provider)
8146
+ transport: (0, import_viem17.custom)(provider)
7942
8147
  })
7943
8148
  });
7944
8149
  if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedWethSponsoredCallback = callback;
@@ -8702,9 +8907,8 @@ var OwneySDK = class {
8702
8907
  verified = inspectFundingReceipt(receipt, { ...evidence, agentWallet, intendedAmount: "MAX" }, token.address, direction);
8703
8908
  }
8704
8909
  const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}`;
8705
- if ((verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
8706
- if (options.refreshBalance !== false)
8707
- agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
8910
+ if (options.refreshBalance !== false && (verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
8911
+ agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
8708
8912
  this.recoveredFundingReads.add(key2);
8709
8913
  if (this.recoveredFundingReads.size > 256) this.recoveredFundingReads.delete(this.recoveredFundingReads.values().next().value);
8710
8914
  }
@@ -8812,6 +9016,44 @@ var OwneySDK = class {
8812
9016
  assertCurrent();
8813
9017
  return true;
8814
9018
  }
9019
+ /** Optional post-payout display proof; receipt verification and the provider
9020
+ * adapter must agree before attaching it to this exact balance object. */
9021
+ async verifyWithdrawalBalance(evidence, balance) {
9022
+ const { state, chainId, assertCurrent } = this.captureReadScope(evidence.chainId);
9023
+ const agent = this.getAgent(evidence.agentId);
9024
+ if (!agent.verifyWithdrawalBalance || !evidence.txHash || state.walletAddress.toLowerCase() !== evidence.walletAddress.toLowerCase()) return balance;
9025
+ const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}:${evidence.intendedAmount}`;
9026
+ const checks = this.fundingBalanceChecks.get(balance) ?? /* @__PURE__ */ new Map();
9027
+ this.fundingBalanceChecks.set(balance, checks);
9028
+ const previous = checks.get(key2);
9029
+ if (previous) {
9030
+ const result2 = await previous;
9031
+ assertCurrent();
9032
+ return result2;
9033
+ }
9034
+ let timer;
9035
+ const read2 = async () => {
9036
+ const verified = await this.inspectFunding(evidence, "withdraw", { refreshBalance: false });
9037
+ assertCurrent();
9038
+ if (verified.transfer !== "confirmed" || verified.delivery !== "confirmed" || !verified.blockNumber) return balance;
9039
+ const metadata = await agent.verifyWithdrawalBalance(state, verified, balance);
9040
+ assertCurrent();
9041
+ if (!metadata || metadata.chainId !== chainId || metadata.asset.toUpperCase() !== evidence.token || !metadata.withdrawalCheck || metadata.withdrawalCheck.txHash.toLowerCase() !== verified.txHash?.toLowerCase() || BigInt(metadata.withdrawalCheck.blockNumber) < BigInt(verified.blockNumber)) return balance;
9042
+ return { ...balance, readMetadata: [
9043
+ ...(balance.readMetadata ?? []).filter((item) => !(item.chainId === chainId && item.asset.toUpperCase() === evidence.token)),
9044
+ metadata
9045
+ ] };
9046
+ };
9047
+ const pending = Promise.race([read2(), new Promise((resolve) => {
9048
+ timer = setTimeout(() => resolve(balance), 2e3);
9049
+ })]).catch(() => balance).finally(() => {
9050
+ if (timer) clearTimeout(timer);
9051
+ });
9052
+ checks.set(key2, pending);
9053
+ const result = await pending;
9054
+ assertCurrent();
9055
+ return result;
9056
+ }
8815
9057
  /** A display acknowledgement controls polling only; it never confirms a financial outcome. */
8816
9058
  endFundingBalanceRefresh(evidence, read2) {
8817
9059
  const { state, chainId } = this.captureReadScope(evidence.chainId);
@@ -9080,7 +9322,7 @@ var OwneySDK = class {
9080
9322
  if (this.isUserRejectedWithdrawal(originalFailure)) throw originalFailure;
9081
9323
  if (entry.balance !== 0n && entry.agent.id !== "yieldseeker") {
9082
9324
  const total = aggregated.agentBalances[entry.agent.id]?.assetBalances?.find((value) => value.chainId === chainId && value.asset.toUpperCase() === token);
9083
- if (!total || (0, import_viem16.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
9325
+ if (!total || (0, import_viem17.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
9084
9326
  }
9085
9327
  try {
9086
9328
  const otherAvailable = indexedAvailable - entry.balance;
@@ -9684,16 +9926,16 @@ var OwneySDK = class {
9684
9926
  );
9685
9927
  }
9686
9928
  const provider = this.requireConnectedProvider();
9687
- const walletChainClient = (0, import_viem16.createPublicClient)({
9929
+ const walletChainClient = (0, import_viem17.createPublicClient)({
9688
9930
  chain: VIEM_CHAIN2[chainId],
9689
- transport: (0, import_viem16.custom)(provider)
9931
+ transport: (0, import_viem17.custom)(provider)
9690
9932
  });
9691
9933
  const publicClient = this.getPaidRpcClient(chainId);
9692
9934
  const approvalAmount = permit2ApprovalAmount(requiredAmount);
9693
- const wallet = (0, import_viem16.createWalletClient)({
9935
+ const wallet = (0, import_viem17.createWalletClient)({
9694
9936
  account: state.walletAddress,
9695
9937
  chain: VIEM_CHAIN2[chainId],
9696
- transport: (0, import_viem16.custom)(provider)
9938
+ transport: (0, import_viem17.custom)(provider)
9697
9939
  });
9698
9940
  await ensureWalletOnChain(walletChainClient, wallet, chainId);
9699
9941
  const hash = await wallet.writeContract({
@@ -9855,7 +10097,7 @@ var OwneySDK = class {
9855
10097
  };
9856
10098
 
9857
10099
  // src/agents/zyfai/zyfai.siwx.ts
9858
- var import_viem17 = require("viem");
10100
+ var import_viem18 = require("viem");
9859
10101
  var import_siwe2 = require("siwe");
9860
10102
  var import_sdk2 = require("@zyfai/sdk");
9861
10103
 
@@ -9982,7 +10224,7 @@ function buildSIWXConfig(deps) {
9982
10224
  issuedAt,
9983
10225
  toString() {
9984
10226
  return new import_siwe2.SiweMessage({
9985
- address: (0, import_viem17.getAddress)(accountAddress),
10227
+ address: (0, import_viem18.getAddress)(accountAddress),
9986
10228
  chainId: numericChainId(chainId),
9987
10229
  domain,
9988
10230
  uri,