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

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");
@@ -4227,7 +4302,7 @@ function rpcDiagnostics(data) {
4227
4302
  details.revertName = data.revertName;
4228
4303
  if (typeof data?.aaCode === "string" && /^AA[0-9]{2}$/.test(data.aaCode)) details.aaCode = data.aaCode;
4229
4304
  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));
4305
+ const panicCode = (0, import_viem11.toHex)(BigInt(data.panicCode));
4231
4306
  if (["0x0", "0x1", "0x11", "0x12", "0x21", "0x22", "0x31", "0x32", "0x41", "0x51"].includes(panicCode))
4232
4307
  details.panicCode = panicCode;
4233
4308
  }
@@ -4447,14 +4522,14 @@ async function submitEoa(input) {
4447
4522
  throw sponsorError("Base did not return EIP-1559 gas fees.", true);
4448
4523
  let operation = {
4449
4524
  sender: input.agentWallet,
4450
- nonce: (0, import_viem10.toHex)(nonce),
4525
+ nonce: (0, import_viem11.toHex)(nonce),
4451
4526
  initCode: "0x",
4452
4527
  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),
4528
+ callGasLimit: (0, import_viem11.toHex)(3e5),
4529
+ verificationGasLimit: (0, import_viem11.toHex)(3e5),
4530
+ preVerificationGas: (0, import_viem11.toHex)(6e4),
4531
+ maxFeePerGas: (0, import_viem11.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
4532
+ maxPriorityFeePerGas: (0, import_viem11.toHex)(fees.maxPriorityFeePerGas),
4458
4533
  paymasterAndData: "0x",
4459
4534
  signature: "0x"
4460
4535
  };
@@ -4462,7 +4537,7 @@ async function submitEoa(input) {
4462
4537
  const stub = await rpc(
4463
4538
  input.rpcUrl,
4464
4539
  "pm_getPaymasterStubData",
4465
- [operation, ENTRY_POINT_V06, (0, import_viem10.toHex)(8453), {}],
4540
+ [operation, ENTRY_POINT_V06, (0, import_viem11.toHex)(8453), {}],
4466
4541
  "prepare"
4467
4542
  );
4468
4543
  if (!stub.paymasterAndData?.startsWith("0x"))
@@ -4477,7 +4552,7 @@ async function submitEoa(input) {
4477
4552
  const final = await rpc(
4478
4553
  input.rpcUrl,
4479
4554
  "pm_getPaymasterData",
4480
- [operation, ENTRY_POINT_V06, (0, import_viem10.toHex)(8453), {}],
4555
+ [operation, ENTRY_POINT_V06, (0, import_viem11.toHex)(8453), {}],
4481
4556
  "prepare"
4482
4557
  );
4483
4558
  if (!final.paymasterAndData?.startsWith("0x"))
@@ -4486,10 +4561,10 @@ async function submitEoa(input) {
4486
4561
  }
4487
4562
  const userOpHash = operationHash(operation);
4488
4563
  await assertOwnerSession(input.state, input.owner);
4489
- const wallet = (0, import_viem10.createWalletClient)({
4564
+ const wallet = (0, import_viem11.createWalletClient)({
4490
4565
  account: input.owner,
4491
4566
  chain: import_chains3.base,
4492
- transport: (0, import_viem10.custom)(input.state.provider)
4567
+ transport: (0, import_viem11.custom)(input.state.provider)
4493
4568
  });
4494
4569
  const signature = await wallet.signMessage({ message: { raw: userOpHash } });
4495
4570
  operation = { ...operation, signature };
@@ -4566,12 +4641,12 @@ async function submitSmart(input) {
4566
4641
  } catch {
4567
4642
  throw sponsorError("This account cannot check paymaster support on Base.", true);
4568
4643
  }
4569
- const supportsPaymaster = capabilities?.[(0, import_viem10.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
4644
+ const supportsPaymaster = capabilities?.[(0, import_viem11.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
4570
4645
  if (supportsPaymaster !== true)
4571
4646
  throw sponsorError("This account cannot use a paymaster on Base.", true);
4572
4647
  await assertOwnerSession(input.state, input.owner);
4573
4648
  let sent;
4574
- const requestedId = (0, import_viem10.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
4649
+ const requestedId = (0, import_viem11.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
4575
4650
  savePending(input.onPending, { callsId: requestedId }, true);
4576
4651
  await checkpoint(input.onBeforeSubmission, { callsId: requestedId });
4577
4652
  try {
@@ -4580,7 +4655,7 @@ async function submitSmart(input) {
4580
4655
  params: [{
4581
4656
  version: "2.0.0",
4582
4657
  from: input.owner,
4583
- chainId: (0, import_viem10.toHex)(8453),
4658
+ chainId: (0, import_viem11.toHex)(8453),
4584
4659
  id: requestedId,
4585
4660
  atomicRequired: false,
4586
4661
  calls: [{ to: input.agentWallet, value: "0x0", data: input.callData }],
@@ -4655,7 +4730,7 @@ async function submitSmart(input) {
4655
4730
  );
4656
4731
  }
4657
4732
  async function submitYieldseekerSponsoredWithdrawal(input) {
4658
- const owner = (0, import_viem10.getAddress)(input.state.walletAddress);
4733
+ const owner = (0, import_viem11.getAddress)(input.state.walletAddress);
4659
4734
  const { intent, rpcUrl } = await requestIntent({
4660
4735
  apiKey: input.apiKey,
4661
4736
  routingApiBaseUrl: input.routingApiBaseUrl,
@@ -4673,7 +4748,7 @@ async function submitYieldseekerSponsoredWithdrawal(input) {
4673
4748
  return intent.ownerPath === "eoa" ? submitEoa(args) : submitSmart(args);
4674
4749
  }
4675
4750
  async function submitYieldseekerSponsoredUpgrade(input) {
4676
- const owner = (0, import_viem10.getAddress)(input.state.walletAddress);
4751
+ const owner = (0, import_viem11.getAddress)(input.state.walletAddress);
4677
4752
  const { intent, rpcUrl } = await requestIntent({
4678
4753
  apiKey: input.apiKey,
4679
4754
  routingApiBaseUrl: input.routingApiBaseUrl,
@@ -4790,6 +4865,8 @@ var YieldseekerAgent = class {
4790
4865
  transactionExecutor;
4791
4866
  unwindReceiptWaiter;
4792
4867
  agentContexts = /* @__PURE__ */ new Map();
4868
+ balanceContexts = /* @__PURE__ */ new WeakMap();
4869
+ balanceVaults = /* @__PURE__ */ new Map();
4793
4870
  users = /* @__PURE__ */ new Map();
4794
4871
  pendingAgents = /* @__PURE__ */ new Map();
4795
4872
  pendingWalletContexts = /* @__PURE__ */ new Map();
@@ -4835,8 +4912,8 @@ var YieldseekerAgent = class {
4835
4912
  if (useCachedV2 && cached && Date.now() - cached.at < 15 * 6e4) return { ...cached.status };
4836
4913
  const status = await readYieldseekerWalletStatus(
4837
4914
  this.getReceiptClient(),
4838
- (0, import_viem11.getAddress)(context.wallet.walletAddress),
4839
- (0, import_viem11.getAddress)(state.walletAddress),
4915
+ (0, import_viem12.getAddress)(context.wallet.walletAddress),
4916
+ (0, import_viem12.getAddress)(state.walletAddress),
4840
4917
  YIELDSEEKER_ASSET_METADATA[asset].address
4841
4918
  );
4842
4919
  this.rememberWalletStatus(key2, status);
@@ -4866,12 +4943,12 @@ var YieldseekerAgent = class {
4866
4943
  const pendingKey2 = `owney.yieldseeker.upgrade:${before.owner.toLowerCase()}:${before.agentWallet.toLowerCase()}`;
4867
4944
  const confirmUpgrade = async (hash, receipt2) => {
4868
4945
  this.withdrawalVersionCache.delete(versionKey);
4869
- const upgradeTopic = (0, import_viem11.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
4946
+ const upgradeTopic = (0, import_viem12.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
4870
4947
  const lastUpgrade = receipt2?.logs.filter((log) => log.address.toLowerCase() === before.agentWallet.toLowerCase() && log.topics[0] === upgradeTopic).at(-1);
4871
4948
  const expectedUpgrade = (() => {
4872
4949
  if (!lastUpgrade || lastUpgrade.removed) return false;
4873
4950
  try {
4874
- const event = (0, import_viem11.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
4951
+ const event = (0, import_viem12.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
4875
4952
  return event.args.implementation.toLowerCase() === YIELDSEEKER_V2_IMPLEMENTATION.toLowerCase();
4876
4953
  } catch {
4877
4954
  return false;
@@ -4989,7 +5066,7 @@ var YieldseekerAgent = class {
4989
5066
  { version: before.version },
4990
5067
  this.id
4991
5068
  );
4992
- const data = (0, import_viem11.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
5069
+ const data = (0, import_viem12.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
4993
5070
  let txHash;
4994
5071
  let receipt;
4995
5072
  if (gasMode === "sponsored") {
@@ -5032,7 +5109,7 @@ var YieldseekerAgent = class {
5032
5109
  }
5033
5110
  } else {
5034
5111
  txHash = await this.submitTransaction(state, chainId, {
5035
- from: (0, import_viem11.getAddress)(state.walletAddress),
5112
+ from: (0, import_viem12.getAddress)(state.walletAddress),
5036
5113
  to: before.agentWallet,
5037
5114
  data,
5038
5115
  value: "0",
@@ -5055,6 +5132,7 @@ var YieldseekerAgent = class {
5055
5132
  }
5056
5133
  this.users.clear();
5057
5134
  this.agentContexts.clear();
5135
+ this.balanceVaults.clear();
5058
5136
  this.pendingAgents.clear();
5059
5137
  this.pendingWalletContexts.clear();
5060
5138
  this.readCache.clear();
@@ -5118,12 +5196,12 @@ var YieldseekerAgent = class {
5118
5196
  } else {
5119
5197
  try {
5120
5198
  txHash = await this.submitTransaction(state, chainId, {
5121
- from: (0, import_viem11.getAddress)(state.walletAddress),
5199
+ from: (0, import_viem12.getAddress)(state.walletAddress),
5122
5200
  to: YIELDSEEKER_ASSET_METADATA[asset].address,
5123
- data: (0, import_viem11.encodeFunctionData)({
5124
- abi: import_viem11.erc20Abi,
5201
+ data: (0, import_viem12.encodeFunctionData)({
5202
+ abi: import_viem12.erc20Abi,
5125
5203
  functionName: "transfer",
5126
- args: [(0, import_viem11.getAddress)(context.wallet.walletAddress), BigInt(amount)]
5204
+ args: [(0, import_viem12.getAddress)(context.wallet.walletAddress), BigInt(amount)]
5127
5205
  }),
5128
5206
  value: "0",
5129
5207
  chainId
@@ -5257,7 +5335,7 @@ var YieldseekerAgent = class {
5257
5335
  );
5258
5336
  const positionsRead = this.readWithdrawalPositions(state, chainId, context);
5259
5337
  const metadata = YIELDSEEKER_ASSET_METADATA[asset];
5260
- const agentWallet = (0, import_viem11.getAddress)(context.wallet.walletAddress);
5338
+ const agentWallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
5261
5339
  const readOwnerFunds = async (blockNumber) => {
5262
5340
  const feeTracker = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5263
5341
  address: agentWallet,
@@ -5266,18 +5344,18 @@ var YieldseekerAgent = class {
5266
5344
  blockNumber
5267
5345
  }), chainId, "eth_call", this.id);
5268
5346
  this.assertSession(generation, chainId, asset);
5269
- if (!(0, import_viem11.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
5347
+ if (!(0, import_viem12.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
5270
5348
  throw this.invalidResponse("wallet fee tracker");
5271
5349
  const [idle2, fees] = await Promise.all([
5272
5350
  withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5273
5351
  address: metadata.address,
5274
- abi: import_viem11.erc20Abi,
5352
+ abi: import_viem12.erc20Abi,
5275
5353
  functionName: "balanceOf",
5276
5354
  args: [agentWallet],
5277
5355
  blockNumber
5278
5356
  }), chainId, "eth_call", this.id),
5279
5357
  withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5280
- address: (0, import_viem11.getAddress)(feeTracker),
5358
+ address: (0, import_viem12.getAddress)(feeTracker),
5281
5359
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
5282
5360
  functionName: "getFeesOwed",
5283
5361
  args: [agentWallet],
@@ -5319,13 +5397,13 @@ var YieldseekerAgent = class {
5319
5397
  let active = true;
5320
5398
  const checks = this.readVaultLiquidity(values.map((position2) => position2.yieldOption), agentWallet, blockNumber).catch(() => []);
5321
5399
  const reads = values.map(async (position2, index) => {
5322
- const address = (0, import_viem11.getAddress)(position2.yieldOption.address);
5400
+ const address = (0, import_viem12.getAddress)(position2.yieldOption.address);
5323
5401
  try {
5324
5402
  const group = (await checks).slice(index * 3, index * 3 + 3);
5325
5403
  if (!active || group.length !== 3 || group.some((value) => value.status !== "success")) return null;
5326
5404
  this.assertSession(generation, chainId, asset);
5327
5405
  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;
5406
+ 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
5407
  const verified = { ...position2, assetsRaw: shares.toString(), withdrawableAssetsRaw: withdrawable.toString() };
5330
5408
  if (shares > 0n && withdrawable === 0n) {
5331
5409
  let positiveValue = false;
@@ -5333,7 +5411,7 @@ var YieldseekerAgent = class {
5333
5411
  try {
5334
5412
  const value = await this.getReceiptClient().readContract({
5335
5413
  address,
5336
- abi: import_viem11.erc4626Abi,
5414
+ abi: import_viem12.erc4626Abi,
5337
5415
  functionName,
5338
5416
  args: [shares],
5339
5417
  blockNumber
@@ -5546,14 +5624,14 @@ var YieldseekerAgent = class {
5546
5624
  delta: maxSettlementBasis.delta - payout,
5547
5625
  expectedNetDeposits: maxSettlementBasis.expectedNetDeposits - payout
5548
5626
  } : this.snapshotMovement(state, chainId, context, -payout);
5549
- const account = (0, import_viem11.getAddress)(state.walletAddress);
5627
+ const account = (0, import_viem12.getAddress)(state.walletAddress);
5550
5628
  let receipt;
5551
5629
  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)({
5630
+ const data = amount === void 0 ? (0, import_viem12.encodeFunctionData)({
5553
5631
  abi: YIELDSEEKER_AGENT_WALLET_ABI,
5554
5632
  functionName: "withdrawAllAssetToUser",
5555
5633
  args: [account, metadata.address]
5556
- }) : (0, import_viem11.encodeFunctionData)({
5634
+ }) : (0, import_viem12.encodeFunctionData)({
5557
5635
  abi: YIELDSEEKER_AGENT_WALLET_ABI,
5558
5636
  functionName: "withdrawAssetToUser",
5559
5637
  args: [account, metadata.address, payout]
@@ -5569,7 +5647,7 @@ var YieldseekerAgent = class {
5569
5647
  refreshYieldseekerSignature: (rejected) => this.auth.refreshToken(state, chainId, rejected),
5570
5648
  userId: context.user.userId,
5571
5649
  agentId: context.agent.agentId,
5572
- agentWallet: (0, import_viem11.getAddress)(context.wallet.walletAddress),
5650
+ agentWallet: (0, import_viem12.getAddress)(context.wallet.walletAddress),
5573
5651
  asset: metadata.address,
5574
5652
  callData: data,
5575
5653
  onPending: (pending) => notifyFunding(onProgress, { ...base6, ...pending }),
@@ -5584,7 +5662,7 @@ var YieldseekerAgent = class {
5584
5662
  onOwnerTransferAttempted?.();
5585
5663
  txHash = await this.submitTransaction(state, chainId, {
5586
5664
  from: account,
5587
- to: (0, import_viem11.getAddress)(context.wallet.walletAddress),
5665
+ to: (0, import_viem12.getAddress)(context.wallet.walletAddress),
5588
5666
  data,
5589
5667
  value: "0",
5590
5668
  chainId
@@ -5692,17 +5770,17 @@ var YieldseekerAgent = class {
5692
5770
  return proof.available;
5693
5771
  }
5694
5772
  async readVaultLiquidity(options, wallet, blockNumber) {
5695
- const owner = (0, import_viem11.getAddress)(wallet);
5773
+ const owner = (0, import_viem12.getAddress)(wallet);
5696
5774
  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
5775
  const results = await Promise.all(batches.map((batch) => this.getReceiptClient().multicall({
5698
5776
  blockNumber,
5699
5777
  allowFailure: true,
5700
5778
  contracts: batch.flatMap((option) => {
5701
- const address = (0, import_viem11.getAddress)(option.address);
5779
+ const address = (0, import_viem12.getAddress)(option.address);
5702
5780
  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] }
5781
+ { address, abi: import_viem12.erc4626Abi, functionName: "asset" },
5782
+ { address, abi: import_viem12.erc20Abi, functionName: "balanceOf", args: [owner] },
5783
+ { address, abi: import_viem12.erc4626Abi, functionName: "maxWithdraw", args: [owner] }
5706
5784
  ];
5707
5785
  })
5708
5786
  })));
@@ -5713,7 +5791,7 @@ var YieldseekerAgent = class {
5713
5791
  const seen = /* @__PURE__ */ new Set();
5714
5792
  for (const value of values) {
5715
5793
  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))
5794
+ 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
5795
  throw this.invalidResponse("yield positions");
5718
5796
  seen.add(option.address.toLowerCase());
5719
5797
  }
@@ -5726,7 +5804,7 @@ var YieldseekerAgent = class {
5726
5804
  const historic = this.readCache.get(`historic:${key2}`)?.value?.position;
5727
5805
  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
5806
  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;
5807
+ 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
5808
  hints.set(option.address.toLowerCase(), {
5731
5809
  yieldOption: option,
5732
5810
  assetsRaw: "0",
@@ -5778,7 +5856,7 @@ var YieldseekerAgent = class {
5778
5856
  const read2 = async () => {
5779
5857
  const client = this.getReceiptClient();
5780
5858
  const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
5781
- const wallet = (0, import_viem11.getAddress)(context.wallet.walletAddress);
5859
+ const wallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
5782
5860
  assertReadCurrent();
5783
5861
  if (typeof blockNumber !== "bigint") throw unavailable();
5784
5862
  const indexedPositions = this.validateWithdrawalPositions(positions ?? [], chainId, context.asset);
@@ -5792,7 +5870,7 @@ var YieldseekerAgent = class {
5792
5870
  this.readVaultLiquidity(options, wallet, blockNumber),
5793
5871
  client.readContract({
5794
5872
  address: metadata.address,
5795
- abi: import_viem11.erc20Abi,
5873
+ abi: import_viem12.erc20Abi,
5796
5874
  functionName: "balanceOf",
5797
5875
  args: [wallet],
5798
5876
  blockNumber
@@ -5804,10 +5882,10 @@ var YieldseekerAgent = class {
5804
5882
  blockNumber
5805
5883
  })
5806
5884
  ]);
5807
- if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem11.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
5885
+ if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem12.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
5808
5886
  assertReadCurrent();
5809
5887
  const fees = await client.readContract({
5810
- address: (0, import_viem11.getAddress)(feeTracker),
5888
+ address: (0, import_viem12.getAddress)(feeTracker),
5811
5889
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
5812
5890
  functionName: "getFeesOwed",
5813
5891
  args: [wallet],
@@ -5818,15 +5896,21 @@ var YieldseekerAgent = class {
5818
5896
  const verifiedVaults = [];
5819
5897
  let deployed = 0n;
5820
5898
  const collect = (options2, results) => {
5899
+ assertReadCurrent();
5900
+ const known = this.balanceVaults.get(contextKey) ?? /* @__PURE__ */ new Set();
5901
+ this.balanceVaults.set(contextKey, known);
5821
5902
  let valid2 = true;
5822
5903
  options2.forEach((option, index) => {
5823
5904
  const group = results.slice(index * 3, index * 3 + 3);
5905
+ const shareProbe = group[1];
5906
+ if (shareProbe?.status === "success" && typeof shareProbe.result === "bigint" && shareProbe.result > 0n)
5907
+ known.add(option.address.toLowerCase());
5824
5908
  if (group.length !== 3 || group.some((value) => value.status !== "success")) {
5825
5909
  valid2 = false;
5826
5910
  return;
5827
5911
  }
5828
5912
  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) {
5913
+ 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
5914
  valid2 = false;
5831
5915
  return;
5832
5916
  }
@@ -5870,7 +5954,7 @@ var YieldseekerAgent = class {
5870
5954
  assertReadCurrent();
5871
5955
  const eligible = /* @__PURE__ */ new Map();
5872
5956
  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))
5957
+ if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem12.isAddress)(option.address))
5874
5958
  eligible.set(option.address.toLowerCase(), option);
5875
5959
  }
5876
5960
  const extra = [...eligible].filter(([address]) => !candidates.has(address)).map(([, option]) => option);
@@ -5899,7 +5983,59 @@ var YieldseekerAgent = class {
5899
5983
  async getBalances(state, chainId, asset) {
5900
5984
  this.assertChain(chainId);
5901
5985
  if (asset !== void 0) this.assertAsset(asset);
5902
- return mapYieldseekerBalances(await this.loadPortfolio(state, chainId, { asset, allowMissingPositions: true }));
5986
+ const contexts = await this.loadPortfolio(state, chainId, { asset, allowMissingPositions: true });
5987
+ const balance = mapYieldseekerBalances(contexts);
5988
+ for (const context of contexts) {
5989
+ const read2 = balance.readMetadata.find((item) => item.asset === context.asset);
5990
+ this.balanceContexts.set(read2, { context, generation: this.readGeneration });
5991
+ const key2 = this.contextKey(state, chainId, context.asset);
5992
+ const known = this.balanceVaults.get(key2) ?? /* @__PURE__ */ new Set();
5993
+ for (const position2 of context.positions) known.add(position2.yieldOption.address.toLowerCase());
5994
+ this.balanceVaults.set(key2, known);
5995
+ }
5996
+ return balance;
5997
+ }
5998
+ async verifyWithdrawalBalance(state, evidence, balance) {
5999
+ this.assertAsset(evidence.token);
6000
+ this.assertChain(evidence.chainId);
6001
+ const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
6002
+ const cached = read2 && this.balanceContexts.get(read2);
6003
+ const context = cached?.generation === this.readGeneration ? cached.context : void 0;
6004
+ if (!context || context.positionsUnavailable || !read2 || !evidence.blockNumber || !evidence.txHash || context.wallet.walletAddress.toLowerCase() !== evidence.agentWallet?.toLowerCase()) return void 0;
6005
+ const key2 = this.contextKey(state, evidence.chainId, evidence.token);
6006
+ const generation = this.readGeneration, version = this.portfolioVersion(key2);
6007
+ if (read2.readVersion !== version) return void 0;
6008
+ const wallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
6009
+ const asset = YIELDSEEKER_ASSET_METADATA[evidence.token];
6010
+ const client = this.getReceiptClient();
6011
+ const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
6012
+ if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
6013
+ const vaults = [...this.balanceVaults.get(key2) ?? []];
6014
+ const [invested, idle, tracker] = await Promise.all([
6015
+ remainingVaultBalance(client, wallet, asset.address, vaults, blockNumber),
6016
+ client.readContract({ address: asset.address, abi: import_viem12.erc20Abi, functionName: "balanceOf", args: [wallet], blockNumber }),
6017
+ client.readContract({ address: wallet, abi: YIELDSEEKER_AGENT_WALLET_ABI, functionName: "feeTracker", blockNumber })
6018
+ ]);
6019
+ if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0, import_viem12.isAddress)(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
6020
+ const fees = await client.readContract({
6021
+ address: tracker,
6022
+ abi: YIELDSEEKER_FEE_TRACKER_ABI,
6023
+ functionName: "getFeesOwed",
6024
+ args: [wallet],
6025
+ blockNumber
6026
+ });
6027
+ this.assertSession(generation, evidence.chainId, evidence.token);
6028
+ if (version !== this.portfolioVersion(key2) || typeof fees !== "bigint" || fees < 0n) return void 0;
6029
+ const total = idle + invested > fees ? idle + invested - fees : 0n;
6030
+ const displayed = balance.assetBalances?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
6031
+ if (!displayed || !evidence.confirmedAmount || !/^\d+$/.test(evidence.confirmedAmount)) return void 0;
6032
+ const amount = (0, import_viem12.parseUnits)(displayed.amount, asset.decimals);
6033
+ if (amount < 0n) return void 0;
6034
+ const displayUnit = evidence.token === "USDC" ? 5000n : 500000000000n;
6035
+ const movementUnit = BigInt(evidence.confirmedAmount) / 1000n;
6036
+ const tolerance = movementUnit < displayUnit ? movementUnit : displayUnit;
6037
+ if ((total > amount ? total - amount : amount - total) > tolerance) return void 0;
6038
+ return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
5903
6039
  }
5904
6040
  invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS) {
5905
6041
  this.assertAsset(asset);
@@ -5939,9 +6075,9 @@ var YieldseekerAgent = class {
5939
6075
  if (!context) return void 0;
5940
6076
  const idle = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5941
6077
  address: YIELDSEEKER_ASSET_METADATA[asset].address,
5942
- abi: import_viem11.erc20Abi,
6078
+ abi: import_viem12.erc20Abi,
5943
6079
  functionName: "balanceOf",
5944
- args: [(0, import_viem11.getAddress)(context.wallet.walletAddress)]
6080
+ args: [(0, import_viem12.getAddress)(context.wallet.walletAddress)]
5945
6081
  }), chainId, "eth_call", this.id);
5946
6082
  this.assertSession(generation, chainId, asset);
5947
6083
  if (typeof idle !== "bigint" || idle < 0n) throw this.invalidResponse("wallet deposit balance");
@@ -5977,7 +6113,7 @@ var YieldseekerAgent = class {
5977
6113
  );
5978
6114
  const vaultAddresses = new Set(
5979
6115
  catalog.flat().filter(
5980
- (yieldOption) => yieldOption.chainId === chainId && (0, import_viem11.isAddress)(yieldOption.address)
6116
+ (yieldOption) => yieldOption.chainId === chainId && (0, import_viem12.isAddress)(yieldOption.address)
5981
6117
  ).map((yieldOption) => yieldOption.address.toLowerCase())
5982
6118
  );
5983
6119
  return mapYieldseekerHistory(contexts, {
@@ -6053,11 +6189,13 @@ var YieldseekerAgent = class {
6053
6189
  const pending = this.pendingReads.get(key2);
6054
6190
  if (pending) return pending;
6055
6191
  const generation = this.readGeneration;
6192
+ const requestedAt = Date.now();
6056
6193
  const request = Promise.resolve().then(read2).then((value) => {
6057
6194
  if (this.readGeneration === generation && this.pendingReads.get(key2) === request) {
6058
6195
  this.readCache.set(key2, {
6059
6196
  expiresAt: Date.now() + ttlMs,
6060
6197
  fetchedAt: Date.now(),
6198
+ requestedAt,
6061
6199
  value
6062
6200
  });
6063
6201
  }
@@ -6104,7 +6242,7 @@ var YieldseekerAgent = class {
6104
6242
  `/users/${user.userId}/agents/${agent.agentId}/wallet`
6105
6243
  ).then((walletResponse) => {
6106
6244
  this.assertSession(generation, chainId, asset);
6107
- if (!walletResponse?.agentWallet || !(0, import_viem11.isAddress)(walletResponse.agentWallet.walletAddress)) {
6245
+ if (!walletResponse?.agentWallet || !(0, import_viem12.isAddress)(walletResponse.agentWallet.walletAddress)) {
6108
6246
  throw this.invalidResponse("agent wallet");
6109
6247
  }
6110
6248
  const context = {
@@ -6134,7 +6272,7 @@ var YieldseekerAgent = class {
6134
6272
  this.users.set(key2, persisted);
6135
6273
  return persisted;
6136
6274
  }
6137
- const walletAddress = (0, import_viem11.getAddress)(state.walletAddress);
6275
+ const walletAddress = (0, import_viem12.getAddress)(state.walletAddress);
6138
6276
  const generation = this.readGeneration;
6139
6277
  let user = null;
6140
6278
  try {
@@ -6426,6 +6564,7 @@ var YieldseekerAgent = class {
6426
6564
  ...context,
6427
6565
  snapshot: snapshot.agentSnapshot,
6428
6566
  fetchedAt: this.readCache.get(`snapshot:${contextKey}`)?.fetchedAt,
6567
+ requestedAt: this.readCache.get(`snapshot:${contextKey}`)?.requestedAt,
6429
6568
  readVersion: version,
6430
6569
  positionsUnavailable,
6431
6570
  ...portfolioParts
@@ -6517,7 +6656,7 @@ var YieldseekerAgent = class {
6517
6656
  this.agentPath(context, "deploy"),
6518
6657
  { method: "POST", body: {} }
6519
6658
  );
6520
- if (!deployed?.agentWallet || !(0, import_viem11.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
6659
+ if (!deployed?.agentWallet || !(0, import_viem12.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
6521
6660
  throw this.invalidResponse("agent deployment", {
6522
6661
  reason: "Deploy did not return the expected Agent Wallet."
6523
6662
  });
@@ -6625,15 +6764,15 @@ var YieldseekerAgent = class {
6625
6764
  return hash2;
6626
6765
  }
6627
6766
  this.assertTransaction(transaction, state, chainId);
6628
- const account = (0, import_viem11.getAddress)(state.walletAddress);
6629
- const walletClient = (0, import_viem11.createWalletClient)({
6767
+ const account = (0, import_viem12.getAddress)(state.walletAddress);
6768
+ const walletClient = (0, import_viem12.createWalletClient)({
6630
6769
  account,
6631
6770
  chain: import_chains4.base,
6632
- transport: (0, import_viem11.custom)(state.provider)
6771
+ transport: (0, import_viem12.custom)(state.provider)
6633
6772
  });
6634
- const walletChainClient = (0, import_viem11.createPublicClient)({
6773
+ const walletChainClient = (0, import_viem12.createPublicClient)({
6635
6774
  chain: import_chains4.base,
6636
- transport: (0, import_viem11.custom)(state.provider)
6775
+ transport: (0, import_viem12.custom)(state.provider)
6637
6776
  });
6638
6777
  await ensureWalletOnChain(
6639
6778
  walletChainClient,
@@ -6643,7 +6782,7 @@ var YieldseekerAgent = class {
6643
6782
  const hash = await walletClient.sendTransaction({
6644
6783
  account,
6645
6784
  chain: import_chains4.base,
6646
- to: (0, import_viem11.getAddress)(transaction.to),
6785
+ to: (0, import_viem12.getAddress)(transaction.to),
6647
6786
  data: transaction.data,
6648
6787
  value: BigInt(transaction.value)
6649
6788
  });
@@ -6747,12 +6886,12 @@ var YieldseekerAgent = class {
6747
6886
  return receipt;
6748
6887
  }
6749
6888
  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)) {
6889
+ 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
6890
  throw this.invalidResponse("transaction");
6752
6891
  }
6753
6892
  }
6754
6893
  assertAgent(agent) {
6755
- if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem11.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
6894
+ if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem12.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
6756
6895
  throw this.invalidResponse("agent");
6757
6896
  }
6758
6897
  }
@@ -6906,7 +7045,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
6906
7045
  }
6907
7046
 
6908
7047
  // src/lib/helpers/withdraw-helper.ts
6909
- var import_viem12 = require("viem");
7048
+ var import_viem13 = require("viem");
6910
7049
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
6911
7050
  const target = asset.toUpperCase();
6912
7051
  return agents.map((agent) => {
@@ -6914,7 +7053,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
6914
7053
  const tokenBalance = agentBalance?.tokens.find(
6915
7054
  (t) => t.chainId === chainId && t.asset.toUpperCase() === target
6916
7055
  );
6917
- let balance = tokenBalance ? (0, import_viem12.parseUnits)(tokenBalance.amount, decimals) : 0n;
7056
+ let balance = tokenBalance ? (0, import_viem13.parseUnits)(tokenBalance.amount, decimals) : 0n;
6918
7057
  if (agent.balanceComposition === "tokens-plus-positions") {
6919
7058
  const chainNameById = {
6920
7059
  1: "ETHEREUM",
@@ -6926,14 +7065,14 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
6926
7065
  const positionChain = position2.chain.trim().toUpperCase();
6927
7066
  const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
6928
7067
  if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
6929
- balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0, import_viem12.parseUnits)(position2.amount, decimals);
7068
+ balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0, import_viem13.parseUnits)(position2.amount, decimals);
6930
7069
  }
6931
7070
  }
6932
7071
  const assetTotal = agentBalance?.assetBalances?.find(
6933
7072
  (t) => t.chainId === chainId && t.asset.toUpperCase() === target
6934
7073
  );
6935
7074
  if (assetTotal) {
6936
- const total = (0, import_viem12.parseUnits)(assetTotal.amount, decimals);
7075
+ const total = (0, import_viem13.parseUnits)(assetTotal.amount, decimals);
6937
7076
  if (total < balance) balance = total > 0n ? total : 0n;
6938
7077
  }
6939
7078
  return { agent, balance };
@@ -7092,14 +7231,14 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
7092
7231
  }
7093
7232
 
7094
7233
  // src/client.ts
7095
- var import_viem16 = require("viem");
7234
+ var import_viem17 = require("viem");
7096
7235
  var import_chains5 = require("viem/chains");
7097
7236
 
7098
7237
  // src/lib/sponsored-token-batch.ts
7099
- var import_viem14 = require("viem");
7238
+ var import_viem15 = require("viem");
7100
7239
 
7101
7240
  // src/lib/permit2-batch.ts
7102
- var import_viem13 = require("viem");
7241
+ var import_viem14 = require("viem");
7103
7242
  var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
7104
7243
  var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
7105
7244
  var ERC2612_PERMIT_TYPES = {
@@ -7111,7 +7250,7 @@ var ERC2612_PERMIT_TYPES = {
7111
7250
  { name: "deadline", type: "uint256" }
7112
7251
  ]
7113
7252
  };
7114
- var ERC2612_READ_ABI = (0, import_viem13.parseAbi)([
7253
+ var ERC2612_READ_ABI = (0, import_viem14.parseAbi)([
7115
7254
  "function name() view returns (string)",
7116
7255
  "function version() view returns (string)",
7117
7256
  "function nonces(address owner) view returns (uint256)"
@@ -7149,7 +7288,7 @@ var PERMIT_BATCH_TYPES = {
7149
7288
  { name: "amount", type: "uint256" }
7150
7289
  ]
7151
7290
  };
7152
- var PERMIT2_BATCH_ABI = (0, import_viem13.parseAbi)([
7291
+ var PERMIT2_BATCH_ABI = (0, import_viem14.parseAbi)([
7153
7292
  "struct TokenPermissions { address token; uint256 amount; }",
7154
7293
  "struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
7155
7294
  "struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
@@ -7192,14 +7331,14 @@ var planOf = (transfers) => JSON.stringify(
7192
7331
  amount: BigInt(t.amount).toString()
7193
7332
  }))
7194
7333
  );
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()}`;
7334
+ 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
7335
  function pendingTokenBatch(i) {
7197
7336
  try {
7198
7337
  const saved = read(pendingKey(i));
7199
7338
  if (!saved) return;
7200
7339
  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 })) };
7340
+ 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;
7341
+ return { txHash: (0, import_viem15.keccak256)(body.serializedTransaction), transfers: body.transfers.map(({ to, amount }) => ({ to, amount })) };
7203
7342
  } catch {
7204
7343
  return;
7205
7344
  }
@@ -7244,14 +7383,47 @@ async function execute(i, key2, plan) {
7244
7383
  const send = async (initial) => {
7245
7384
  let body = initial;
7246
7385
  save(key2, body);
7386
+ 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
7387
  try {
7388
+ const post = () => postSponsorBatchTransfer({ apiKey: i.apiKey, baseUrl: i.baseUrl, body });
7389
+ const pendingError = (phase, txHash) => new OwneyError(
7390
+ "DEPOSIT_IN_PROGRESS",
7391
+ phase === "approval" ? "Deposit approval is awaiting confirmation. Retry the same amount to continue it." : "Deposit is awaiting confirmation. Its transaction is still being checked.",
7392
+ { sponsorPending: true, phase, txHash, safeToFallback: false }
7393
+ );
7394
+ const assertReceipt = (receipt, phase) => {
7395
+ if (receipt.status !== "success") throw new OwneyError(
7396
+ "SPONSOR_REQUEST_FAILED",
7397
+ `Sponsored ${phase} transaction reverted. Please retry.`,
7398
+ { notSubmitted: true, safeToFallback: false }
7399
+ );
7400
+ };
7401
+ const waitForConfirmation = async (phase, hash2) => {
7402
+ let receipt;
7403
+ try {
7404
+ receipt = await i.pub.waitForTransactionReceipt({ hash: hash2, confirmations: 1, timeout: 9e4, checkReplacement: false });
7405
+ } catch {
7406
+ receipt = await i.pub.getTransactionReceipt({ hash: hash2 }).catch(() => void 0);
7407
+ }
7408
+ if (!receipt) throw pendingError(phase, hash2);
7409
+ assertReceipt(receipt, phase);
7410
+ };
7411
+ const postSigned = async (phase, hash2) => {
7412
+ try {
7413
+ return await post();
7414
+ } catch (error) {
7415
+ if (rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true) throw error;
7416
+ await waitForConfirmation(phase, hash2);
7417
+ return void 0;
7418
+ }
7419
+ };
7248
7420
  if (body.erc2612Permit && !body.serializedPermitTransaction) {
7249
7421
  const preparedPermit = await postSponsorBatchTransfer({
7250
7422
  apiKey: i.apiKey,
7251
7423
  baseUrl: i.baseUrl,
7252
7424
  body
7253
7425
  });
7254
- if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem14.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
7426
+ if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem15.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
7255
7427
  throw new Error(
7256
7428
  "Sponsorship API did not return a valid prepared permit transaction."
7257
7429
  );
@@ -7262,12 +7434,18 @@ async function execute(i, key2, plan) {
7262
7434
  save(key2, body);
7263
7435
  }
7264
7436
  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)
7437
+ const permitHash = body.serializedPermitTransaction ? (0, import_viem15.keccak256)(body.serializedPermitTransaction) : void 0;
7438
+ let prepared = permitHash ? await postSigned("approval", permitHash) : await post();
7439
+ if (prepared?.status === "pending") {
7440
+ if (!permitHash || prepared.phase !== "approval" || prepared.txHash !== permitHash)
7441
+ throw new Error("Sponsorship approval does not match the pending transaction.");
7442
+ await waitForConfirmation("approval", permitHash);
7443
+ prepared = void 0;
7444
+ }
7445
+ if (!prepared) prepared = await post();
7446
+ if (prepared.status === "pending" && permitHash && prepared.phase === "approval" && prepared.txHash === permitHash)
7447
+ throw pendingError("approval", permitHash);
7448
+ if (!prepared.serializedTransaction || (0, import_viem15.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
7271
7449
  throw new Error(
7272
7450
  "Sponsorship API did not return a valid prepared transaction."
7273
7451
  );
@@ -7278,22 +7456,33 @@ async function execute(i, key2, plan) {
7278
7456
  save(key2, body);
7279
7457
  }
7280
7458
  try {
7281
- i.onSubmitted?.((0, import_viem14.keccak256)(body.serializedTransaction));
7459
+ i.onSubmitted?.((0, import_viem15.keccak256)(body.serializedTransaction));
7282
7460
  } catch {
7283
7461
  }
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
- );
7462
+ const hash = (0, import_viem15.keccak256)(body.serializedTransaction);
7463
+ const existing = await i.pub.getTransactionReceipt({ hash }).catch(() => void 0);
7464
+ if (existing) {
7465
+ assertReceipt(existing, "deposit");
7466
+ void post().catch(() => void 0);
7467
+ clear(key2);
7468
+ return hash;
7469
+ }
7470
+ let result = await postSigned("deposit", hash);
7471
+ if (result?.status === "pending" && result.phase === "approval" && body.serializedPermitTransaction && result.txHash === (0, import_viem15.keccak256)(body.serializedPermitTransaction)) {
7472
+ await waitForConfirmation("approval", result.txHash);
7473
+ result = await postSigned("deposit", hash);
7474
+ if (result?.status === "pending" && result.phase === "approval" && result.txHash === (0, import_viem15.keccak256)(body.serializedPermitTransaction)) throw pendingError("approval", result.txHash);
7475
+ }
7476
+ if (result) {
7477
+ if (result.txHash !== hash || result.status === "pending" && result.phase !== "deposit")
7478
+ throw new Error("Sponsorship receipt does not match the pending transaction.");
7479
+ if (result.status === "pending") await waitForConfirmation("deposit", hash);
7480
+ }
7481
+ if (!result || result.status === "pending") void post().catch(() => void 0);
7293
7482
  clear(key2);
7294
- return result.txHash;
7483
+ return hash;
7295
7484
  } catch (error) {
7296
- if (!body.serializedTransaction || error instanceof OwneyError && error.details?.notSubmitted === true)
7485
+ if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
7297
7486
  clear(key2);
7298
7487
  throw error;
7299
7488
  }
@@ -7303,7 +7492,7 @@ async function execute(i, key2, plan) {
7303
7492
  throw new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit changed. Check its status before depositing again.");
7304
7493
  if (saved) {
7305
7494
  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)
7495
+ 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
7496
  throw new Error(
7308
7497
  "Retry the previous token deposit and agent split first to reconcile its status."
7309
7498
  );
@@ -7320,7 +7509,7 @@ async function execute(i, key2, plan) {
7320
7509
  "DEPOSIT_INSUFFICIENT_BALANCE",
7321
7510
  "Insufficient token balance for this deposit."
7322
7511
  );
7323
- if (allowance < total && (i.chainId !== 8453 || !(0, import_viem14.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
7512
+ if (allowance < total && (i.chainId !== 8453 || !(0, import_viem15.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
7324
7513
  throw new OwneyError(
7325
7514
  "PERMIT2_APPROVAL_REQUIRED",
7326
7515
  "token deposits need a one-time Permit2 approval."
@@ -7499,7 +7688,7 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
7499
7688
  }
7500
7689
 
7501
7690
  // src/lib/sponsored-calls-deposit.ts
7502
- var import_viem15 = require("viem");
7691
+ var import_viem16 = require("viem");
7503
7692
  var DEFAULT_POLL_INTERVAL_MS = 1500;
7504
7693
  var DEFAULT_MAX_POLLS = 30;
7505
7694
  async function paymasterSupported(provider, owner, chainId) {
@@ -7507,7 +7696,7 @@ async function paymasterSupported(provider, owner, chainId) {
7507
7696
  method: "wallet_getCapabilities",
7508
7697
  params: [owner]
7509
7698
  });
7510
- const forChain = caps?.[(0, import_viem15.toHex)(chainId)] ?? caps?.[String(chainId)];
7699
+ const forChain = caps?.[(0, import_viem16.toHex)(chainId)] ?? caps?.[String(chainId)];
7511
7700
  return Boolean(forChain?.paymasterService?.supported);
7512
7701
  }
7513
7702
  function makeSponsoredCallsCallback(deps) {
@@ -7544,8 +7733,8 @@ function makeSponsoredCallsCallback(deps) {
7544
7733
  const calls = transfers.map((transfer) => ({
7545
7734
  to: token,
7546
7735
  value: "0x0",
7547
- data: (0, import_viem15.encodeFunctionData)({
7548
- abi: import_viem15.erc20Abi,
7736
+ data: (0, import_viem16.encodeFunctionData)({
7737
+ abi: import_viem16.erc20Abi,
7549
7738
  functionName: "transfer",
7550
7739
  args: [transfer.to, BigInt(transfer.amount)]
7551
7740
  })
@@ -7577,7 +7766,7 @@ function makeSponsoredCallsCallback(deps) {
7577
7766
  url.searchParams.append("owneyIntent", intent);
7578
7767
  paymasterUrl = url.toString();
7579
7768
  }
7580
- const requestedId = (0, import_viem15.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
7769
+ const requestedId = (0, import_viem16.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
7581
7770
  const progress = (id, transfer) => {
7582
7771
  try {
7583
7772
  deps.onCallsProgress?.(id, transfers, transfer);
@@ -7594,7 +7783,7 @@ function makeSponsoredCallsCallback(deps) {
7594
7783
  version: "2.0.0",
7595
7784
  id: requestedId,
7596
7785
  from: deps.ownerAddress,
7597
- chainId: (0, import_viem15.toHex)(chainId),
7786
+ chainId: (0, import_viem16.toHex)(chainId),
7598
7787
  atomicRequired: transfers.length > 1,
7599
7788
  calls,
7600
7789
  capabilities: {
@@ -7746,6 +7935,7 @@ var OwneySDK = class {
7746
7935
  cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
7747
7936
  agentReads = new AgentReads();
7748
7937
  recoveredFundingReads = /* @__PURE__ */ new Set();
7938
+ fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
7749
7939
  activationChecks = /* @__PURE__ */ new Map();
7750
7940
  readAgent(agent, method, fetch2, params = null) {
7751
7941
  const key2 = JSON.stringify([
@@ -7791,6 +7981,7 @@ var OwneySDK = class {
7791
7981
  }
7792
7982
  this.agentReads.clearInFlight();
7793
7983
  this.activationChecks.clear();
7984
+ this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
7794
7985
  this.state = { provider, walletAddress, chainId: null };
7795
7986
  this.cachedSponsoredCallback = null;
7796
7987
  this.cachedWethSponsoredCallback = null;
@@ -7802,6 +7993,7 @@ var OwneySDK = class {
7802
7993
  */
7803
7994
  async disconnect() {
7804
7995
  this.state = null;
7996
+ this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
7805
7997
  for (const agent of this.agents.values()) {
7806
7998
  await agent.disconnect();
7807
7999
  }
@@ -7876,14 +8068,14 @@ var OwneySDK = class {
7876
8068
  // PublicClient/WalletClient param types — structurally identical at
7877
8069
  // runtime, but the two share a name TS treats as unrelated.
7878
8070
  getPublicClient: (cid) => this.getPaidRpcClient(cid),
7879
- getWalletChainClient: (cid) => (0, import_viem16.createPublicClient)({
8071
+ getWalletChainClient: (cid) => (0, import_viem17.createPublicClient)({
7880
8072
  chain: VIEM_CHAIN2[cid],
7881
- transport: (0, import_viem16.custom)(provider)
8073
+ transport: (0, import_viem17.custom)(provider)
7882
8074
  }),
7883
- getWalletClient: (cid) => (0, import_viem16.createWalletClient)({
8075
+ getWalletClient: (cid) => (0, import_viem17.createWalletClient)({
7884
8076
  account: owner,
7885
8077
  chain: VIEM_CHAIN2[cid],
7886
- transport: (0, import_viem16.custom)(provider)
8078
+ transport: (0, import_viem17.custom)(provider)
7887
8079
  })
7888
8080
  });
7889
8081
  if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedSponsoredCallback = callback;
@@ -7931,14 +8123,14 @@ var OwneySDK = class {
7931
8123
  // PublicClient/WalletClient param types — structurally identical at
7932
8124
  // runtime, but the two share a name TS treats as unrelated.
7933
8125
  getPublicClient: (cid) => this.getPaidRpcClient(cid),
7934
- getWalletChainClient: (cid) => (0, import_viem16.createPublicClient)({
8126
+ getWalletChainClient: (cid) => (0, import_viem17.createPublicClient)({
7935
8127
  chain: VIEM_CHAIN2[cid],
7936
- transport: (0, import_viem16.custom)(provider)
8128
+ transport: (0, import_viem17.custom)(provider)
7937
8129
  }),
7938
- getWalletClient: (cid) => (0, import_viem16.createWalletClient)({
8130
+ getWalletClient: (cid) => (0, import_viem17.createWalletClient)({
7939
8131
  account: owner,
7940
8132
  chain: VIEM_CHAIN2[cid],
7941
- transport: (0, import_viem16.custom)(provider)
8133
+ transport: (0, import_viem17.custom)(provider)
7942
8134
  })
7943
8135
  });
7944
8136
  if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedWethSponsoredCallback = callback;
@@ -8702,9 +8894,8 @@ var OwneySDK = class {
8702
8894
  verified = inspectFundingReceipt(receipt, { ...evidence, agentWallet, intendedAmount: "MAX" }, token.address, direction);
8703
8895
  }
8704
8896
  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);
8897
+ if (options.refreshBalance !== false && (verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
8898
+ agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
8708
8899
  this.recoveredFundingReads.add(key2);
8709
8900
  if (this.recoveredFundingReads.size > 256) this.recoveredFundingReads.delete(this.recoveredFundingReads.values().next().value);
8710
8901
  }
@@ -8812,6 +9003,44 @@ var OwneySDK = class {
8812
9003
  assertCurrent();
8813
9004
  return true;
8814
9005
  }
9006
+ /** Optional post-payout display proof; receipt verification and the provider
9007
+ * adapter must agree before attaching it to this exact balance object. */
9008
+ async verifyWithdrawalBalance(evidence, balance) {
9009
+ const { state, chainId, assertCurrent } = this.captureReadScope(evidence.chainId);
9010
+ const agent = this.getAgent(evidence.agentId);
9011
+ if (!agent.verifyWithdrawalBalance || !evidence.txHash || state.walletAddress.toLowerCase() !== evidence.walletAddress.toLowerCase()) return balance;
9012
+ const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}:${evidence.intendedAmount}`;
9013
+ const checks = this.fundingBalanceChecks.get(balance) ?? /* @__PURE__ */ new Map();
9014
+ this.fundingBalanceChecks.set(balance, checks);
9015
+ const previous = checks.get(key2);
9016
+ if (previous) {
9017
+ const result2 = await previous;
9018
+ assertCurrent();
9019
+ return result2;
9020
+ }
9021
+ let timer;
9022
+ const read2 = async () => {
9023
+ const verified = await this.inspectFunding(evidence, "withdraw", { refreshBalance: false });
9024
+ assertCurrent();
9025
+ if (verified.transfer !== "confirmed" || verified.delivery !== "confirmed" || !verified.blockNumber) return balance;
9026
+ const metadata = await agent.verifyWithdrawalBalance(state, verified, balance);
9027
+ assertCurrent();
9028
+ 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;
9029
+ return { ...balance, readMetadata: [
9030
+ ...(balance.readMetadata ?? []).filter((item) => !(item.chainId === chainId && item.asset.toUpperCase() === evidence.token)),
9031
+ metadata
9032
+ ] };
9033
+ };
9034
+ const pending = Promise.race([read2(), new Promise((resolve) => {
9035
+ timer = setTimeout(() => resolve(balance), 2e3);
9036
+ })]).catch(() => balance).finally(() => {
9037
+ if (timer) clearTimeout(timer);
9038
+ });
9039
+ checks.set(key2, pending);
9040
+ const result = await pending;
9041
+ assertCurrent();
9042
+ return result;
9043
+ }
8815
9044
  /** A display acknowledgement controls polling only; it never confirms a financial outcome. */
8816
9045
  endFundingBalanceRefresh(evidence, read2) {
8817
9046
  const { state, chainId } = this.captureReadScope(evidence.chainId);
@@ -9080,7 +9309,7 @@ var OwneySDK = class {
9080
9309
  if (this.isUserRejectedWithdrawal(originalFailure)) throw originalFailure;
9081
9310
  if (entry.balance !== 0n && entry.agent.id !== "yieldseeker") {
9082
9311
  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;
9312
+ if (!total || (0, import_viem17.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
9084
9313
  }
9085
9314
  try {
9086
9315
  const otherAvailable = indexedAvailable - entry.balance;
@@ -9684,16 +9913,16 @@ var OwneySDK = class {
9684
9913
  );
9685
9914
  }
9686
9915
  const provider = this.requireConnectedProvider();
9687
- const walletChainClient = (0, import_viem16.createPublicClient)({
9916
+ const walletChainClient = (0, import_viem17.createPublicClient)({
9688
9917
  chain: VIEM_CHAIN2[chainId],
9689
- transport: (0, import_viem16.custom)(provider)
9918
+ transport: (0, import_viem17.custom)(provider)
9690
9919
  });
9691
9920
  const publicClient = this.getPaidRpcClient(chainId);
9692
9921
  const approvalAmount = permit2ApprovalAmount(requiredAmount);
9693
- const wallet = (0, import_viem16.createWalletClient)({
9922
+ const wallet = (0, import_viem17.createWalletClient)({
9694
9923
  account: state.walletAddress,
9695
9924
  chain: VIEM_CHAIN2[chainId],
9696
- transport: (0, import_viem16.custom)(provider)
9925
+ transport: (0, import_viem17.custom)(provider)
9697
9926
  });
9698
9927
  await ensureWalletOnChain(walletChainClient, wallet, chainId);
9699
9928
  const hash = await wallet.writeContract({
@@ -9855,7 +10084,7 @@ var OwneySDK = class {
9855
10084
  };
9856
10085
 
9857
10086
  // src/agents/zyfai/zyfai.siwx.ts
9858
- var import_viem17 = require("viem");
10087
+ var import_viem18 = require("viem");
9859
10088
  var import_siwe2 = require("siwe");
9860
10089
  var import_sdk2 = require("@zyfai/sdk");
9861
10090
 
@@ -9982,7 +10211,7 @@ function buildSIWXConfig(deps) {
9982
10211
  issuedAt,
9983
10212
  toString() {
9984
10213
  return new import_siwe2.SiweMessage({
9985
- address: (0, import_viem17.getAddress)(accountAddress),
10214
+ address: (0, import_viem18.getAddress)(accountAddress),
9986
10215
  chainId: numericChainId(chainId),
9987
10216
  domain,
9988
10217
  uri,