@owney/sdk 0.7.23-beta.0 → 0.7.23

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,103 +1,5 @@
1
1
  import { SIWXConfig } from '@reown/appkit-controllers';
2
2
 
3
- /**
4
- * Swap-to-yield types (ROUT-242).
5
- *
6
- * The SDK never talks to 1inch directly — the API key is a paid credential and
7
- * lives in the routing API. Everything here describes the routing API's
8
- * `/api/v1/swap/*` contract.
9
- */
10
- /**
11
- * Which rail a swap rides, decided server-side from the chains.
12
- *
13
- * `classic` — same chain. One atomic transaction: it either completes or
14
- * nothing moved.
15
- *
16
- * `fusion-plus` — crossing chains. The user's funds sit in an escrow while a
17
- * resolver fills the other side, so the order has a lifecycle and can end in
18
- * `expired` → `refunding` → `refunded` without ever depositing.
19
- */
20
- type SwapRail = "classic" | "fusion-plus";
21
- type SwapTokenInfo = {
22
- readonly symbol: string;
23
- readonly address: string;
24
- readonly decimals: number;
25
- /** Native asset (ETH). A swap SOURCE only — never a deposit target. */
26
- readonly isNative?: true;
27
- };
28
- type SwapChainTokens = {
29
- readonly chainId: number;
30
- /** What the user may pay with. */
31
- readonly sources: readonly SwapTokenInfo[];
32
- /** What a swap may resolve into — what Owney actually deposits. */
33
- readonly depositTargets: readonly SwapTokenInfo[];
34
- };
35
- type SwapQuote = {
36
- rail: SwapRail;
37
- src: {
38
- chainId: number;
39
- symbol: string;
40
- address: string;
41
- amount: string;
42
- };
43
- dst: {
44
- chainId: number;
45
- symbol: string;
46
- address: string;
47
- amount: string;
48
- };
49
- /**
50
- * Worst-case output once the Dutch auction has fully decayed. Gate minimum
51
- * deposit checks on THIS, not `dst.amount` — a fill at auction end that lands
52
- * under the agent's floor would leave the user swapped but not deposited.
53
- */
54
- dstAmountMin: string;
55
- /** Cross-chain only. Per-order escrow schedule in seconds, set by 1inch. */
56
- timeLocks?: Record<string, number>;
57
- /**
58
- * Cross-chain only. How many preimages to mint before building an order.
59
- * Building with the wrong number produces escrows the user's secrets cannot
60
- * unlock, stranding the swap until its cancellation timelock.
61
- */
62
- secretsCount?: number;
63
- /**
64
- * Cross-chain only. The contract the source token must be approved to (the
65
- * 1inch Limit Order Protocol) before a resolver can fill the order.
66
- *
67
- * Absent on the classic rail, where the router address arrives with the swap
68
- * calldata instead.
69
- */
70
- spender?: string;
71
- /**
72
- * True only for a cross-chain swap FROM native ETH, which needs an on-chain
73
- * order creation carrying the full amount as msg.value. The user's funds
74
- * leave the wallet before any fill, so the UI must say so. ERC-20 sources are
75
- * signature-only after their one-time approval.
76
- */
77
- requiresOnchainOrder: boolean;
78
- };
79
- /**
80
- * Terminal states are `executed`, `expired`, `cancelled` and `refunded`.
81
- * `refunding` is the window the returning-funds screen renders: the order has
82
- * failed and the money is on its way back, but is not back yet.
83
- */
84
- type SwapOrderStatus = "pending" | "executed" | "expired" | "cancelled" | "refunding" | "refunded" | "unpublished";
85
- /** Stage reported to the UI while a swap-and-deposit runs. */
86
- type SwapStage = "quoting" | "approving" | "signing" | "swapping" | "swapped" | "depositing" | "refunding" | "refunded";
87
- type SwapQuoteParams = {
88
- /** Asset the user is paying WITH. */
89
- from: {
90
- chainId: number;
91
- symbol: string;
92
- amount: string;
93
- };
94
- /** Deposit target. Must be an asset Owney can actually deposit. */
95
- to: {
96
- chainId: number;
97
- symbol: string;
98
- };
99
- };
100
-
101
3
  type ZyfaiRpcUrlsConfig = Partial<Record<(typeof SUPPORTED_CHAIN_IDS)[number], string>>;
102
4
  interface OwneySDKConfig {
103
5
  apiKey: string;
@@ -493,6 +395,30 @@ interface AgentApy {
493
395
  interface OwneyAgentApy {
494
396
  agentApy: Record<AgentId, AgentApy>;
495
397
  }
398
+ /** One day's cumulative NET earnings for the selected chain/asset. */
399
+ interface DailyEarningsPoint {
400
+ /** ISO date string for the day, e.g. "2026-09-01". */
401
+ date: string;
402
+ /** Cumulative net-of-fee earnings as of this day, in the asset's units. */
403
+ net: number;
404
+ }
405
+ interface AccountDailyEarnings {
406
+ walletAddress: string;
407
+ /**
408
+ * Cumulative net-earnings series for the requested window, ascending by date.
409
+ * Empty when the provider returns no snapshots for this chain/asset.
410
+ */
411
+ points: DailyEarningsPoint[];
412
+ }
413
+ /** Earnings accrued across a window, derived from an AccountDailyEarnings series. */
414
+ interface RecentEarnings {
415
+ /** Net earnings over the window; never negative. */
416
+ amount: number;
417
+ /** Days actually spanned by the series — not necessarily the days requested. */
418
+ spanDays: number;
419
+ /** True when the series is shorter than the requested window. */
420
+ isTruncated: boolean;
421
+ }
496
422
 
497
423
  type DepositCallback = (smartWalletAddress: string, chainId: number, amount: string) => Promise<`0x${string}`> | `0x${string}`;
498
424
  interface IAgent {
@@ -529,6 +455,12 @@ interface IAgent {
529
455
  * single asset on the chain. Agents without per-asset positions ignore it.
530
456
  */
531
457
  tokenSymbol?: string): Promise<AccountAgentApy>;
458
+ /**
459
+ * Daily cumulative NET earnings for the window, scoped to a chain/asset.
460
+ * Backs the "recent earnings" subline, whose figure must reconcile with the
461
+ * balance headline directly above it. (ROUT-452)
462
+ */
463
+ getDailyEarnings?(state: ConnectionState, chainId: number, days: DailyApyDays, tokenSymbol?: string): Promise<AccountDailyEarnings>;
532
464
  getHistory(state: ConnectionState, chainId: number, options?: HistoryFilters): Promise<OwneyAgentHistory>;
533
465
  getUserProfile(state: ConnectionState, chainId: number): Promise<AgentUserProfile>;
534
466
  /**
@@ -727,83 +659,6 @@ declare class OwneySDK {
727
659
  private hasExistingBalance;
728
660
  private validateAssetSupport;
729
661
  private getEligibleAgents;
730
- /** Lazily built so an app that never swaps pays nothing for it. */
731
- private swapApiClient?;
732
- private swapApi;
733
- /**
734
- * Put the wallet on `chainId`, or fail with something actionable.
735
- *
736
- * Reuses the same guard the deposit rail uses, which re-reads the chain after
737
- * switching — some wallets resolve wallet_switchEthereumChain before the
738
- * network has actually changed.
739
- */
740
- private ensureSwapChain;
741
- /**
742
- * Binds the executor's abstract deps to this client's wallet.
743
- *
744
- * Kept as a builder rather than baked into the executor so the whole swap
745
- * flow stays testable without a provider — the executor never imports viem.
746
- */
747
- private buildSwapDeps;
748
- /**
749
- * Assets the user may pay with, and what each chain deposits into.
750
- *
751
- * The source list is deliberately wider than the deposit list: it includes
752
- * native ETH and USDT, which Owney never holds but users often do.
753
- */
754
- getSwapTokens(): Promise<{
755
- chains: SwapChainTokens[];
756
- }>;
757
- /**
758
- * Price a swap without committing to it.
759
- *
760
- * `dstAmountMin` is the number to validate against a deposit minimum —
761
- * `dst.amount` is an estimate that a decaying auction or slippage can undercut,
762
- * and a swap landing below the floor leaves the user swapped but not
763
- * deposited.
764
- */
765
- getSwapQuote(params: SwapQuoteParams): Promise<SwapQuote>;
766
- /**
767
- * Swap an asset the user holds into a deposit asset, then deposit it.
768
- *
769
- * Kept separate from `deposit()` rather than bolted on as an option: the
770
- * return shape differs, the staging callback is meaningless on the plain
771
- * path, and integrators who never swap should not have to reason about any
772
- * of it.
773
- *
774
- * The deposit runs on the MEASURED arrival, not the quote. A quote is an
775
- * estimate, so depositing the quoted figure would either strand dust or try
776
- * to move funds that never came.
777
- *
778
- * Failure modes differ in a way callers must respect. A same-chain swap is
779
- * atomic — if it fails, nothing moved. A cross-chain swap escrows the user's
780
- * funds first, so SWAP_ORDER_EXPIRED / REFUNDED / CANCELLED all mean the
781
- * money left the wallet. Only the former can honestly say "nothing has left
782
- * your wallet".
783
- */
784
- swapAndDeposit(options: {
785
- from: {
786
- chainId: number;
787
- symbol: string;
788
- amount: string;
789
- };
790
- /** Deposit target. Defaults to the active chain's asset when omitted. */
791
- to: {
792
- chainId: number;
793
- symbol: string;
794
- };
795
- agentId?: AgentId;
796
- /** Percent, classic rail only. Fusion+ prices through its auction. */
797
- slippage?: number;
798
- onSwapProgress?: (stage: SwapStage) => void;
799
- }): Promise<{
800
- swap: {
801
- received: string;
802
- orderHash?: string;
803
- txHash?: string;
804
- };
805
- deposit: OwneyDepositResult | OwneyMultiDepositResult;
806
- }>;
807
662
  /**
808
663
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
809
664
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -839,6 +694,18 @@ declare class OwneySDK {
839
694
  * @param options.days - Lookback period: "7D", "14D", or "30D"
840
695
  * @returns {AccountAgentApy} for a single agent, or {OwneyAccountApy} with totalApy and per-agent breakdown
841
696
  */
697
+ /**
698
+ * Daily cumulative NET earnings for the selected chain/asset, backing the
699
+ * "recent earnings" subline. Net is computed as Zyfai's own
700
+ * `lifetime + unrealized + current x 0.9`, so the figure reconciles with the
701
+ * balance headline rather than reading ~11% high. (ROUT-452)
702
+ *
703
+ * Unlike getAccountApy this does NOT blend across agents: earnings are
704
+ * summed, not weighted, and an agent that fails to report must not silently
705
+ * subtract from the total. Without an agentId the series is the sum of the
706
+ * agents that answered.
707
+ */
708
+ getDailyEarnings({ agentId, days, tokenSymbol, }: AccountApyOptions): Promise<AccountDailyEarnings>;
842
709
  getAccountApy({ agentId, days, tokenSymbol, }: AccountApyOptions): Promise<OwneyAccountApy | AccountAgentApy>;
843
710
  /**
844
711
  * Get transaction history for a specific agent, or all agents.
@@ -904,7 +771,7 @@ declare class OwneySDK {
904
771
  getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
905
772
  }
906
773
 
907
- 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" | "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_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
774
+ 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" | "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_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "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";
908
775
  declare class OwneyError extends Error {
909
776
  readonly code: OwneyErrorCode;
910
777
  readonly details?: Record<string, unknown>;
@@ -957,6 +824,21 @@ declare global {
957
824
  /** Enable/disable debug logging programmatically. */
958
825
  declare function setOwneyDebug(enabled: boolean): void;
959
826
 
827
+ /**
828
+ * Earnings accrued across a window, as the difference between the series'
829
+ * endpoints.
830
+ *
831
+ * Differencing endpoints rather than summing `daily_total_delta_by_token`
832
+ * means a missing day in the middle of the window cannot undercount the
833
+ * result — the two endpoints are cumulative totals, so whatever happened in
834
+ * between is already priced in.
835
+ *
836
+ * `requestedDays` is the window the user selected in the APY chart. When the
837
+ * series is shorter than that, the caller relabels ("Since you started")
838
+ * rather than claiming a window we don't have data for.
839
+ */
840
+ declare function recentEarningsFromPoints(points: DailyEarningsPoint[], requestedDays?: number): RecentEarnings | null;
841
+
960
842
  type OwneySIWXConfig = {
961
843
  /** Owney/Zyfai API key — same value passed to `new OwneySDK({ apiKey })`. */
962
844
  apiKey: string;
@@ -970,40 +852,4 @@ type OwneySIWXConfig = {
970
852
  */
971
853
  declare function createOwneySIWX(config: OwneySIWXConfig): SIWXConfig;
972
854
 
973
- /**
974
- * Persists cross-chain swap secrets so an in-flight order survives a reload.
975
- *
976
- * This is not a convenience. A Fusion+ order is only completable by whoever
977
- * holds the secret preimages: the resolver deploys escrows, then waits for the
978
- * secret before it can claim and release funds to the user. Lose the secrets
979
- * mid-order and the swap cannot complete — the user waits out the cancellation
980
- * timelock for a refund instead.
981
- *
982
- * That matters here because the UI explicitly tells the user "you can safely
983
- * close this window", so surviving a reload is a requirement, not a nicety.
984
- *
985
- * Trade-off: the same one `zyfai.auth-cache` makes. Secrets in `localStorage`
986
- * are exposed to XSS, but they are single-use, worthless once the order
987
- * settles, and only ever unlock funds back to the user's own wallet.
988
- */
989
- type StoredOrder = {
990
- orderHash: string;
991
- /** Preimages, one per fill. Index matters — fill N needs secret N. */
992
- secrets: string[];
993
- /** Chain the funds left from, so a resumed session can report it. */
994
- srcChainId: number;
995
- /** For the resumed UI: what the user was paying with and expecting. */
996
- srcSymbol: string;
997
- dstSymbol: string;
998
- dstChainId: number;
999
- amount: string;
1000
- /** Epoch ms. Used to drop orders far past any plausible timelock. */
1001
- createdAt: number;
1002
- };
1003
- /**
1004
- * Every stored order, newest first, dropping anything past MAX_AGE_MS.
1005
- * Used on mount to resume orders the user left in flight.
1006
- */
1007
- declare function listOrders(now?: number): StoredOrder[];
1008
-
1009
- export { type AccountAgentApy, type AccountApyOptions, 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 AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, 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 SwapChainTokens, type SwapOrderStatus, type SwapQuote, type SwapQuoteParams, type SwapRail, type SwapStage, type SwapTokenInfo, type WithdrawOptions, createOwneySIWX, listOrders as listPendingSwaps, setOwneyDebug };
855
+ 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 AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, 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 RecentEarnings, type WithdrawOptions, createOwneySIWX, recentEarningsFromPoints, setOwneyDebug };
package/dist/index.d.ts CHANGED
@@ -1,103 +1,5 @@
1
1
  import { SIWXConfig } from '@reown/appkit-controllers';
2
2
 
3
- /**
4
- * Swap-to-yield types (ROUT-242).
5
- *
6
- * The SDK never talks to 1inch directly — the API key is a paid credential and
7
- * lives in the routing API. Everything here describes the routing API's
8
- * `/api/v1/swap/*` contract.
9
- */
10
- /**
11
- * Which rail a swap rides, decided server-side from the chains.
12
- *
13
- * `classic` — same chain. One atomic transaction: it either completes or
14
- * nothing moved.
15
- *
16
- * `fusion-plus` — crossing chains. The user's funds sit in an escrow while a
17
- * resolver fills the other side, so the order has a lifecycle and can end in
18
- * `expired` → `refunding` → `refunded` without ever depositing.
19
- */
20
- type SwapRail = "classic" | "fusion-plus";
21
- type SwapTokenInfo = {
22
- readonly symbol: string;
23
- readonly address: string;
24
- readonly decimals: number;
25
- /** Native asset (ETH). A swap SOURCE only — never a deposit target. */
26
- readonly isNative?: true;
27
- };
28
- type SwapChainTokens = {
29
- readonly chainId: number;
30
- /** What the user may pay with. */
31
- readonly sources: readonly SwapTokenInfo[];
32
- /** What a swap may resolve into — what Owney actually deposits. */
33
- readonly depositTargets: readonly SwapTokenInfo[];
34
- };
35
- type SwapQuote = {
36
- rail: SwapRail;
37
- src: {
38
- chainId: number;
39
- symbol: string;
40
- address: string;
41
- amount: string;
42
- };
43
- dst: {
44
- chainId: number;
45
- symbol: string;
46
- address: string;
47
- amount: string;
48
- };
49
- /**
50
- * Worst-case output once the Dutch auction has fully decayed. Gate minimum
51
- * deposit checks on THIS, not `dst.amount` — a fill at auction end that lands
52
- * under the agent's floor would leave the user swapped but not deposited.
53
- */
54
- dstAmountMin: string;
55
- /** Cross-chain only. Per-order escrow schedule in seconds, set by 1inch. */
56
- timeLocks?: Record<string, number>;
57
- /**
58
- * Cross-chain only. How many preimages to mint before building an order.
59
- * Building with the wrong number produces escrows the user's secrets cannot
60
- * unlock, stranding the swap until its cancellation timelock.
61
- */
62
- secretsCount?: number;
63
- /**
64
- * Cross-chain only. The contract the source token must be approved to (the
65
- * 1inch Limit Order Protocol) before a resolver can fill the order.
66
- *
67
- * Absent on the classic rail, where the router address arrives with the swap
68
- * calldata instead.
69
- */
70
- spender?: string;
71
- /**
72
- * True only for a cross-chain swap FROM native ETH, which needs an on-chain
73
- * order creation carrying the full amount as msg.value. The user's funds
74
- * leave the wallet before any fill, so the UI must say so. ERC-20 sources are
75
- * signature-only after their one-time approval.
76
- */
77
- requiresOnchainOrder: boolean;
78
- };
79
- /**
80
- * Terminal states are `executed`, `expired`, `cancelled` and `refunded`.
81
- * `refunding` is the window the returning-funds screen renders: the order has
82
- * failed and the money is on its way back, but is not back yet.
83
- */
84
- type SwapOrderStatus = "pending" | "executed" | "expired" | "cancelled" | "refunding" | "refunded" | "unpublished";
85
- /** Stage reported to the UI while a swap-and-deposit runs. */
86
- type SwapStage = "quoting" | "approving" | "signing" | "swapping" | "swapped" | "depositing" | "refunding" | "refunded";
87
- type SwapQuoteParams = {
88
- /** Asset the user is paying WITH. */
89
- from: {
90
- chainId: number;
91
- symbol: string;
92
- amount: string;
93
- };
94
- /** Deposit target. Must be an asset Owney can actually deposit. */
95
- to: {
96
- chainId: number;
97
- symbol: string;
98
- };
99
- };
100
-
101
3
  type ZyfaiRpcUrlsConfig = Partial<Record<(typeof SUPPORTED_CHAIN_IDS)[number], string>>;
102
4
  interface OwneySDKConfig {
103
5
  apiKey: string;
@@ -493,6 +395,30 @@ interface AgentApy {
493
395
  interface OwneyAgentApy {
494
396
  agentApy: Record<AgentId, AgentApy>;
495
397
  }
398
+ /** One day's cumulative NET earnings for the selected chain/asset. */
399
+ interface DailyEarningsPoint {
400
+ /** ISO date string for the day, e.g. "2026-09-01". */
401
+ date: string;
402
+ /** Cumulative net-of-fee earnings as of this day, in the asset's units. */
403
+ net: number;
404
+ }
405
+ interface AccountDailyEarnings {
406
+ walletAddress: string;
407
+ /**
408
+ * Cumulative net-earnings series for the requested window, ascending by date.
409
+ * Empty when the provider returns no snapshots for this chain/asset.
410
+ */
411
+ points: DailyEarningsPoint[];
412
+ }
413
+ /** Earnings accrued across a window, derived from an AccountDailyEarnings series. */
414
+ interface RecentEarnings {
415
+ /** Net earnings over the window; never negative. */
416
+ amount: number;
417
+ /** Days actually spanned by the series — not necessarily the days requested. */
418
+ spanDays: number;
419
+ /** True when the series is shorter than the requested window. */
420
+ isTruncated: boolean;
421
+ }
496
422
 
497
423
  type DepositCallback = (smartWalletAddress: string, chainId: number, amount: string) => Promise<`0x${string}`> | `0x${string}`;
498
424
  interface IAgent {
@@ -529,6 +455,12 @@ interface IAgent {
529
455
  * single asset on the chain. Agents without per-asset positions ignore it.
530
456
  */
531
457
  tokenSymbol?: string): Promise<AccountAgentApy>;
458
+ /**
459
+ * Daily cumulative NET earnings for the window, scoped to a chain/asset.
460
+ * Backs the "recent earnings" subline, whose figure must reconcile with the
461
+ * balance headline directly above it. (ROUT-452)
462
+ */
463
+ getDailyEarnings?(state: ConnectionState, chainId: number, days: DailyApyDays, tokenSymbol?: string): Promise<AccountDailyEarnings>;
532
464
  getHistory(state: ConnectionState, chainId: number, options?: HistoryFilters): Promise<OwneyAgentHistory>;
533
465
  getUserProfile(state: ConnectionState, chainId: number): Promise<AgentUserProfile>;
534
466
  /**
@@ -727,83 +659,6 @@ declare class OwneySDK {
727
659
  private hasExistingBalance;
728
660
  private validateAssetSupport;
729
661
  private getEligibleAgents;
730
- /** Lazily built so an app that never swaps pays nothing for it. */
731
- private swapApiClient?;
732
- private swapApi;
733
- /**
734
- * Put the wallet on `chainId`, or fail with something actionable.
735
- *
736
- * Reuses the same guard the deposit rail uses, which re-reads the chain after
737
- * switching — some wallets resolve wallet_switchEthereumChain before the
738
- * network has actually changed.
739
- */
740
- private ensureSwapChain;
741
- /**
742
- * Binds the executor's abstract deps to this client's wallet.
743
- *
744
- * Kept as a builder rather than baked into the executor so the whole swap
745
- * flow stays testable without a provider — the executor never imports viem.
746
- */
747
- private buildSwapDeps;
748
- /**
749
- * Assets the user may pay with, and what each chain deposits into.
750
- *
751
- * The source list is deliberately wider than the deposit list: it includes
752
- * native ETH and USDT, which Owney never holds but users often do.
753
- */
754
- getSwapTokens(): Promise<{
755
- chains: SwapChainTokens[];
756
- }>;
757
- /**
758
- * Price a swap without committing to it.
759
- *
760
- * `dstAmountMin` is the number to validate against a deposit minimum —
761
- * `dst.amount` is an estimate that a decaying auction or slippage can undercut,
762
- * and a swap landing below the floor leaves the user swapped but not
763
- * deposited.
764
- */
765
- getSwapQuote(params: SwapQuoteParams): Promise<SwapQuote>;
766
- /**
767
- * Swap an asset the user holds into a deposit asset, then deposit it.
768
- *
769
- * Kept separate from `deposit()` rather than bolted on as an option: the
770
- * return shape differs, the staging callback is meaningless on the plain
771
- * path, and integrators who never swap should not have to reason about any
772
- * of it.
773
- *
774
- * The deposit runs on the MEASURED arrival, not the quote. A quote is an
775
- * estimate, so depositing the quoted figure would either strand dust or try
776
- * to move funds that never came.
777
- *
778
- * Failure modes differ in a way callers must respect. A same-chain swap is
779
- * atomic — if it fails, nothing moved. A cross-chain swap escrows the user's
780
- * funds first, so SWAP_ORDER_EXPIRED / REFUNDED / CANCELLED all mean the
781
- * money left the wallet. Only the former can honestly say "nothing has left
782
- * your wallet".
783
- */
784
- swapAndDeposit(options: {
785
- from: {
786
- chainId: number;
787
- symbol: string;
788
- amount: string;
789
- };
790
- /** Deposit target. Defaults to the active chain's asset when omitted. */
791
- to: {
792
- chainId: number;
793
- symbol: string;
794
- };
795
- agentId?: AgentId;
796
- /** Percent, classic rail only. Fusion+ prices through its auction. */
797
- slippage?: number;
798
- onSwapProgress?: (stage: SwapStage) => void;
799
- }): Promise<{
800
- swap: {
801
- received: string;
802
- orderHash?: string;
803
- txHash?: string;
804
- };
805
- deposit: OwneyDepositResult | OwneyMultiDepositResult;
806
- }>;
807
662
  /**
808
663
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
809
664
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -839,6 +694,18 @@ declare class OwneySDK {
839
694
  * @param options.days - Lookback period: "7D", "14D", or "30D"
840
695
  * @returns {AccountAgentApy} for a single agent, or {OwneyAccountApy} with totalApy and per-agent breakdown
841
696
  */
697
+ /**
698
+ * Daily cumulative NET earnings for the selected chain/asset, backing the
699
+ * "recent earnings" subline. Net is computed as Zyfai's own
700
+ * `lifetime + unrealized + current x 0.9`, so the figure reconciles with the
701
+ * balance headline rather than reading ~11% high. (ROUT-452)
702
+ *
703
+ * Unlike getAccountApy this does NOT blend across agents: earnings are
704
+ * summed, not weighted, and an agent that fails to report must not silently
705
+ * subtract from the total. Without an agentId the series is the sum of the
706
+ * agents that answered.
707
+ */
708
+ getDailyEarnings({ agentId, days, tokenSymbol, }: AccountApyOptions): Promise<AccountDailyEarnings>;
842
709
  getAccountApy({ agentId, days, tokenSymbol, }: AccountApyOptions): Promise<OwneyAccountApy | AccountAgentApy>;
843
710
  /**
844
711
  * Get transaction history for a specific agent, or all agents.
@@ -904,7 +771,7 @@ declare class OwneySDK {
904
771
  getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
905
772
  }
906
773
 
907
- 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" | "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_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
774
+ 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" | "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_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "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";
908
775
  declare class OwneyError extends Error {
909
776
  readonly code: OwneyErrorCode;
910
777
  readonly details?: Record<string, unknown>;
@@ -957,6 +824,21 @@ declare global {
957
824
  /** Enable/disable debug logging programmatically. */
958
825
  declare function setOwneyDebug(enabled: boolean): void;
959
826
 
827
+ /**
828
+ * Earnings accrued across a window, as the difference between the series'
829
+ * endpoints.
830
+ *
831
+ * Differencing endpoints rather than summing `daily_total_delta_by_token`
832
+ * means a missing day in the middle of the window cannot undercount the
833
+ * result — the two endpoints are cumulative totals, so whatever happened in
834
+ * between is already priced in.
835
+ *
836
+ * `requestedDays` is the window the user selected in the APY chart. When the
837
+ * series is shorter than that, the caller relabels ("Since you started")
838
+ * rather than claiming a window we don't have data for.
839
+ */
840
+ declare function recentEarningsFromPoints(points: DailyEarningsPoint[], requestedDays?: number): RecentEarnings | null;
841
+
960
842
  type OwneySIWXConfig = {
961
843
  /** Owney/Zyfai API key — same value passed to `new OwneySDK({ apiKey })`. */
962
844
  apiKey: string;
@@ -970,40 +852,4 @@ type OwneySIWXConfig = {
970
852
  */
971
853
  declare function createOwneySIWX(config: OwneySIWXConfig): SIWXConfig;
972
854
 
973
- /**
974
- * Persists cross-chain swap secrets so an in-flight order survives a reload.
975
- *
976
- * This is not a convenience. A Fusion+ order is only completable by whoever
977
- * holds the secret preimages: the resolver deploys escrows, then waits for the
978
- * secret before it can claim and release funds to the user. Lose the secrets
979
- * mid-order and the swap cannot complete — the user waits out the cancellation
980
- * timelock for a refund instead.
981
- *
982
- * That matters here because the UI explicitly tells the user "you can safely
983
- * close this window", so surviving a reload is a requirement, not a nicety.
984
- *
985
- * Trade-off: the same one `zyfai.auth-cache` makes. Secrets in `localStorage`
986
- * are exposed to XSS, but they are single-use, worthless once the order
987
- * settles, and only ever unlock funds back to the user's own wallet.
988
- */
989
- type StoredOrder = {
990
- orderHash: string;
991
- /** Preimages, one per fill. Index matters — fill N needs secret N. */
992
- secrets: string[];
993
- /** Chain the funds left from, so a resumed session can report it. */
994
- srcChainId: number;
995
- /** For the resumed UI: what the user was paying with and expecting. */
996
- srcSymbol: string;
997
- dstSymbol: string;
998
- dstChainId: number;
999
- amount: string;
1000
- /** Epoch ms. Used to drop orders far past any plausible timelock. */
1001
- createdAt: number;
1002
- };
1003
- /**
1004
- * Every stored order, newest first, dropping anything past MAX_AGE_MS.
1005
- * Used on mount to resume orders the user left in flight.
1006
- */
1007
- declare function listOrders(now?: number): StoredOrder[];
1008
-
1009
- export { type AccountAgentApy, type AccountApyOptions, 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 AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, 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 SwapChainTokens, type SwapOrderStatus, type SwapQuote, type SwapQuoteParams, type SwapRail, type SwapStage, type SwapTokenInfo, type WithdrawOptions, createOwneySIWX, listOrders as listPendingSwaps, setOwneyDebug };
855
+ 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 AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, 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 RecentEarnings, type WithdrawOptions, createOwneySIWX, recentEarningsFromPoints, setOwneyDebug };