@owney/sdk 0.7.25-beta.1 → 0.7.25-beta.11

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.d.cts CHANGED
@@ -1,12 +1,23 @@
1
1
  import { Hex } from 'viem';
2
2
  import { SIWXConfig } from '@reown/appkit-controllers';
3
3
 
4
- type ZyfaiRpcUrlsConfig = Partial<Record<(typeof SUPPORTED_CHAIN_IDS)[number], string>>;
4
+ type RpcUrlsConfig = Partial<Record<(typeof SUPPORTED_CHAIN_IDS)[number], string>>;
5
+ /** @deprecated Use RpcUrlsConfig. */
6
+ type ZyfaiRpcUrlsConfig = RpcUrlsConfig;
5
7
  interface OwneySDKConfig {
6
8
  apiKey: string;
9
+ /**
10
+ * Optional per-chain RPC overrides used for application-owned reads and
11
+ * transaction receipt polling. Missing chains use the Owney routing API's
12
+ * read-only RPC proxy. No upstream RPC credentials are included in the SDK.
13
+ * Wallet providers remain responsible for account access, chain switching,
14
+ * signatures, and transaction submission.
15
+ */
16
+ rpcUrls?: RpcUrlsConfig;
7
17
  /**
8
18
  * Optional per-chain RPC overrides for Zyfai SDK network calls.
9
19
  * Example: { 8453: "https://...", 42161: "https://..." }
20
+ * @deprecated Use rpcUrls so every agent shares the same read transport.
10
21
  */
11
22
  zyfaiRpcUrls?: ZyfaiRpcUrlsConfig;
12
23
  /** Optional Owney Yieldseeker proxy base URL override for integration tests. */
@@ -15,9 +26,9 @@ interface OwneySDKConfig {
15
26
  yieldseekerSiweOrigin?: string;
16
27
  /**
17
28
  * Optional override for the Owney routing API base URL used by all routing
18
- * calls (defaults to the OWNEY_ROUTING_API_BASE_URL env var, then the
19
- * production URL). Set this to point at a local/staging routing API,
20
- * e.g. "http://localhost:3000", when testing sponsor changes.
29
+ * calls. RPC proxy requests use OWNEY_ROUTING_API_BASE_URL when this is
30
+ * omitted; without either value, all rpcUrls must be configured.
31
+ * Set this to a local/staging routing API when testing sponsor changes.
21
32
  */
22
33
  routingApiBaseUrl?: string;
23
34
  /**
@@ -59,6 +70,121 @@ type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
59
70
  type OwneySupportedChains = (typeof SUPPORTED_CHAINS)[number];
60
71
  type OwneySupportedTokens = (typeof SUPPORTED_TOKENS)[number];
61
72
 
73
+ /**
74
+ * One protocol's pool selection on one chain. `pools` holds Zyfai pool NAMES
75
+ * verbatim — matched case-sensitively by customizeBatch, and an unrecognised
76
+ * name makes Zyfai's rebalance engine skip the whole protocol, so these strings
77
+ * must not be normalised anywhere.
78
+ *
79
+ * An empty array means "no usable pools on this chain".
80
+ */
81
+ type OrgPoolSelection = {
82
+ protocolId: string;
83
+ chainId: number;
84
+ pools: string[];
85
+ };
86
+ /**
87
+ * The partner's protocol/pool policy (ROUT-224). Sparse — only protocols they
88
+ * narrowed appear. Optional so an older routing API, which does not return the
89
+ * field, still parses; undefined and null both mean "change nothing".
90
+ */
91
+ type OrgPoolPolicy = {
92
+ autoApproveProtocols: boolean;
93
+ autoApprovePools: boolean;
94
+ selections: OrgPoolSelection[];
95
+ };
96
+ /**
97
+ * The organization's agent execution policy, or null when the partner has never
98
+ * configured one — in which case the agents leave the user's profile alone.
99
+ */
100
+ type OrgAgentConfig = {
101
+ splittingMode: "none" | "automatic" | "force";
102
+ minSplits: number | null;
103
+ poolPolicy?: OrgPoolPolicy | null;
104
+ };
105
+
106
+ type DepositCallback = (smartWalletAddress: string, chainId: number, amount: string) => Promise<`0x${string}`> | `0x${string}`;
107
+ interface IAgent {
108
+ readonly id: string;
109
+ readonly supportedChainIds: readonly OwneySupportedChainId[];
110
+ readonly supportedAssets: readonly AgentSupportedAssets[];
111
+ /**
112
+ * Describes how `AgentBalance.tokens` relates to `positions`.
113
+ * Most adapters expose token totals that already include deployed positions.
114
+ * Providers such as Yieldseeker expose idle wallet tokens separately, so
115
+ * withdrawal planning must add matching position amounts.
116
+ */
117
+ readonly balanceComposition?: "tokens-include-positions" | "tokens-plus-positions";
118
+ /**
119
+ * Whether a withdrawal requires an owner-approved wallet transaction.
120
+ * Aggregate withdrawals run these agents before relayer-only agents so a
121
+ * rejected wallet request cannot happen after another leg has committed.
122
+ */
123
+ readonly withdrawalRequiresWalletApproval?: boolean;
124
+ disconnect(): Promise<void>;
125
+ activateAgent(state: ConnectionState, chainId: number, asset?: OwneySupportedTokens): Promise<void>;
126
+ /**
127
+ * Apply the organization's agent policy to this user's account.
128
+ *
129
+ * Optional: an agent that has no equivalent knob simply omits it, which is why
130
+ * this is not part of `activateAgent`'s signature. Declared on the interface
131
+ * rather than only on ZyfaiAgent so the contract stays agent-neutral — the
132
+ * ticket asks for a design that can also cover Surf, which has no adapter yet.
133
+ *
134
+ * Implementations must be **non-fatal**: this runs during activation as a side
135
+ * effect, so a failure has to leave the user connected and their profile
136
+ * unchanged rather than break the connect.
137
+ */
138
+ applyOrgPolicy?(state: ConnectionState, chainId: number, policy: OrgAgentConfig): Promise<void>;
139
+ deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback, onProgress?: FundingProgress): Promise<OwneyDepositResult>;
140
+ withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string, onProgress?: FundingProgress): Promise<AgentWithdrawResult>;
141
+ /** Invalidate only the confirmed asset. This hook must not sign or submit transactions. */
142
+ invalidateFundingRead?(state: ConnectionState, chainId: number, asset: OwneySupportedTokens, refreshUntil?: number): void;
143
+ /** End accelerated balance reads only for the exact snapshot the caller displayed. */
144
+ endFundingBalanceRefresh?(state: ConnectionState, chainId: number, asset: OwneySupportedTokens, read: AssetReadMetadata): boolean;
145
+ getFundingHistory?(state: ConnectionState, chainId: number, options?: HistoryFilters): Promise<OwneyAgentHistory>;
146
+ getFundingWallet?(state: ConnectionState, chainId: number, asset: OwneySupportedTokens): Promise<string>;
147
+ getBalances(state: ConnectionState, chainId: number, asset?: OwneySupportedTokens): Promise<AgentBalance>;
148
+ getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
149
+ /**
150
+ * Refresh the agent's earnings snapshot when its backend supports doing so.
151
+ * Implementations own freshness and request-deduplication policy.
152
+ */
153
+ refreshEarnings?(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
154
+ getAccountApy(state: ConnectionState, chainId: number, days: DailyApyDays,
155
+ /**
156
+ * Optional asset symbol ("USDC" / "WETH") scoping the daily series to a
157
+ * single asset on the chain. Agents without per-asset positions ignore it.
158
+ */
159
+ tokenSymbol?: string): Promise<AccountAgentApy>;
160
+ /**
161
+ * Daily cumulative NET earnings for the window, scoped to a chain/asset.
162
+ * Backs the "recent earnings" subline, whose figure must reconcile with the
163
+ * balance headline directly above it. (ROUT-452)
164
+ */
165
+ getDailyEarnings?(state: ConnectionState, chainId: number, days: LookbackDays, tokenSymbol?: string): Promise<AccountDailyEarnings>;
166
+ getHistory(state: ConnectionState, chainId: number, options?: HistoryFilters): Promise<OwneyAgentHistory>;
167
+ getUserProfile(state: ConnectionState, chainId: number): Promise<AgentUserProfile>;
168
+ /**
169
+ * Ensure the given asset uses backend protocol auto-selection
170
+ * (`autoSelectProtocols: true`). Optional capability — only agents whose
171
+ * backend models per-asset protocol selection implement it. Returns whether
172
+ * a write occurred (`false` = already enabled / not supported).
173
+ */
174
+ ensureAutoSelectProtocols?(state: ConnectionState, chainId: number, asset: "USDC" | "WETH"): Promise<boolean>;
175
+ getAgentApy(days: DailyApyDays, options?: AgentApyOptions): Promise<AgentApy>;
176
+ }
177
+ /**
178
+ * Optional filters for per-agent APY lookups.
179
+ * - `tokenSymbol` / `chainId` scope the APY to a specific asset+chain when
180
+ * the underlying provider supports it (Zyfai). Agents whose backends do
181
+ * not yet support per-asset APY will ignore these options.
182
+ */
183
+ type AgentApyOptions = {
184
+ tokenSymbol?: string;
185
+ chainId?: number;
186
+ };
187
+
62
188
  type AgentId = "zyfai" | "yieldseeker";
63
189
  type Asset = string;
64
190
  type AgentSupportedAsset = {
@@ -108,13 +234,19 @@ type HistoryFilters = {
108
234
  tokenSymbol?: string;
109
235
  };
110
236
  type HistoryOptions = {
237
+ chainId?: number;
111
238
  agentId?: AgentId;
112
239
  filters?: HistoryFilters;
113
240
  };
114
241
  type WithdrawOptions = {
242
+ /** Exclude unresolved providers from aggregate withdrawals; direct agent requests are unchanged. */
243
+ excludeAgentIds?: AgentId[];
244
+ onProgress?: FundingProgress;
115
245
  asset: Asset;
116
246
  amount?: string;
117
247
  agentId?: AgentId;
248
+ /** Called after each agent returns; callback failures never change a financial result. */
249
+ onAgentResult?: (agentId: AgentId, result: AgentWithdrawResult) => void;
118
250
  };
119
251
  type AccountApyOptions = {
120
252
  agentId?: AgentId;
@@ -161,6 +293,7 @@ type AgentsApyOptions = {
161
293
  chainId?: number;
162
294
  };
163
295
  type DepositOptions = {
296
+ onProgress?: FundingProgress;
164
297
  amount: string;
165
298
  asset: Asset;
166
299
  depositCallback?: DepositCallback;
@@ -168,40 +301,52 @@ type DepositOptions = {
168
301
  onApproved?: () => void;
169
302
  };
170
303
 
171
- /**
172
- * One protocol's pool selection on one chain. `pools` holds Zyfai pool NAMES
173
- * verbatim — matched case-sensitively by customizeBatch, and an unrecognised
174
- * name makes Zyfai's rebalance engine skip the whole protocol, so these strings
175
- * must not be normalised anywhere.
176
- *
177
- * An empty array means "no usable pools on this chain".
178
- */
179
- type OrgPoolSelection = {
180
- protocolId: string;
304
+ type FundingStage = "pending" | "confirmed" | "unknown" | "failed" | "not-applicable";
305
+ /** Evidence about one provider leg. Amounts are token base units, never USD. */
306
+ interface FundingEvidence {
307
+ agentId: AgentId;
181
308
  chainId: number;
182
- pools: string[];
183
- };
184
- /**
185
- * The partner's protocol/pool policy (ROUT-224). Sparse — only protocols they
186
- * narrowed appear. Optional so an older routing API, which does not return the
187
- * field, still parses; undefined and null both mean "change nothing".
188
- */
189
- type OrgPoolPolicy = {
190
- autoApproveProtocols: boolean;
191
- autoApprovePools: boolean;
192
- selections: OrgPoolSelection[];
193
- };
194
- /**
195
- * The organization's agent execution policy, or null when the partner has never
196
- * configured one — in which case the agents leave the user's profile alone.
197
- */
198
- type OrgAgentConfig = {
199
- splittingMode: "none" | "automatic" | "force";
200
- minSplits: number | null;
201
- poolPolicy?: OrgPoolPolicy | null;
202
- };
203
-
309
+ token: OwneySupportedTokens;
310
+ walletAddress: string;
311
+ agentWallet?: string;
312
+ intendedAmount: string;
313
+ confirmedAmount?: string;
314
+ txHash?: string;
315
+ blockNumber?: string;
316
+ logIndexes?: number[];
317
+ transferLogs?: {
318
+ logIndex: number;
319
+ amountRaw: string;
320
+ }[];
321
+ /** Sanitized execution-request evidence. Attempted does not prove server acceptance. */
322
+ withdrawalRequest?: {
323
+ attempted: boolean;
324
+ method?: "GET" | "POST";
325
+ path?: "/users/withdraw" | "/users/partial-withdraw";
326
+ elapsedMs?: number;
327
+ failure?: "network" | "unauthorized" | "forbidden" | "rate-limited" | "other";
328
+ };
329
+ transfer: FundingStage;
330
+ registration: FundingStage;
331
+ delivery: FundingStage;
332
+ }
333
+ type FundingProgress = (evidence: FundingEvidence) => void;
334
+ interface AssetReadMetadata {
335
+ chainId: number;
336
+ asset: string;
337
+ fetchedAt?: number;
338
+ /** When the underlying provider request started; preserved on cached reads. */
339
+ requestedAt?: number;
340
+ /** SDK cache generation, not an onchain block or provider timestamp. */
341
+ readVersion?: number;
342
+ providerUpdatedAt?: string;
343
+ snapshotId?: string;
344
+ blockNumber?: string;
345
+ netDepositsRaw?: string;
346
+ positionsStatus: "available" | "unavailable";
347
+ }
204
348
  interface OwneyDepositResult {
349
+ evidence?: FundingEvidence;
205
350
  txHash: string;
206
351
  smartWallet: string;
207
352
  amount: string;
@@ -210,6 +355,7 @@ interface OwneyMultiDepositResult {
210
355
  agentResults: Record<string, OwneyDepositResult>;
211
356
  }
212
357
  interface AgentWithdrawResult {
358
+ evidence?: FundingEvidence;
213
359
  txHash?: string;
214
360
  type: "full" | "partial";
215
361
  /** Smallest-unit amount, or a provider sentinel such as "all" for a full request. */
@@ -237,8 +383,10 @@ interface OwneyPosition {
237
383
  pool?: string;
238
384
  asset: string;
239
385
  amount: string;
240
- /** Smallest-unit amount when the provider exposes it alongside `amount`. */
386
+ /** Provider-native raw quantity; may represent vault shares, not the underlying asset. */
241
387
  amountRaw?: string;
388
+ /** Withdrawable underlying asset amount in that asset's smallest units. */
389
+ withdrawableAmountRaw?: string;
242
390
  apy?: number;
243
391
  tvl?: number;
244
392
  /** Pool liquidity. Prepared slot — Zyfai will add this to its portfolio
@@ -269,6 +417,7 @@ interface OwneyPendingAllocation {
269
417
  since?: string;
270
418
  }
271
419
  interface AgentBalance {
420
+ readMetadata?: AssetReadMetadata[];
272
421
  /** Authoritative native balances per asset/network, including idle and invested funds. */
273
422
  assetBalances?: OwneyToken[];
274
423
  smartWallet?: `0x${string}`;
@@ -313,6 +462,10 @@ interface AgentEarnings {
313
462
  interface OwneyEarnings {
314
463
  totalEarnings: string;
315
464
  agentEarnings: Record<AgentId, AgentEarnings>;
465
+ /** Per-agent failures when an aggregate read returned a partial result. */
466
+ agentErrors?: Partial<Record<AgentId, string>>;
467
+ /** Absolute provider cooldown deadlines (Unix milliseconds). */
468
+ agentRetryAt?: Partial<Record<AgentId, number>>;
316
469
  }
317
470
  type ApyByChainAndAsset = Partial<Record<OwneySupportedChainId, Partial<Record<OwneySupportedTokens, number>>>>;
318
471
  /** A single day's net APY for the connected account, as a percentage number. */
@@ -358,6 +511,15 @@ interface OwneyAllocationApy {
358
511
  }
359
512
  type HistoryAction = "Rebalance" | "Deposit" | "Top up" | "Withdraw" | "Earned";
360
513
  interface HistoryTransaction {
514
+ tokenAddress?: string;
515
+ agentWallet?: string;
516
+ logIndexes?: number[];
517
+ transferLogs?: {
518
+ logIndex: number;
519
+ amountRaw: string;
520
+ }[];
521
+ amountRaw?: string;
522
+ blockNumber?: string;
361
523
  txHashes: string[];
362
524
  chainId?: number;
363
525
  tokenSymbol?: string;
@@ -386,6 +548,8 @@ interface AgentHistoryPosition {
386
548
  amount?: string;
387
549
  }
388
550
  interface AgentHistoryEntry {
551
+ /** Stable provider/transfer identity, independent of row order. */
552
+ id?: string;
389
553
  agent: AgentId;
390
554
  action: HistoryAction;
391
555
  date: string;
@@ -396,6 +560,8 @@ interface AgentHistoryEntry {
396
560
  positions?: AgentHistoryPosition[];
397
561
  }
398
562
  interface OwneyAgentHistory {
563
+ agentErrors?: Partial<Record<AgentId, string>>;
564
+ agentRetryAt?: Partial<Record<AgentId, number>>;
399
565
  data: AgentHistoryEntry[];
400
566
  /** True iff a subsequent page exists; pair with `nextCursor`. */
401
567
  hasMore: boolean;
@@ -471,76 +637,6 @@ interface AccountDailyEarnings {
471
637
  assets: AssetDailyEarnings[];
472
638
  }
473
639
 
474
- type DepositCallback = (smartWalletAddress: string, chainId: number, amount: string) => Promise<`0x${string}`> | `0x${string}`;
475
- interface IAgent {
476
- readonly id: string;
477
- readonly supportedChainIds: readonly OwneySupportedChainId[];
478
- readonly supportedAssets: readonly AgentSupportedAssets[];
479
- /**
480
- * Describes how `AgentBalance.tokens` relates to `positions`.
481
- * Most adapters expose token totals that already include deployed positions.
482
- * Providers such as Yieldseeker expose idle wallet tokens separately, so
483
- * withdrawal planning must add matching position amounts.
484
- */
485
- readonly balanceComposition?: "tokens-include-positions" | "tokens-plus-positions";
486
- disconnect(): Promise<void>;
487
- activateAgent(state: ConnectionState, chainId: number, asset?: OwneySupportedTokens): Promise<void>;
488
- /**
489
- * Apply the organization's agent policy to this user's account.
490
- *
491
- * Optional: an agent that has no equivalent knob simply omits it, which is why
492
- * this is not part of `activateAgent`'s signature. Declared on the interface
493
- * rather than only on ZyfaiAgent so the contract stays agent-neutral — the
494
- * ticket asks for a design that can also cover Surf, which has no adapter yet.
495
- *
496
- * Implementations must be **non-fatal**: this runs during activation as a side
497
- * effect, so a failure has to leave the user connected and their profile
498
- * unchanged rather than break the connect.
499
- */
500
- applyOrgPolicy?(state: ConnectionState, chainId: number, policy: OrgAgentConfig): Promise<void>;
501
- deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
502
- withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
503
- getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
504
- getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
505
- /**
506
- * Refresh the agent's earnings snapshot when its backend supports doing so.
507
- * Implementations own freshness and request-deduplication policy.
508
- */
509
- refreshEarnings?(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
510
- getAccountApy(state: ConnectionState, chainId: number, days: DailyApyDays,
511
- /**
512
- * Optional asset symbol ("USDC" / "WETH") scoping the daily series to a
513
- * single asset on the chain. Agents without per-asset positions ignore it.
514
- */
515
- tokenSymbol?: string): Promise<AccountAgentApy>;
516
- /**
517
- * Daily cumulative NET earnings for the window, scoped to a chain/asset.
518
- * Backs the "recent earnings" subline, whose figure must reconcile with the
519
- * balance headline directly above it. (ROUT-452)
520
- */
521
- getDailyEarnings?(state: ConnectionState, chainId: number, days: LookbackDays, tokenSymbol?: string): Promise<AccountDailyEarnings>;
522
- getHistory(state: ConnectionState, chainId: number, options?: HistoryFilters): Promise<OwneyAgentHistory>;
523
- getUserProfile(state: ConnectionState, chainId: number): Promise<AgentUserProfile>;
524
- /**
525
- * Ensure the given asset uses backend protocol auto-selection
526
- * (`autoSelectProtocols: true`). Optional capability — only agents whose
527
- * backend models per-asset protocol selection implement it. Returns whether
528
- * a write occurred (`false` = already enabled / not supported).
529
- */
530
- ensureAutoSelectProtocols?(state: ConnectionState, chainId: number, asset: "USDC" | "WETH"): Promise<boolean>;
531
- getAgentApy(days: DailyApyDays, options?: AgentApyOptions): Promise<AgentApy>;
532
- }
533
- /**
534
- * Optional filters for per-agent APY lookups.
535
- * - `tokenSymbol` / `chainId` scope the APY to a specific asset+chain when
536
- * the underlying provider supports it (Zyfai). Agents whose backends do
537
- * not yet support per-asset APY will ignore these options.
538
- */
539
- type AgentApyOptions = {
540
- tokenSymbol?: string;
541
- chainId?: number;
542
- };
543
-
544
640
  declare class OwneySDK {
545
641
  private agents;
546
642
  private activeAgents;
@@ -554,6 +650,7 @@ declare class OwneySDK {
554
650
  private apiKey;
555
651
  private orgAgentConfig;
556
652
  private orgAgentConfigPromise;
653
+ private rpcUrls?;
557
654
  private zyfaiRpcUrls?;
558
655
  private yieldseekerApiBaseUrl?;
559
656
  private yieldseekerSiweOrigin?;
@@ -564,6 +661,7 @@ declare class OwneySDK {
564
661
  private paymasterServiceUrl?;
565
662
  private cachedSponsoredCallsCallbacks;
566
663
  private readonly agentReads;
664
+ private readonly recoveredFundingReads;
567
665
  private readonly activationChecks;
568
666
  private readAgent;
569
667
  private initializingAgentsPromise;
@@ -593,6 +691,7 @@ declare class OwneySDK {
593
691
  private requireState;
594
692
  private requireChainId;
595
693
  private requireConnectedProvider;
694
+ private getPaidRpcClient;
596
695
  /** Builds the default USDC batch callback for the connected wallet. */
597
696
  private getDefaultSponsoredCallback;
598
697
  /** Builds the wallet-native sponsored calls callback for compatible paymasters. */
@@ -605,6 +704,7 @@ declare class OwneySDK {
605
704
  */
606
705
  private getDefaultWethSponsoredCallback;
607
706
  private getAgent;
707
+ getActiveAgentIds(): AgentId[];
608
708
  private getActiveAgents;
609
709
  /**
610
710
  * Read the org's agent policy once and reuse it. fetchOrgAgentConfig never
@@ -676,10 +776,12 @@ declare class OwneySDK {
676
776
  * Invokes `agent.deposit` with the resolved sponsored callback, composing
677
777
  * two independent auto-recovery mechanisms:
678
778
  *
679
- * 1. Missing Permit2 allowance: when the app did not supply its own
680
- * callback and the attempt fails with `PERMIT2_APPROVAL_REQUIRED` on a
681
- * token deposit, this is the wallet's first Permit2 deposit for that token. We send
682
- * the one-time (user-paid) Permit2 approval via `approvePermit2()` and
779
+ * 1. Missing Permit2 allowance outside the atomic Base-USDC path: when the
780
+ * app did not supply its own callback and the attempt fails with
781
+ * `PERMIT2_APPROVAL_REQUIRED`, this is the wallet's first Permit2 deposit
782
+ * for that token. Base USDC bundles a gasless ERC-2612 approval inside
783
+ * its sponsored deposit and never reaches this branch. Other tokens send
784
+ * the one-time user-paid Permit2 approval via `approvePermit2()` and
683
785
  * retry the SAME sponsored attempt once. Bounded to one approval attempt
684
786
  * per call so a wallet/agent that keeps reporting the allowance as
685
787
  * missing can't loop forever. If `approvePermit2()` itself throws (e.g.
@@ -711,6 +813,24 @@ declare class OwneySDK {
711
813
  private hasExistingBalance;
712
814
  private validateAssetSupport;
713
815
  private getEligibleAgents;
816
+ /**
817
+ * Run owner-approved withdrawals before relayer-only withdrawals. Wallet
818
+ * approval is the only point at which the user can cancel the aggregate
819
+ * operation, so no relayer leg should commit before it has completed.
820
+ */
821
+ private orderAgentsForWithdrawal;
822
+ private isUserRejectedWithdrawal;
823
+ private captureReadScope;
824
+ /** Revalidate a saved transfer against the authenticated account and actual receipt. */
825
+ inspectFunding(evidence: FundingEvidence, direction: "deposit" | "withdraw", options?: {
826
+ balanceRefreshUntil?: number;
827
+ refreshBalance?: boolean;
828
+ }): Promise<FundingEvidence>;
829
+ /** A display acknowledgement controls polling only; it never confirms a financial outcome. */
830
+ endFundingBalanceRefresh(evidence: FundingEvidence, read: AssetReadMetadata): boolean;
831
+ /** History lookup for receipt recovery; adapters may not authenticate or sign here. */
832
+ getFundingHistory(evidence: FundingEvidence, fromDate: string, options?: Pick<HistoryFilters, "cursor" | "toDate">): Promise<OwneyAgentHistory>;
833
+ recoverDepositRegistration(evidence: FundingEvidence): Promise<FundingEvidence>;
714
834
  /**
715
835
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
716
836
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -721,12 +841,16 @@ declare class OwneySDK {
721
841
  * @returns {AgentWithdrawResult} for a single agent, or {OwneyWithdrawResult} with per-agent results
722
842
  */
723
843
  withdraw(options: WithdrawOptions): Promise<OwneyWithdrawResult | AgentWithdrawResult>;
844
+ private withdrawFromAgents;
724
845
  /**
725
846
  * Get the user's balances for a specific agent, or aggregated across all agents.
726
847
  * @param agentId - Optional. Agent to query. Omit for aggregated balances.
727
848
  * @returns {AgentBalance} for a single agent, or {OwneyBalances} with totalBalance and per-agent breakdown
728
849
  */
729
- getBalances(agentId?: AgentId): Promise<OwneyBalances | AgentBalance>;
850
+ getBalances(agentId?: AgentId, options?: {
851
+ chainId?: number;
852
+ asset?: OwneySupportedTokens;
853
+ }): Promise<OwneyBalances | AgentBalance>;
730
854
  /**
731
855
  * Get the user's on-chain earnings for a specific agent, or aggregated across all agents.
732
856
  * @param agentId - Optional. Agent to query. Omit for aggregated earnings.
@@ -738,6 +862,7 @@ declare class OwneySDK {
738
862
  * Agents without a refresh capability fall back to their current snapshot.
739
863
  */
740
864
  refreshEarnings(agentId?: AgentId): Promise<OwneyEarnings | AgentEarnings>;
865
+ private aggregateEarnings;
741
866
  /**
742
867
  * Get the weighted APY for the user's account over a time period.
743
868
  * When querying all agents, the total APY is a balance-weighted average.
@@ -793,14 +918,16 @@ declare class OwneySDK {
793
918
  ensureAutoSelectProtocols(asset: "USDC" | "WETH", agentId?: AgentId): Promise<boolean>;
794
919
  /**
795
920
  * User-paid approval of Permit2 on the selected token for the active chain.
796
- * Approves exactly the pending deposit amount. Another approval is required
797
- * for a later deposit once this allowance has been consumed. Resolves after
798
- * one confirmation so the subsequent deposit attempt sees the new allowance.
921
+ * Grants the maximum ERC20 allowance so later deposits do not require another
922
+ * approval. Resolves after one confirmation so the subsequent deposit attempt
923
+ * sees the new allowance. Deposit retries pass their captured chain id so a
924
+ * concurrent activation cannot redirect the approval to another network.
799
925
  *
800
926
  * @param requiredAmount Raw base-unit amount the pending deposit must cover.
927
+ * @param expectedChainId Chain captured by the deposit that requested approval.
801
928
  * @returns the approval transaction hash.
802
929
  */
803
- approvePermit2(asset?: OwneySupportedTokens, requiredAmount?: bigint): Promise<`0x${string}`>;
930
+ approvePermit2(asset?: OwneySupportedTokens, requiredAmount?: bigint, expectedChainId?: OwneySupportedChainId): Promise<`0x${string}`>;
804
931
  /**
805
932
  * Get the agent's average APY performance over a time period. Does not require a wallet connection.
806
933
  * @param options - Contains agentId (optional) and days ("7D", "14D", or "30D")
@@ -844,6 +971,8 @@ type YieldseekerAgentOptions = {
844
971
  baseUrl?: string;
845
972
  fetchFn?: YieldseekerFetch;
846
973
  auth?: YieldseekerAuthDependencies;
974
+ /** Dedicated read transport; Base is used for receipt polling. */
975
+ rpcUrls?: RpcUrlsConfig;
847
976
  /** Test seam for the wallet-submission/receipt boundary. */
848
977
  transactionExecutor?: (state: ConnectionState, chainId: number, transaction: YieldseekerTransaction) => Promise<Hex>;
849
978
  /** Test seam for transactions submitted outside transactionExecutor. */
@@ -852,6 +981,7 @@ type YieldseekerAgentOptions = {
852
981
  declare class YieldseekerAgent implements IAgent {
853
982
  readonly id = "yieldseeker";
854
983
  readonly balanceComposition: "tokens-plus-positions";
984
+ readonly withdrawalRequiresWalletApproval = true;
855
985
  readonly supportedChainIds: readonly [8453];
856
986
  readonly supportedAssets: readonly [{
857
987
  readonly chainId: 8453;
@@ -866,19 +996,37 @@ declare class YieldseekerAgent implements IAgent {
866
996
  }];
867
997
  private readonly api;
868
998
  private readonly auth;
999
+ private readonly rpcUrls?;
1000
+ private receiptClient?;
869
1001
  private readonly transactionExecutor?;
870
1002
  private readonly unwindReceiptWaiter?;
871
1003
  private readonly agentContexts;
872
1004
  private readonly users;
873
1005
  private readonly pendingAgents;
1006
+ private readonly pendingWalletContexts;
1007
+ private readonly readCache;
1008
+ private readonly pendingReads;
1009
+ private readGeneration;
1010
+ private readonly portfolioVersions;
1011
+ private readonly snapshotFailures;
1012
+ private readonly standardReadFailures;
1013
+ private readonly reconcileUntil;
1014
+ private readonly activityRefreshUntil;
1015
+ private readonly snapshotMovements;
1016
+ private readonly movementEpochs;
874
1017
  private readonly yieldOptions;
875
1018
  private readonly pendingYieldOptions;
876
1019
  constructor(owneyApiKey: string, options?: YieldseekerAgentOptions);
1020
+ private getReceiptClient;
877
1021
  disconnect(): Promise<void>;
878
1022
  activateAgent(state: ConnectionState, chainId: number, asset?: OwneySupportedTokens): Promise<void>;
879
- deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
880
- withdraw(state: ConnectionState, chainId: number, asset: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
881
- getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
1023
+ deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback, onProgress?: FundingProgress): Promise<OwneyDepositResult>;
1024
+ withdraw(state: ConnectionState, chainId: number, asset: OwneySupportedTokens, amount?: string, onProgress?: FundingProgress): Promise<AgentWithdrawResult>;
1025
+ private withdrawInternal;
1026
+ getBalances(state: ConnectionState, chainId: number, asset?: OwneySupportedTokens): Promise<AgentBalance>;
1027
+ invalidateFundingRead(state: ConnectionState, chainId: number, asset: OwneySupportedTokens, refreshUntil?: number): void;
1028
+ endFundingBalanceRefresh(state: ConnectionState, chainId: number, asset: OwneySupportedTokens, read: AssetReadMetadata): boolean;
1029
+ getFundingWallet(state: ConnectionState, chainId: number, asset: OwneySupportedTokens): Promise<string>;
882
1030
  getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
883
1031
  getAccountApy(state: ConnectionState, chainId: number, days: DailyApyDays, tokenSymbol?: string): Promise<AccountAgentApy>;
884
1032
  getHistory(state: ConnectionState, chainId: number, options?: HistoryFilters): Promise<OwneyAgentHistory>;
@@ -887,13 +1035,28 @@ declare class YieldseekerAgent implements IAgent {
887
1035
  private loadYieldOptions;
888
1036
  private userKey;
889
1037
  private contextKey;
1038
+ private assertSession;
1039
+ private cachedRead;
1040
+ private agentListKey;
1041
+ private listAgents;
1042
+ private contextForAgent;
890
1043
  private resolveUser;
891
1044
  private forgetUser;
892
1045
  private ensureAgent;
893
1046
  private findAgent;
894
1047
  private resolveAgent;
895
1048
  private loadPortfolio;
1049
+ private loadActivityPortfolio;
1050
+ private resolvePortfolioContexts;
1051
+ private portfolioVersion;
1052
+ private portfolioCacheMs;
1053
+ private snapshotMovement;
1054
+ private advancePortfolioVersion;
1055
+ private requestPortfolioSnapshot;
1056
+ private portfolioSnapshot;
896
1057
  private loadPortfolioContext;
1058
+ private loadActivityContext;
1059
+ private loadPortfolioParts;
897
1060
  private deployAgent;
898
1061
  private refreshSnapshotAfterMovement;
899
1062
  private agentPath;
@@ -913,7 +1076,7 @@ declare class YieldseekerAgent implements IAgent {
913
1076
  private invalidResponse;
914
1077
  }
915
1078
 
916
- type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "AGENT_ACTIVATION_PARTIAL_FAILURE" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_BALANCE_UNAVAILABLE" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "AGENT_API_ERROR" | "AGENT_AUTH_FAILED" | "AGENT_INVALID_RESPONSE" | "AGENT_TIMEOUT" | "AGENT_TRANSACTION_REVERTED" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
1079
+ type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "AGENT_ACTIVATION_PARTIAL_FAILURE" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_BALANCE_UNAVAILABLE" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "AGENT_API_ERROR" | "AGENT_AUTH_FAILED" | "AGENT_INVALID_RESPONSE" | "AGENT_TIMEOUT" | "AGENT_TRANSACTION_REVERTED" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "EARNINGS_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
917
1080
  declare class OwneyError extends Error {
918
1081
  readonly code: OwneyErrorCode;
919
1082
  readonly details?: Record<string, unknown>;
@@ -979,4 +1142,4 @@ type OwneySIWXConfig = {
979
1142
  */
980
1143
  declare function createOwneySIWX(config: OwneySIWXConfig): SIWXConfig;
981
1144
 
982
- export { type AccountAgentApy, type AccountApyOptions, type AccountDailyEarnings, type AgentApy, type AgentApyDetails, type AgentBalance, AgentChainIncompatibleError, type AgentEarnings, type AgentHistoryEntry, type AgentHistoryPosition, type AgentId, AgentNotFoundError, type AgentSupportedAsset, type AgentSupportedAssets, type AgentUserProfile, type AgentWithdrawResult, type AgentsApyOptions, type AllocationAgentApy, type AllocationApyOptions, type ApyByChainAndAsset, type ApyHistoryPoint, type Asset, type AssetDailyEarnings, type AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DailyEarningsOptions, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, type LookbackDays, NotConnectedError, type OwneyAccountApy, type OwneyAgentApy, type OwneyAgentHistory, type OwneyAllocationApy, type OwneyBalances, type OwneyDepositResult, type OwneyEarnings, OwneyError, type OwneyErrorCode, type OwneyMultiDepositResult, type OwneyPosition, OwneySDK, type OwneySDKConfig, type OwneySIWXConfig, type OwneySupportedChainId, type OwneySupportedChains, type OwneySupportedTokens, type OwneyToken, type OwneyUserProfile, type OwneyWithdrawResult, type RebalanceLog, type WithdrawOptions, YieldseekerAgent, createOwneySIWX, setOwneyDebug };
1145
+ export { type AccountAgentApy, type AccountApyOptions, type AccountDailyEarnings, type AgentApy, type AgentApyDetails, type AgentBalance, AgentChainIncompatibleError, type AgentEarnings, type AgentHistoryEntry, type AgentHistoryPosition, type AgentId, AgentNotFoundError, type AgentSupportedAsset, type AgentSupportedAssets, type AgentUserProfile, type AgentWithdrawResult, type AgentsApyOptions, type AllocationAgentApy, type AllocationApyOptions, type ApyByChainAndAsset, type ApyHistoryPoint, type Asset, type AssetDailyEarnings, type AssetReadMetadata, type AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DailyEarningsOptions, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type FundingEvidence, type FundingProgress, type FundingStage, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, type LookbackDays, NotConnectedError, type OwneyAccountApy, type OwneyAgentApy, type OwneyAgentHistory, type OwneyAllocationApy, type OwneyBalances, type OwneyDepositResult, type OwneyEarnings, OwneyError, type OwneyErrorCode, type OwneyMultiDepositResult, type OwneyPosition, OwneySDK, type OwneySDKConfig, type OwneySIWXConfig, type OwneySupportedChainId, type OwneySupportedChains, type OwneySupportedTokens, type OwneyToken, type OwneyUserProfile, type OwneyWithdrawResult, type RebalanceLog, type RpcUrlsConfig, type WithdrawOptions, YieldseekerAgent, type ZyfaiRpcUrlsConfig, createOwneySIWX, setOwneyDebug };