@owney/sdk 0.7.25-beta.20 → 0.7.25-beta.21

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
@@ -286,6 +286,240 @@ var AgentChainIncompatibleError = class extends OwneyError {
286
286
  }
287
287
  };
288
288
 
289
+ // src/lib/transfer-auth.ts
290
+ var import_viem2 = require("viem");
291
+
292
+ // src/lib/sponsor-client.ts
293
+ var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
294
+ async function postPaymasterIntent(input) {
295
+ const base6 = input.baseUrl ?? ROUTING_API_BASE_URL;
296
+ let res;
297
+ try {
298
+ res = await fetch(`${base6}/api/v1/sponsor/paymaster-intent`, {
299
+ method: "POST",
300
+ headers: {
301
+ "content-type": "application/json",
302
+ "x-owney-api-key": input.apiKey,
303
+ Authorization: `Signature ${input.yieldseekerSignature}`
304
+ },
305
+ body: JSON.stringify(input.body)
306
+ });
307
+ } catch (networkError) {
308
+ throw new OwneyError(
309
+ "SPONSOR_REQUEST_FAILED",
310
+ `Paymaster intent network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
311
+ { cause: String(networkError), safeToFallback: true }
312
+ );
313
+ }
314
+ const text = await res.text();
315
+ let parsed = null;
316
+ try {
317
+ parsed = JSON.parse(text);
318
+ } catch {
319
+ }
320
+ if (!res.ok || !parsed?.success || typeof parsed.data?.intent !== "string" || typeof parsed.data.expiresAt !== "number") {
321
+ throw new OwneyError(
322
+ "SPONSOR_REQUEST_FAILED",
323
+ `Paymaster intent API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
324
+ {
325
+ statusCode: res.status,
326
+ responseBody: text.slice(0, 500),
327
+ safeToFallback: true
328
+ }
329
+ );
330
+ }
331
+ return parsed.data;
332
+ }
333
+ async function getSponsorRelayerAddress(input) {
334
+ const base6 = input.baseUrl ?? ROUTING_API_BASE_URL;
335
+ let res;
336
+ try {
337
+ res = await fetch(
338
+ `${base6}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
339
+ {
340
+ headers: { "x-owney-api-key": input.apiKey }
341
+ }
342
+ );
343
+ } catch (networkError) {
344
+ throw new OwneyError(
345
+ "SPONSOR_REQUEST_FAILED",
346
+ `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
347
+ { cause: String(networkError), safeToFallback: true }
348
+ );
349
+ }
350
+ const text = await res.text();
351
+ let parsed = null;
352
+ try {
353
+ parsed = JSON.parse(text);
354
+ } catch {
355
+ }
356
+ if (!res.ok || !parsed?.success || !parsed.data?.relayer) {
357
+ throw new OwneyError(
358
+ "SPONSOR_REQUEST_FAILED",
359
+ `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
360
+ {
361
+ statusCode: res.status,
362
+ responseBody: text.slice(0, 500),
363
+ safeToFallback: true
364
+ }
365
+ );
366
+ }
367
+ return parsed.data.relayer;
368
+ }
369
+ async function postSponsorBatchTransfer(input) {
370
+ let res;
371
+ try {
372
+ res = await fetch(
373
+ `${input.baseUrl ?? ROUTING_API_BASE_URL}/api/v1/sponsor/permit2-batch`,
374
+ {
375
+ method: "POST",
376
+ headers: {
377
+ "content-type": "application/json",
378
+ "x-owney-api-key": input.apiKey
379
+ },
380
+ body: JSON.stringify(input.body)
381
+ }
382
+ );
383
+ } catch {
384
+ throw new OwneyError(
385
+ "SPONSOR_REQUEST_FAILED",
386
+ "Deposit status is unknown. Retry the same amount to check it.",
387
+ { safeToFallback: false }
388
+ );
389
+ }
390
+ const parsed = await res.json().catch(() => null);
391
+ if (!res.ok || !parsed?.success || !/^0x[0-9a-fA-F]{64}$/.test(parsed.data?.txHash ?? "")) {
392
+ throw new OwneyError(
393
+ "SPONSOR_REQUEST_FAILED",
394
+ "Deposit could not be confirmed. Retry the same amount to check its status.",
395
+ {
396
+ statusCode: res.status,
397
+ safeToFallback: false,
398
+ notSubmitted: parsed?.notSubmitted === true || parsed?.error?.notSubmitted === true || parsed?.error?.details?.notSubmitted === true
399
+ }
400
+ );
401
+ }
402
+ return parsed.data;
403
+ }
404
+
405
+ // src/lib/permit2.ts
406
+ var import_viem3 = require("viem");
407
+ var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
408
+ var MAX_UINT256 = 2n ** 256n - 1n;
409
+ function permit2ApprovalAmount(requiredAmount) {
410
+ if (requiredAmount <= 0n) {
411
+ throw new Error("Permit2 approval requires a positive deposit amount");
412
+ }
413
+ return MAX_UINT256;
414
+ }
415
+ var ERC20_ALLOWANCE_ABI = [
416
+ {
417
+ type: "function",
418
+ name: "allowance",
419
+ stateMutability: "view",
420
+ inputs: [
421
+ { name: "owner", type: "address" },
422
+ { name: "spender", type: "address" }
423
+ ],
424
+ outputs: [{ name: "", type: "uint256" }]
425
+ },
426
+ {
427
+ type: "function",
428
+ name: "approve",
429
+ stateMutability: "nonpayable",
430
+ inputs: [
431
+ { name: "spender", type: "address" },
432
+ { name: "amount", type: "uint256" }
433
+ ],
434
+ outputs: [{ name: "", type: "bool" }]
435
+ },
436
+ {
437
+ type: "function",
438
+ name: "balanceOf",
439
+ stateMutability: "view",
440
+ inputs: [{ name: "account", type: "address" }],
441
+ outputs: [{ name: "", type: "uint256" }]
442
+ }
443
+ ];
444
+ function randomPermit2Nonce() {
445
+ const bytes = new Uint8Array(32);
446
+ globalThis.crypto.getRandomValues(bytes);
447
+ return BigInt((0, import_viem3.bytesToHex)(bytes));
448
+ }
449
+ async function readPermit2Allowance(publicClient, token, owner, blockNumber) {
450
+ return publicClient.readContract({
451
+ address: token,
452
+ abi: ERC20_ALLOWANCE_ABI,
453
+ functionName: "allowance",
454
+ args: [owner, PERMIT2_ADDRESS],
455
+ ...blockNumber === void 0 ? {} : { blockNumber }
456
+ });
457
+ }
458
+ async function readErc20Balance(publicClient, token, owner) {
459
+ return publicClient.readContract({
460
+ address: token,
461
+ abi: ERC20_ALLOWANCE_ABI,
462
+ functionName: "balanceOf",
463
+ args: [owner]
464
+ });
465
+ }
466
+
467
+ // src/lib/chain-guard.ts
468
+ var CHAIN_NAMES = {
469
+ 1: "Ethereum",
470
+ 8453: "Base",
471
+ 42161: "Arbitrum"
472
+ };
473
+ function chainName(chainId) {
474
+ return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
475
+ }
476
+ async function ensureWalletOnChain(pub, wallet, expected) {
477
+ const actual = await pub.getChainId();
478
+ if (actual === expected) return;
479
+ try {
480
+ await wallet.switchChain({ id: expected });
481
+ } catch (error) {
482
+ throw new OwneyError(
483
+ "CHAIN_MISMATCH",
484
+ `Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
485
+ {
486
+ expectedChainId: expected,
487
+ actualChainId: actual,
488
+ cause: error instanceof Error ? error.message : String(error)
489
+ }
490
+ );
491
+ }
492
+ const after = await pub.getChainId();
493
+ if (after !== expected) {
494
+ throw new OwneyError(
495
+ "CHAIN_MISMATCH",
496
+ `Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
497
+ { expectedChainId: expected, actualChainId: after }
498
+ );
499
+ }
500
+ }
501
+
502
+ // src/lib/sponsored-deposit.ts
503
+ var AUTH_WINDOW_SECONDS = 15 * 60;
504
+ var verificationSetter = /* @__PURE__ */ Symbol("owney.depositVerificationSetter");
505
+ function provideDepositVerificationContext(callback, context) {
506
+ callback[verificationSetter]?.(context);
507
+ }
508
+ function makeVerificationAwareDepositCallback(implementation) {
509
+ let nextVerification;
510
+ const callback = async (smartWallet, chainId, amount) => {
511
+ const verification = nextVerification;
512
+ nextVerification = void 0;
513
+ return implementation(smartWallet, chainId, amount, verification);
514
+ };
515
+ Object.defineProperty(callback, verificationSetter, {
516
+ value: (context) => {
517
+ nextVerification = context;
518
+ }
519
+ });
520
+ return callback;
521
+ }
522
+
289
523
  // src/lib/rate-limit.ts
290
524
  function rateLimitDelay(error, now = Date.now()) {
291
525
  const seen = /* @__PURE__ */ new Set();
@@ -560,7 +794,7 @@ function hasEmptyWithdrawalSnapshot(raw2, chainId, token) {
560
794
  }
561
795
 
562
796
  // src/agents/zyfai/zyfai.deposit.ts
563
- var import_viem2 = require("viem");
797
+ var import_viem4 = require("viem");
564
798
 
565
799
  // src/types/config.ts
566
800
  var P_SUPPORTED_CHAINS = {
@@ -610,20 +844,20 @@ var SupportedAssets = [
610
844
  ];
611
845
 
612
846
  // src/agents/zyfai/zyfai.deposit.ts
613
- async function submitZyfaiDeposit({ sdk, state, chain, amount, asset, smartWallet, assertCurrent }) {
847
+ async function submitZyfaiDeposit({ sdk, state, chain, amount, asset, smartWallet, assertCurrent, onBeforeSubmission }) {
614
848
  const owner = state.walletAddress;
615
849
  const provider = state.provider;
616
850
  const token = SupportedAssets.find((value) => value.chainId === chain.id && value.symbol === asset);
617
- if (!token || !(0, import_viem2.isAddress)(owner) || !(0, import_viem2.isAddress)(smartWallet) || !/^\d+$/.test(amount) || BigInt(amount) <= 0n)
851
+ if (!token || !(0, import_viem4.isAddress)(owner) || !(0, import_viem4.isAddress)(smartWallet) || !/^\d+$/.test(amount) || BigInt(amount) <= 0n)
618
852
  throw new OwneyError("AGENT_INVALID_RESPONSE", "Invalid Zyfai deposit transfer.", { chainId: chain.id, asset }, "zyfai");
619
853
  assertCurrent();
620
854
  const prepared = await sdk.prepareEnterPosition({ userAddress: owner, chainId: chain.id, amount, asset, strategy: "aggressive" });
621
855
  assertCurrent();
622
- const expectedData = (0, import_viem2.encodeFunctionData)({ abi: import_viem2.erc20Abi, functionName: "transfer", args: [smartWallet, BigInt(amount)] });
856
+ const expectedData = (0, import_viem4.encodeFunctionData)({ abi: import_viem4.erc20Abi, functionName: "transfer", args: [smartWallet, BigInt(amount)] });
623
857
  const transfer = prepared?.transfer;
624
858
  if (!transfer || transfer.safeAddress?.toLowerCase() !== smartWallet.toLowerCase() || transfer.tokenAddress?.toLowerCase() !== token.address.toLowerCase() || transfer.to?.toLowerCase() !== token.address.toLowerCase() || transfer.data?.toLowerCase() !== expectedData.toLowerCase() || transfer.value !== "0")
625
859
  throw new OwneyError("AGENT_INVALID_RESPONSE", "Zyfai prepared a different deposit transfer.", { chainId: chain.id, asset }, "zyfai");
626
- const wallet = (0, import_viem2.createWalletClient)({ account: owner, chain, transport: (0, import_viem2.custom)({
860
+ const wallet = (0, import_viem4.createWalletClient)({ account: owner, chain, transport: (0, import_viem4.custom)({
627
861
  request: async (args) => {
628
862
  assertCurrent();
629
863
  if (args.method === "eth_sendTransaction") {
@@ -634,6 +868,8 @@ async function submitZyfaiDeposit({ sdk, state, chain, amount, asset, smartWalle
634
868
  assertCurrent();
635
869
  if (!Array.isArray(accounts) || typeof accounts[0] !== "string" || accounts[0].toLowerCase() !== owner.toLowerCase() || Number(chainId) !== chain.id)
636
870
  throw new OwneyError("NOT_CONNECTED", "Wallet changed while preparing Zyfai deposit.", void 0, "zyfai");
871
+ await onBeforeSubmission?.();
872
+ assertCurrent();
637
873
  }
638
874
  return provider.request(args);
639
875
  }
@@ -643,7 +879,7 @@ async function submitZyfaiDeposit({ sdk, state, chain, amount, asset, smartWalle
643
879
 
644
880
  // src/agents/zyfai/zyfai.agent.ts
645
881
  var import_sdk = require("@zyfai/sdk");
646
- var import_viem5 = require("viem");
882
+ var import_viem7 = require("viem");
647
883
  var import_chains = require("viem/chains");
648
884
 
649
885
  // src/lib/debug.ts
@@ -690,8 +926,8 @@ var DayFilterMapping = {
690
926
  };
691
927
 
692
928
  // src/agents/zyfai/zyfai.mapper.ts
693
- var import_viem3 = require("viem");
694
- var exactHexAmount = (raw2, decimals) => (0, import_viem3.formatUnits)(BigInt(/^0x/i.test(raw2) ? raw2 : `0x${raw2}`), decimals);
929
+ var import_viem5 = require("viem");
930
+ var exactHexAmount = (raw2, decimals) => (0, import_viem5.formatUnits)(BigInt(/^0x/i.test(raw2) ? raw2 : `0x${raw2}`), decimals);
695
931
  var DECIMALS_BY_SYMBOL = {
696
932
  usdc: 6,
697
933
  weth: 18,
@@ -790,7 +1026,7 @@ function mapBalances(raw2, _chainId, smartWallet) {
790
1026
  // legacy `amount` fallback is hex. Runtime
791
1027
  // getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
792
1028
  // when present, otherwise fall back to the per-symbol lookup.
793
- amount: p.underlyingAmountWithFee ?? p.underlyingAmount ? (0, import_viem3.formatUnits)(
1029
+ amount: p.underlyingAmountWithFee ?? p.underlyingAmount ? (0, import_viem5.formatUnits)(
794
1030
  BigInt(p.underlyingAmountWithFee ?? p.underlyingAmount ?? "0"),
795
1031
  tokenDecimals(
796
1032
  p.token_symbol,
@@ -1455,7 +1691,7 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
1455
1691
  }
1456
1692
 
1457
1693
  // src/lib/paid-rpc.ts
1458
- var import_viem4 = require("viem");
1694
+ var import_viem6 = require("viem");
1459
1695
  var PAID_RPC_RETRY_COUNT = 3;
1460
1696
  var PAID_RPC_RETRY_DELAY_MS = 1e3;
1461
1697
  function configuredRpcProxyBaseUrl(baseUrl) {
@@ -1491,9 +1727,9 @@ function createPaidRpcClient(chain, rpcUrls) {
1491
1727
  rpcUrls,
1492
1728
  chain.id
1493
1729
  );
1494
- return (0, import_viem4.createPublicClient)({
1730
+ return (0, import_viem6.createPublicClient)({
1495
1731
  chain,
1496
- transport: (0, import_viem4.http)(url, {
1732
+ transport: (0, import_viem6.http)(url, {
1497
1733
  retryCount: PAID_RPC_RETRY_COUNT,
1498
1734
  retryDelay: PAID_RPC_RETRY_DELAY_MS
1499
1735
  })
@@ -1590,7 +1826,7 @@ async function withPaidRpcDiagnostics(operation, chainId, rpcMethod, agentId) {
1590
1826
  }
1591
1827
 
1592
1828
  // src/agents/zyfai/zyfai.agent.ts
1593
- var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem5.parseAbi)([
1829
+ var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem7.parseAbi)([
1594
1830
  "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
1595
1831
  ]);
1596
1832
  var WETH_ADDRESS_BY_CHAIN = {
@@ -1757,7 +1993,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
1757
1993
  }, asset.address, entry.action === "Withdraw" ? "withdraw" : "deposit");
1758
1994
  if (evidence.transfer === "confirmed" && evidence.confirmedAmount) {
1759
1995
  Object.assign(tx, {
1760
- amount: (0, import_viem5.formatUnits)(BigInt(evidence.confirmedAmount), asset.decimals),
1996
+ amount: (0, import_viem7.formatUnits)(BigInt(evidence.confirmedAmount), asset.decimals),
1761
1997
  amountRaw: evidence.confirmedAmount,
1762
1998
  blockNumber: evidence.blockNumber,
1763
1999
  logIndexes: evidence.logIndexes,
@@ -2470,7 +2706,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2470
2706
  await this.ensureSessionKey(ownerAddress, chainId, redeployed.address);
2471
2707
  return redeployed.address;
2472
2708
  }
2473
- async deposit(state, chainId, amount, asset, depositCallback, onProgress) {
2709
+ async deposit(state, chainId, amount, asset, depositCallback, onProgress, onBeforeSubmission) {
2474
2710
  const validChainId = isValidChainId(chainId);
2475
2711
  const owner = state.walletAddress;
2476
2712
  const provider = state.provider;
@@ -2503,7 +2739,18 @@ var ZyfaiAgent = class _ZyfaiAgent {
2503
2739
  amount,
2504
2740
  asset,
2505
2741
  smartWallet,
2506
- assertCurrent
2742
+ assertCurrent,
2743
+ onBeforeSubmission: onBeforeSubmission ? () => onBeforeSubmission({
2744
+ agentId: this.id,
2745
+ chainId,
2746
+ token: asset,
2747
+ walletAddress: owner,
2748
+ agentWallet: smartWallet,
2749
+ intendedAmount: amount,
2750
+ transfer: "pending",
2751
+ registration: "pending",
2752
+ delivery: "not-applicable"
2753
+ }) : void 0
2507
2754
  });
2508
2755
  let evidence = {
2509
2756
  agentId: this.id,
@@ -2573,7 +2820,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2573
2820
  this.sdk.getPortfolio(owner).catch(() => void 0)
2574
2821
  ]);
2575
2822
  assertScope();
2576
- if (!(0, import_viem5.isAddress)(wallet.address) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase())
2823
+ if (!(0, import_viem7.isAddress)(wallet.address) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase())
2577
2824
  throw new OwneyError(
2578
2825
  "AGENT_AUTH_FAILED",
2579
2826
  "Could not verify Zyfai's withdrawal wallet.",
@@ -2584,7 +2831,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2584
2831
  const asset = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === token);
2585
2832
  const idle = asset ? await this.getPublicClient(chainId).readContract({
2586
2833
  address: asset.address,
2587
- abi: import_viem5.erc20Abi,
2834
+ abi: import_viem7.erc20Abi,
2588
2835
  functionName: "balanceOf",
2589
2836
  args: [wallet.address]
2590
2837
  }).catch(() => void 0) : void 0;
@@ -2831,13 +3078,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
2831
3078
  this.sdk.getSmartWalletByEOA(owner)
2832
3079
  ]);
2833
3080
  assertScope();
2834
- if (!(0, import_viem5.isAddress)(wallet.address) || wallet.isDeployed !== false && (wallet.isDeployed !== true || wallet.isOwner !== true) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase()) throw unavailable();
3081
+ if (!(0, import_viem7.isAddress)(wallet.address) || wallet.isDeployed !== false && (wallet.isDeployed !== true || wallet.isOwner !== true) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase()) throw unavailable();
2835
3082
  const client = this.getPublicClient(validChainId);
2836
3083
  const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
2837
3084
  assertScope();
2838
3085
  const idle = await client.readContract({
2839
3086
  address: asset.address,
2840
- abi: import_viem5.erc20Abi,
3087
+ abi: import_viem7.erc20Abi,
2841
3088
  functionName: "balanceOf",
2842
3089
  args: [wallet.address],
2843
3090
  blockNumber
@@ -2894,7 +3141,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2894
3141
  if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
2895
3142
  const idle = await client.readContract({
2896
3143
  address: asset.address,
2897
- abi: import_viem5.erc20Abi,
3144
+ abi: import_viem7.erc20Abi,
2898
3145
  functionName: "balanceOf",
2899
3146
  args: [balance.smartWallet],
2900
3147
  blockNumber
@@ -3102,240 +3349,6 @@ var ZyfaiAgent = class _ZyfaiAgent {
3102
3349
  var import_viem13 = require("viem");
3103
3350
  var import_chains4 = require("viem/chains");
3104
3351
 
3105
- // src/lib/chain-guard.ts
3106
- var CHAIN_NAMES = {
3107
- 1: "Ethereum",
3108
- 8453: "Base",
3109
- 42161: "Arbitrum"
3110
- };
3111
- function chainName(chainId) {
3112
- return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
3113
- }
3114
- async function ensureWalletOnChain(pub, wallet, expected) {
3115
- const actual = await pub.getChainId();
3116
- if (actual === expected) return;
3117
- try {
3118
- await wallet.switchChain({ id: expected });
3119
- } catch (error) {
3120
- throw new OwneyError(
3121
- "CHAIN_MISMATCH",
3122
- `Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
3123
- {
3124
- expectedChainId: expected,
3125
- actualChainId: actual,
3126
- cause: error instanceof Error ? error.message : String(error)
3127
- }
3128
- );
3129
- }
3130
- const after = await pub.getChainId();
3131
- if (after !== expected) {
3132
- throw new OwneyError(
3133
- "CHAIN_MISMATCH",
3134
- `Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
3135
- { expectedChainId: expected, actualChainId: after }
3136
- );
3137
- }
3138
- }
3139
-
3140
- // src/lib/transfer-auth.ts
3141
- var import_viem6 = require("viem");
3142
-
3143
- // src/lib/sponsor-client.ts
3144
- var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
3145
- async function postPaymasterIntent(input) {
3146
- const base6 = input.baseUrl ?? ROUTING_API_BASE_URL;
3147
- let res;
3148
- try {
3149
- res = await fetch(`${base6}/api/v1/sponsor/paymaster-intent`, {
3150
- method: "POST",
3151
- headers: {
3152
- "content-type": "application/json",
3153
- "x-owney-api-key": input.apiKey,
3154
- Authorization: `Signature ${input.yieldseekerSignature}`
3155
- },
3156
- body: JSON.stringify(input.body)
3157
- });
3158
- } catch (networkError) {
3159
- throw new OwneyError(
3160
- "SPONSOR_REQUEST_FAILED",
3161
- `Paymaster intent network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
3162
- { cause: String(networkError), safeToFallback: true }
3163
- );
3164
- }
3165
- const text = await res.text();
3166
- let parsed = null;
3167
- try {
3168
- parsed = JSON.parse(text);
3169
- } catch {
3170
- }
3171
- if (!res.ok || !parsed?.success || typeof parsed.data?.intent !== "string" || typeof parsed.data.expiresAt !== "number") {
3172
- throw new OwneyError(
3173
- "SPONSOR_REQUEST_FAILED",
3174
- `Paymaster intent API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
3175
- {
3176
- statusCode: res.status,
3177
- responseBody: text.slice(0, 500),
3178
- safeToFallback: true
3179
- }
3180
- );
3181
- }
3182
- return parsed.data;
3183
- }
3184
- async function getSponsorRelayerAddress(input) {
3185
- const base6 = input.baseUrl ?? ROUTING_API_BASE_URL;
3186
- let res;
3187
- try {
3188
- res = await fetch(
3189
- `${base6}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
3190
- {
3191
- headers: { "x-owney-api-key": input.apiKey }
3192
- }
3193
- );
3194
- } catch (networkError) {
3195
- throw new OwneyError(
3196
- "SPONSOR_REQUEST_FAILED",
3197
- `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
3198
- { cause: String(networkError), safeToFallback: true }
3199
- );
3200
- }
3201
- const text = await res.text();
3202
- let parsed = null;
3203
- try {
3204
- parsed = JSON.parse(text);
3205
- } catch {
3206
- }
3207
- if (!res.ok || !parsed?.success || !parsed.data?.relayer) {
3208
- throw new OwneyError(
3209
- "SPONSOR_REQUEST_FAILED",
3210
- `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
3211
- {
3212
- statusCode: res.status,
3213
- responseBody: text.slice(0, 500),
3214
- safeToFallback: true
3215
- }
3216
- );
3217
- }
3218
- return parsed.data.relayer;
3219
- }
3220
- async function postSponsorBatchTransfer(input) {
3221
- let res;
3222
- try {
3223
- res = await fetch(
3224
- `${input.baseUrl ?? ROUTING_API_BASE_URL}/api/v1/sponsor/permit2-batch`,
3225
- {
3226
- method: "POST",
3227
- headers: {
3228
- "content-type": "application/json",
3229
- "x-owney-api-key": input.apiKey
3230
- },
3231
- body: JSON.stringify(input.body)
3232
- }
3233
- );
3234
- } catch {
3235
- throw new OwneyError(
3236
- "SPONSOR_REQUEST_FAILED",
3237
- "Deposit status is unknown. Retry the same amount to check it.",
3238
- { safeToFallback: false }
3239
- );
3240
- }
3241
- const parsed = await res.json().catch(() => null);
3242
- if (!res.ok || !parsed?.success || !/^0x[0-9a-fA-F]{64}$/.test(parsed.data?.txHash ?? "")) {
3243
- throw new OwneyError(
3244
- "SPONSOR_REQUEST_FAILED",
3245
- "Deposit could not be confirmed. Retry the same amount to check its status.",
3246
- {
3247
- statusCode: res.status,
3248
- safeToFallback: false,
3249
- notSubmitted: parsed?.notSubmitted === true || parsed?.error?.notSubmitted === true || parsed?.error?.details?.notSubmitted === true
3250
- }
3251
- );
3252
- }
3253
- return parsed.data;
3254
- }
3255
-
3256
- // src/lib/permit2.ts
3257
- var import_viem7 = require("viem");
3258
- var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
3259
- var MAX_UINT256 = 2n ** 256n - 1n;
3260
- function permit2ApprovalAmount(requiredAmount) {
3261
- if (requiredAmount <= 0n) {
3262
- throw new Error("Permit2 approval requires a positive deposit amount");
3263
- }
3264
- return MAX_UINT256;
3265
- }
3266
- var ERC20_ALLOWANCE_ABI = [
3267
- {
3268
- type: "function",
3269
- name: "allowance",
3270
- stateMutability: "view",
3271
- inputs: [
3272
- { name: "owner", type: "address" },
3273
- { name: "spender", type: "address" }
3274
- ],
3275
- outputs: [{ name: "", type: "uint256" }]
3276
- },
3277
- {
3278
- type: "function",
3279
- name: "approve",
3280
- stateMutability: "nonpayable",
3281
- inputs: [
3282
- { name: "spender", type: "address" },
3283
- { name: "amount", type: "uint256" }
3284
- ],
3285
- outputs: [{ name: "", type: "bool" }]
3286
- },
3287
- {
3288
- type: "function",
3289
- name: "balanceOf",
3290
- stateMutability: "view",
3291
- inputs: [{ name: "account", type: "address" }],
3292
- outputs: [{ name: "", type: "uint256" }]
3293
- }
3294
- ];
3295
- function randomPermit2Nonce() {
3296
- const bytes = new Uint8Array(32);
3297
- globalThis.crypto.getRandomValues(bytes);
3298
- return BigInt((0, import_viem7.bytesToHex)(bytes));
3299
- }
3300
- async function readPermit2Allowance(publicClient, token, owner, blockNumber) {
3301
- return publicClient.readContract({
3302
- address: token,
3303
- abi: ERC20_ALLOWANCE_ABI,
3304
- functionName: "allowance",
3305
- args: [owner, PERMIT2_ADDRESS],
3306
- ...blockNumber === void 0 ? {} : { blockNumber }
3307
- });
3308
- }
3309
- async function readErc20Balance(publicClient, token, owner) {
3310
- return publicClient.readContract({
3311
- address: token,
3312
- abi: ERC20_ALLOWANCE_ABI,
3313
- functionName: "balanceOf",
3314
- args: [owner]
3315
- });
3316
- }
3317
-
3318
- // src/lib/sponsored-deposit.ts
3319
- var AUTH_WINDOW_SECONDS = 15 * 60;
3320
- var verificationSetter = /* @__PURE__ */ Symbol("owney.depositVerificationSetter");
3321
- function provideDepositVerificationContext(callback, context) {
3322
- callback[verificationSetter]?.(context);
3323
- }
3324
- function makeVerificationAwareDepositCallback(implementation) {
3325
- let nextVerification;
3326
- const callback = async (smartWallet, chainId, amount) => {
3327
- const verification = nextVerification;
3328
- nextVerification = void 0;
3329
- return implementation(smartWallet, chainId, amount, verification);
3330
- };
3331
- Object.defineProperty(callback, verificationSetter, {
3332
- value: (context) => {
3333
- nextVerification = context;
3334
- }
3335
- });
3336
- return callback;
3337
- }
3338
-
3339
3352
  // src/agents/yieldseeker/yieldseeker.auth.ts
3340
3353
  var import_siwe = require("siwe");
3341
3354
  var import_viem8 = require("viem");
@@ -5387,7 +5400,7 @@ var YieldseekerAgent = class {
5387
5400
  this.assertAsset(targetAsset);
5388
5401
  await this.ensureAgent(state, chainId, targetAsset);
5389
5402
  }
5390
- async deposit(state, chainId, amount, asset, depositCallback, onProgress) {
5403
+ async deposit(state, chainId, amount, asset, depositCallback, onProgress, onBeforeSubmission) {
5391
5404
  this.assertChain(chainId);
5392
5405
  this.assertAsset(asset);
5393
5406
  if (BigInt(amount) <= 0n) {
@@ -5443,7 +5456,17 @@ var YieldseekerAgent = class {
5443
5456
  chainId
5444
5457
  }, submitted, (value) => {
5445
5458
  receipt = value;
5446
- });
5459
+ }, onBeforeSubmission ? () => onBeforeSubmission({
5460
+ agentId: this.id,
5461
+ chainId,
5462
+ token: asset,
5463
+ walletAddress: state.walletAddress,
5464
+ agentWallet: context.wallet.walletAddress,
5465
+ intendedAmount: amount,
5466
+ transfer: "pending",
5467
+ registration: "not-applicable",
5468
+ delivery: "not-applicable"
5469
+ }) : void 0);
5447
5470
  } catch (error) {
5448
5471
  if (error instanceof OwneyError && error.details?.ownerTransferNotExecuted === true && error.details.reason === "TRANSACTION_REPLACED_WITH_DIFFERENT_CALL") {
5449
5472
  notifyFunding(onProgress, {
@@ -7039,8 +7062,9 @@ var YieldseekerAgent = class {
7039
7062
  this.id
7040
7063
  );
7041
7064
  }
7042
- async submitTransaction(state, chainId, transaction, onSubmitted, onReceipt) {
7065
+ async submitTransaction(state, chainId, transaction, onSubmitted, onReceipt, onBeforeSubmission) {
7043
7066
  if (this.transactionExecutor) {
7067
+ await onBeforeSubmission?.();
7044
7068
  const hash2 = await this.transactionExecutor(state, chainId, transaction, onReceipt);
7045
7069
  onSubmitted?.(hash2);
7046
7070
  return hash2;
@@ -7050,7 +7074,10 @@ var YieldseekerAgent = class {
7050
7074
  const walletClient = (0, import_viem13.createWalletClient)({
7051
7075
  account,
7052
7076
  chain: import_chains4.base,
7053
- transport: (0, import_viem13.custom)(state.provider)
7077
+ transport: onBeforeSubmission ? (0, import_viem13.custom)({ request: async (args) => {
7078
+ if (args.method === "eth_sendTransaction") await onBeforeSubmission();
7079
+ return state.provider.request(args);
7080
+ } }, { retryCount: 0 }) : (0, import_viem13.custom)(state.provider)
7054
7081
  });
7055
7082
  const walletChainClient = (0, import_viem13.createPublicClient)({
7056
7083
  chain: import_chains4.base,
@@ -7891,6 +7918,7 @@ async function execute(i, key2, plan) {
7891
7918
  };
7892
7919
  save(key2, body);
7893
7920
  }
7921
+ await i.onBeforeSubmission?.((0, import_viem16.keccak256)(body.serializedTransaction));
7894
7922
  try {
7895
7923
  i.onSubmitted?.((0, import_viem16.keccak256)(body.serializedTransaction));
7896
7924
  } catch {
@@ -7918,6 +7946,13 @@ async function execute(i, key2, plan) {
7918
7946
  clear(key2, body);
7919
7947
  return hash;
7920
7948
  } catch (error) {
7949
+ if (initial.serializedTransaction && error instanceof OwneyError && error.code === "DEPOSIT_CHECKPOINT_FAILED") {
7950
+ throw new OwneyError(
7951
+ error.code,
7952
+ "Could not save recovery of the existing deposit.",
7953
+ { ...error.details, notSubmitted: false, safeToFallback: false }
7954
+ );
7955
+ }
7921
7956
  if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
7922
7957
  clear(key2, body);
7923
7958
  throw error;
@@ -8044,6 +8079,7 @@ function makeSponsoredTokenCallback(deps) {
8044
8079
  wallet,
8045
8080
  onApproved: deps.onApproved,
8046
8081
  onSubmitted: (hash) => deps.onSubmitted?.(hash, transfers),
8082
+ onBeforeSubmission: (hash) => deps.onBeforeSubmission?.(hash, transfers),
8047
8083
  resumeTxHash: deps.resumeTxHash
8048
8084
  });
8049
8085
  };
@@ -8215,6 +8251,7 @@ function makeSponsoredCallsCallback(deps) {
8215
8251
  } catch {
8216
8252
  }
8217
8253
  };
8254
+ await deps.onBeforeSubmission?.(requestedId, transfers);
8218
8255
  progress(requestedId, "pending");
8219
8256
  let sendResult;
8220
8257
  try {
@@ -8512,8 +8549,8 @@ var OwneySDK = class {
8512
8549
  return createPaidRpcClient(VIEM_CHAIN2[chainId], this.rpcUrls);
8513
8550
  }
8514
8551
  /** Builds the default USDC batch callback for the connected wallet. */
8515
- getDefaultSponsoredCallback(onApproved, onSubmitted, resumeTxHash) {
8516
- if (!onApproved && !onSubmitted && !resumeTxHash && this.cachedSponsoredCallback)
8552
+ getDefaultSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission) {
8553
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && this.cachedSponsoredCallback)
8517
8554
  return this.cachedSponsoredCallback;
8518
8555
  const provider = this.requireConnectedProvider();
8519
8556
  const owner = this.state.walletAddress;
@@ -8523,6 +8560,7 @@ var OwneySDK = class {
8523
8560
  ownerAddress: owner,
8524
8561
  onApproved,
8525
8562
  onSubmitted,
8563
+ onBeforeSubmission,
8526
8564
  resumeTxHash,
8527
8565
  tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
8528
8566
  // Casts work around viem's chain-narrowed Client vs the generic
@@ -8539,13 +8577,13 @@ var OwneySDK = class {
8539
8577
  transport: (0, import_viem18.custom)(provider)
8540
8578
  })
8541
8579
  });
8542
- if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedSponsoredCallback = callback;
8580
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission) this.cachedSponsoredCallback = callback;
8543
8581
  return callback;
8544
8582
  }
8545
8583
  /** Builds the wallet-native sponsored calls callback for compatible paymasters. */
8546
- getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress) {
8584
+ getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress, onBeforeSubmission) {
8547
8585
  const cached = this.cachedSponsoredCallsCallbacks.get(asset);
8548
- if (!onApproved && !onSubmitted && !onCallsProgress && cached) return cached;
8586
+ if (!onApproved && !onSubmitted && !onCallsProgress && !onBeforeSubmission && cached) return cached;
8549
8587
  const provider = this.requireConnectedProvider();
8550
8588
  const callback = makeSponsoredCallsCallback({
8551
8589
  apiKey: this.apiKey,
@@ -8556,9 +8594,10 @@ var OwneySDK = class {
8556
8594
  onApproved,
8557
8595
  onSubmitted,
8558
8596
  onCallsProgress,
8597
+ onBeforeSubmission,
8559
8598
  tokenAddressByChain: sponsoredTokensFor(asset)
8560
8599
  });
8561
- if (!onApproved && !onSubmitted && !onCallsProgress) this.cachedSponsoredCallsCallbacks.set(asset, callback);
8600
+ if (!onApproved && !onSubmitted && !onCallsProgress && !onBeforeSubmission) this.cachedSponsoredCallsCallbacks.set(asset, callback);
8562
8601
  return callback;
8563
8602
  }
8564
8603
  /**
@@ -8567,8 +8606,8 @@ var OwneySDK = class {
8567
8606
  * Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
8568
8607
  * single-use batch authorization instead of an EIP-3009 authorization.
8569
8608
  */
8570
- getDefaultWethSponsoredCallback(onApproved, onSubmitted, resumeTxHash) {
8571
- if (!onApproved && !onSubmitted && !resumeTxHash && this.cachedWethSponsoredCallback)
8609
+ getDefaultWethSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission) {
8610
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && this.cachedWethSponsoredCallback)
8572
8611
  return this.cachedWethSponsoredCallback;
8573
8612
  const provider = this.requireConnectedProvider();
8574
8613
  const owner = this.state.walletAddress;
@@ -8578,6 +8617,7 @@ var OwneySDK = class {
8578
8617
  ownerAddress: owner,
8579
8618
  onApproved,
8580
8619
  onSubmitted,
8620
+ onBeforeSubmission,
8581
8621
  resumeTxHash,
8582
8622
  tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
8583
8623
  // Casts work around viem's chain-narrowed Client vs the generic
@@ -8594,7 +8634,7 @@ var OwneySDK = class {
8594
8634
  transport: (0, import_viem18.custom)(provider)
8595
8635
  })
8596
8636
  });
8597
- if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedWethSponsoredCallback = callback;
8637
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission) this.cachedWethSponsoredCallback = callback;
8598
8638
  return callback;
8599
8639
  }
8600
8640
  getAgent(agentId) {
@@ -8910,8 +8950,12 @@ var OwneySDK = class {
8910
8950
  );
8911
8951
  const prepared = /* @__PURE__ */ new Map();
8912
8952
  const paidFallbackAgents = /* @__PURE__ */ new Set();
8913
- const onProgress = options.onProgress ? (evidence) => {
8914
- if (evidence.agentWallet) prepared.set(evidence.agentWallet.toLowerCase(), evidence);
8953
+ const onProgress = options.onProgress || options.onBeforeSubmission ? (evidence) => {
8954
+ if (evidence.agentWallet) {
8955
+ const wallet = evidence.agentWallet.toLowerCase();
8956
+ evidence = { ...prepared.get(wallet), ...evidence };
8957
+ prepared.set(wallet, evidence);
8958
+ }
8915
8959
  notifyFunding(options.onProgress, evidence);
8916
8960
  } : void 0;
8917
8961
  const onSubmitted = onProgress ? (hash, destinations) => {
@@ -8931,9 +8975,45 @@ var OwneySDK = class {
8931
8975
  }
8932
8976
  const state = this.requireState();
8933
8977
  const chainId = this.requireChainId();
8978
+ let checkpointFailure;
8979
+ let checkpointFailedEvidence = [];
8980
+ const checkpoint2 = options.onBeforeSubmission ? async (evidence) => {
8981
+ try {
8982
+ if (this.state !== state || state.chainId !== chainId) throw new Error("Wallet changed before deposit submission.");
8983
+ const submitting = evidence.map((leg) => ({ ...leg, depositSubmission: "started" }));
8984
+ await options.onBeforeSubmission(submitting);
8985
+ if (this.state !== state || state.chainId !== chainId) throw new Error("Wallet changed before deposit submission.");
8986
+ submitting.forEach((leg) => notifyFunding(onProgress, leg));
8987
+ } catch (cause) {
8988
+ checkpointFailedEvidence = evidence;
8989
+ checkpointFailure = new OwneyError(
8990
+ "DEPOSIT_CHECKPOINT_FAILED",
8991
+ "Could not safely save this deposit before submission.",
8992
+ { notSubmitted: !options.resumeTxHash, safeToFallback: false, cause }
8993
+ );
8994
+ throw checkpointFailure;
8995
+ }
8996
+ } : void 0;
8997
+ const checkpointDestinations = checkpoint2 ? async (destinations, identifier) => {
8998
+ const evidence = destinations.map((destination) => {
8999
+ const leg = prepared.get(destination.to.toLowerCase());
9000
+ if (!leg || leg.intendedAmount !== destination.amount)
9001
+ throw new OwneyError("DEPOSIT_CHECKPOINT_FAILED", "Missing prepared deposit destination.", { notSubmitted: true, safeToFallback: false });
9002
+ return { ...leg, ...identifier, transfer: "pending" };
9003
+ });
9004
+ await checkpoint2(evidence);
9005
+ } : void 0;
9006
+ const checkpointHash = checkpointDestinations ? (hash, destinations) => checkpointDestinations(destinations, { txHash: hash }) : void 0;
9007
+ const checkpointCalls = checkpointDestinations ? (id, destinations) => checkpointDestinations(destinations, { callsId: id }) : void 0;
9008
+ const checkpointPaid = checkpoint2 ? (evidence) => checkpoint2([evidence]) : void 0;
9009
+ const customCallback = depositCallback && checkpointDestinations ? makeVerificationAwareDepositCallback(async (to, cid, value, verification) => {
9010
+ if (verification) provideDepositVerificationContext(depositCallback, verification);
9011
+ await checkpointDestinations([{ to, amount: value }], {});
9012
+ return depositCallback(to, cid, value);
9013
+ }) : depositCallback;
8934
9014
  if (options.resumeTxHash && (depositCallback || this.paymasterServiceUrl || !/^0x[\da-f]{64}$/i.test(options.resumeTxHash)))
8935
9015
  throw new OwneyError("DEPOSIT_IN_PROGRESS", "This deposit cannot resume the saved relayer transaction.");
8936
- const effectiveCallback = depositCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash) : this.getDefaultSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash));
9016
+ const effectiveCallback = customCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress, checkpointCalls) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash) : this.getDefaultSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash));
8937
9017
  try {
8938
9018
  if (options.resumeTxHash) {
8939
9019
  const token = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === asset);
@@ -8997,7 +9077,8 @@ var OwneySDK = class {
8997
9077
  depositCallback,
8998
9078
  onProgress,
8999
9079
  () => paidFallbackAgents.add(agent.id),
9000
- !!options.resumeTxHash
9080
+ !!options.resumeTxHash,
9081
+ checkpointPaid
9001
9082
  );
9002
9083
  }
9003
9084
  const totalAmount = BigInt(amount);
@@ -9099,7 +9180,8 @@ var OwneySDK = class {
9099
9180
  depositCallback,
9100
9181
  onProgress,
9101
9182
  () => paidFallbackAgents.add(agent.id),
9102
- !!options.resumeTxHash
9183
+ !!options.resumeTxHash,
9184
+ checkpointPaid
9103
9185
  );
9104
9186
  } catch (error) {
9105
9187
  if (Object.keys(agentResults).length === 0) throw error;
@@ -9119,12 +9201,22 @@ var OwneySDK = class {
9119
9201
  }
9120
9202
  return { agentResults };
9121
9203
  } catch (error) {
9204
+ if (checkpointFailure && !(error instanceof OwneyError && error.details?.notSubmitted === false)) {
9205
+ error = error instanceof OwneyError && error.code === "DEPOSIT_PARTIAL_FAILURE" ? new OwneyError(
9206
+ error.code,
9207
+ "Some deposits completed before another agent could be submitted.",
9208
+ { ...error.details, cause: checkpointFailure },
9209
+ error.agentId
9210
+ ) : checkpointFailure;
9211
+ if (!options.resumeTxHash) for (const evidence of checkpointFailedEvidence)
9212
+ notifyFunding(onProgress, { ...evidence, transfer: "failed" });
9213
+ }
9122
9214
  if (!depositCallback && onProgress && !options.resumeTxHash) {
9123
9215
  const ids = agentId ? [agentId] : this.getEligibleAgents(chainId, asset).map((agent) => agent.id);
9124
9216
  for (const id of ids) {
9125
9217
  const evidence = [...prepared.values()].find((value) => value.agentId === id);
9126
- if (paidFallbackAgents.has(id) || evidence?.transfer === "confirmed" || evidence?.transfer === "failed") continue;
9127
9218
  const rejected = error instanceof OwneyError && error.details?.notSubmitted === true;
9219
+ if (!rejected && paidFallbackAgents.has(id) || evidence?.transfer === "confirmed" || evidence?.transfer === "failed") continue;
9128
9220
  if (!rejected && (evidence?.txHash || evidence?.userOpHash || evidence?.callsId)) continue;
9129
9221
  notifyFunding(onProgress, { ...evidence ?? {
9130
9222
  agentId: id,
@@ -9167,11 +9259,11 @@ var OwneySDK = class {
9167
9259
  * propagates unchanged. Scoped per agent invocation so one agent's failure
9168
9260
  * doesn't force a retry of sibling agents in a multi-agent split.
9169
9261
  */
9170
- async depositWithFallback(agent, state, chainId, amount, asset, effectiveCallback, appCallback, onProgress, onPaidFallback, resumeOnly = false) {
9262
+ async depositWithFallback(agent, state, chainId, amount, asset, effectiveCallback, appCallback, onProgress, onPaidFallback, resumeOnly = false, onBeforeSubmission) {
9171
9263
  const attempt = (callback) => withFailureReporting(
9172
9264
  this.apiKey,
9173
9265
  agent.id,
9174
- () => onProgress ? agent.deposit(state, chainId, amount, asset, callback, onProgress) : agent.deposit(state, chainId, amount, asset, callback),
9266
+ () => onBeforeSubmission ? agent.deposit(state, chainId, amount, asset, callback, onProgress, onBeforeSubmission) : onProgress ? agent.deposit(state, chainId, amount, asset, callback, onProgress) : agent.deposit(state, chainId, amount, asset, callback),
9175
9267
  this.routingApiBaseUrl
9176
9268
  );
9177
9269
  let approvalAttempted = false;