@spicenet-io/spiceflow-ui 4.10.0-next.3 → 4.10.0-rc.0

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.
Files changed (92) hide show
  1. package/README.md +145 -28
  2. package/dist/auth-privy.cjs.js +1 -1
  3. package/dist/auth-privy.js +1 -1
  4. package/dist/components/AccountDisplay/parts/AccountCustomSection.d.ts +1 -1
  5. package/dist/components/AccountDisplay/parts/AccountHeader.d.ts +0 -1
  6. package/dist/components/AccountDisplay/parts/AccountIdleBalances.d.ts +4 -6
  7. package/dist/components/AccountDisplay/parts/AccountPanel.d.ts +4 -4
  8. package/dist/components/AccountDisplay/types.d.ts +18 -3
  9. package/dist/components/SpiceDeposit/lib/escrowCredit.d.ts +2 -0
  10. package/dist/components/SpiceLock/lib/helpers.d.ts +1 -0
  11. package/dist/components/SpiceSupply/lib/actionProceeds.d.ts +9 -2
  12. package/dist/components/SpiceSupply/lib/buildBatches.d.ts +22 -12
  13. package/dist/components/SpiceSupply/lib/executors.d.ts +12 -19
  14. package/dist/components/SpiceSupply/lib/feeConversion.d.ts +15 -2
  15. package/dist/components/SpiceSupply/lib/feeFunding.d.ts +21 -0
  16. package/dist/components/SpiceSupply/lib/feeOnlyExecution.d.ts +1 -1
  17. package/dist/components/SpiceSupply/lib/feePreview.d.ts +56 -16
  18. package/dist/components/SpiceSupply/lib/payFundingBatches.d.ts +2 -1
  19. package/dist/components/SpiceWithdraw/lib/helpers.d.ts +1 -1
  20. package/dist/components/SpiceWithdraw/lib/useEmbeddedWithdraw.d.ts +152 -0
  21. package/dist/components/SpiceWithdraw/parts/WithdrawBalanceCardHeader.d.ts +2 -3
  22. package/dist/components/SpiceWithdraw/parts/WithdrawDestinationCard.d.ts +4 -2
  23. package/dist/components/SpiceWithdraw/parts/WithdrawDetailsPanel.d.ts +4 -2
  24. package/dist/components/SpiceWithdraw/parts/WithdrawSourceCard.d.ts +4 -2
  25. package/dist/components/StatusDisplay/parts/StatusPanel.d.ts +2 -2
  26. package/dist/execution/directExecution.d.ts +11 -0
  27. package/dist/execution/escrowCredit.d.ts +18 -0
  28. package/dist/execution/externalWalletClient.d.ts +5 -0
  29. package/dist/execution/fundEmbeddedWallet.d.ts +9 -1
  30. package/dist/execution/intentSigning.d.ts +3 -2
  31. package/dist/execution/pollIntentStep.d.ts +8 -10
  32. package/dist/execution/sourceFunding.d.ts +11 -28
  33. package/dist/execution/transactionReceipt.d.ts +1 -0
  34. package/dist/hooks/index.d.ts +9 -8
  35. package/dist/hooks/useDestinationToken.d.ts +20 -0
  36. package/dist/hooks/useInventoryResource.d.ts +21 -0
  37. package/dist/hooks/useIsUserWhitelisted.d.ts +12 -12
  38. package/dist/hooks/useLockWalletAssets.d.ts +1 -1
  39. package/dist/hooks/useSpiceAction.d.ts +46 -0
  40. package/dist/hooks/useSpiceAssets.d.ts +4 -1
  41. package/dist/hooks/useSpiceExecution.d.ts +6 -6
  42. package/dist/hooks/useSpiceInventory.d.ts +31 -0
  43. package/dist/hooks/useSpiceLock.d.ts +115 -0
  44. package/dist/hooks/useSpiceLockQuote.d.ts +35 -3
  45. package/dist/hooks/useSpiceRollupPrices.d.ts +9 -0
  46. package/dist/hooks/useSpiceSupply.d.ts +63 -27
  47. package/dist/hooks/useSupplyAssets.d.ts +23 -18
  48. package/dist/hooks/useSupplyQuote.d.ts +20 -5
  49. package/dist/hooks/useTokenLogo.d.ts +1 -0
  50. package/dist/hooks/useWallet.d.ts +3 -2
  51. package/dist/hooks/useWalletBalances.d.ts +10 -4
  52. package/dist/index.cjs.js +16 -29
  53. package/dist/index.d.ts +53 -47
  54. package/dist/index.js +16 -29
  55. package/dist/privy-DgLAdE7U.js +2 -0
  56. package/dist/privy-TGSRGTFo.js +2 -0
  57. package/dist/providers/SpiceFlowProvider.d.ts +5 -3
  58. package/dist/types/assets.d.ts +14 -4
  59. package/dist/types/lock.d.ts +7 -3
  60. package/dist/types/supply.d.ts +44 -4
  61. package/dist/types/withdraw.d.ts +9 -3
  62. package/dist/utils/actionDefinition.d.ts +2 -0
  63. package/dist/utils/amounts.d.ts +2 -0
  64. package/dist/utils/assetDisplay.d.ts +8 -0
  65. package/dist/utils/assetPolicy.d.ts +16 -0
  66. package/dist/utils/chains/index.d.ts +4 -4
  67. package/dist/utils/crossChainRouter/liquidityVenues.d.ts +9 -10
  68. package/dist/utils/crossChainRouter/nativeWrap.d.ts +2 -2
  69. package/dist/utils/crossChainRouter/uniV3.d.ts +9 -5
  70. package/dist/utils/crossChainRouter/uniV4.d.ts +2 -0
  71. package/dist/utils/directWithdraw.d.ts +0 -4
  72. package/dist/utils/fees.d.ts +6 -1
  73. package/dist/utils/inventoryStore.d.ts +27 -0
  74. package/dist/utils/prices/providerPrices.d.ts +12 -0
  75. package/dist/utils/relayer/index.d.ts +4 -2
  76. package/dist/utils/rollupBalances.d.ts +4 -0
  77. package/dist/utils/swapQuotes.d.ts +0 -1
  78. package/dist/utils/theme.d.ts +3 -3
  79. package/dist/utils/tokenLogos.d.ts +2 -0
  80. package/dist/utils/tokenResolution.d.ts +27 -3
  81. package/package.json +7 -2
  82. package/dist/components/SpiceLock/lib/executors.d.ts +0 -76
  83. package/dist/components/SpiceSupply/lib/controlledFunding.d.ts +0 -55
  84. package/dist/components/SpiceSupply/lib/externalAction.d.ts +0 -63
  85. package/dist/components/SpiceSupply/lib/sourceConversion.d.ts +0 -12
  86. package/dist/components/SpiceWithdraw/parts/WithdrawBalancePopover.d.ts +0 -15
  87. package/dist/hooks/useDirectWithdraw.d.ts +0 -12
  88. package/dist/hooks/useSourceFundingConversion.d.ts +0 -22
  89. package/dist/privy-C4NTw6Dl.js +0 -2
  90. package/dist/privy-XbtFily9.js +0 -2
  91. package/dist/utils/crossChainRouter/algebra.d.ts +0 -83
  92. package/dist/utils/crossChainRouter/sourceFundingQuote.d.ts +0 -58
package/README.md CHANGED
@@ -2,39 +2,75 @@
2
2
 
3
3
  A React component library for building DeFi swap interfaces with multi-chain support.
4
4
 
5
- ## Installation
5
+ ## Version and migration
6
+
7
+ The shared inventory/action refactor merged in PR #103. As checked September 14, 2026,
8
+ `4.9.6-consistency.16` is published under `consistency`; npm `latest` remains `4.9.5`.
9
+ Check the actual registry tag and client pin before adopting it. See
10
+ [CONSISTENCY-MIGRATION.md](CONSISTENCY-MIGRATION.md) for migration breaks and candidate-specific evidence.
11
+ A merged source change does not publish npm or upgrade consuming apps.
12
+
13
+ The unified action controller in this source restores direct external execution for a wallet asset matching the destination token and chain. Clients keep one action definition across direct and routed execution. See [the migration guide](CONSISTENCY-MIGRATION.md#unreleased-direct-external-execution-in-the-unified-controller) for scope, gas, recovery and the unpublished release status.
14
+
15
+ ## Installation and provider setup
16
+
17
+ Select an approved exact version, preserving the app's dependency-age and security policies:
6
18
 
7
19
  ```bash
8
- npm install @spicenet-io/spiceflow-ui
20
+ bun add --exact @spicenet-io/spiceflow-ui@4.9.6-consistency.16
9
21
  ```
10
22
 
11
- ## Usage
23
+ The example is a prerelease selection, not a stable recommendation or a policy bypass.
24
+ Reuse compatible host-owned Privy, wagmi and QueryClient providers. Read the exact
25
+ package's peer dependencies; do not replace the wallet stack as part of a version bump.
12
26
 
13
27
  ```tsx
14
- import { SwapWidget, SpiceFlowProvider } from "@spicenet-io/spiceflow-ui";
28
+ import { SpiceFlowProvider } from "@spicenet-io/spiceflow-ui";
15
29
  import "@spicenet-io/spiceflow-ui/styles.css";
16
30
 
17
- function App() {
18
- return (
19
- <SpiceFlowProvider
20
- provider="privy"
21
- privyAppId="your-privy-app-id"
22
- dynamicEnvironmentId="your-env-id"
23
- paraApiKey="your-para-api-key"
24
- paraAppName="your-app-name"
25
- >
26
- <SwapWidget
27
- swapBatches={swapBatches}
28
- supportedChains={[1, 137, 42161]}
29
- showSlippageSettings={true}
30
- enableFlipSwap={true}
31
- theme="dark"
32
- />
33
- </SpiceFlowProvider>
34
- );
35
- }
31
+ // Inside the host's existing WagmiProvider → QueryClientProvider → PrivyProvider stack.
32
+ <SpiceFlowProvider
33
+ provider="privy"
34
+ network="mainnet"
35
+ nativeChainId={8453}
36
+ rpcOverrides={clientRpcUrls}
37
+ >
38
+ {children}
39
+ </SpiceFlowProvider>;
36
40
  ```
37
41
 
42
+ Configure Privy credentials/policy on the host's `PrivyProvider`. Supply client RPCs
43
+ for every enabled source, conversion and destination chain, and keep the SDK/wallet
44
+ chain sets aligned. Wallet-library transports alone do not configure SDK reads;
45
+ there is no internal RPC fallback. Keep private credentials out of browser bundles.
46
+
47
+ ## Integration ownership
48
+
49
+ - Use stock components when they fit the approved UI; use `useSpiceSupply` for custom
50
+ action forms. `useSpiceLock` and legacy `useSpiceAction` delegate to that controller.
51
+ - Supply destination metadata, protocol `buildActionCalls` or destination-only
52
+ `lockBatches`, beneficiary semantics, and awaited application updates. The SDK owns
53
+ inventory, routing, Max, fees, accepted plans, funding, execution and recovery.
54
+ - For custom holdings, use `useSpiceInventory` and `assetPositionId`. Keep raw balance,
55
+ default visibility and spend eligibility separate. Preserve rows during refresh;
56
+ stale/failed balances cannot authorize spending, and confirmed zero wins.
57
+ - In this unreleased source, eligible External-mode actions with a matching wallet token
58
+ and destination chain execute directly from the external signer, without embedded funding.
59
+ Other assets/chains still use embedded funding and the shared routed executor.
60
+ `onPayExecute` and `onLockExecute` remain blocked; the deprecated external-caller hint
61
+ supports only the direct case. Verify contract caller/beneficiary and NFT receiver behavior.
62
+ Published `.16` does not contain this restoration.
63
+ - Supply `input` adds fees to principal; `input-inclusive` uses a total budget; Pay
64
+ `output` fixes the destination amount. Use controller readiness/Max/status instead of
65
+ constructing an executor context or duplicating fee arithmetic in the host.
66
+ - Use controller recovery for uncertain funding and `retryFinalization()` for failed
67
+ application updates after settlement. Preserve original host terms across reload.
68
+ - Deposit and rollup Withdraw retain distinct execution semantics while sharing
69
+ inventory/policy. Account wallet withdrawal uses the fee-only Supply path.
70
+
71
+ Inventory isolation does not establish support for simultaneous differently configured
72
+ providers: underlying quote/execution transports still have global state.
73
+
38
74
  ## Liquidity venues
39
75
 
40
76
  When a flow has to swap on the destination chain, the SDK quotes every liquidity
@@ -108,12 +144,93 @@ it becomes a `protocol` everyone can name.
108
144
 
109
145
  ## Development
110
146
 
111
- ### Fee-Charging Intent Flows
147
+ ### Rollup balance pricing
148
+
149
+ Rollup USD values use the host-configured RPC provider's pricing capability when the balance API has no valid value. The built-in account panel and withdrawal modal enable this while open; custom `useSpiceAssets` consumers can opt in with `priceEnabled`. Quantities arrive independently. Lookups follow receipt mappings, prefer `nativeChainId`, and fall back to other supported chains with a configured Alchemy endpoint. Explicit account `tokenPrices` overrides still take precedence over provider quotes.
150
+
151
+ Wallet discovery and rollup balances share a one-minute quote cache. Pricing polls only while the view is open and the page is visible. A failed refresh can retain a marked stale quote for up to five minutes; an unavailable quote displays `—`. No extra key, internal RPC, or symbol-based ERC-20 price fallback is used.
152
+
153
+ ### Host-supplied token logos
154
+
155
+ `AccountDisplay.tokenLogos` maps a token symbol to a logo URL, the same key
156
+ shape `tokenPrices` uses. A discovered embedded-wallet balance falls back to
157
+ it when the RPC provider returns no logo, which is what happens for a token
158
+ that is not in the chain's configured token list. Provider metadata still
159
+ wins when it has a logo.
160
+
161
+ ```tsx
162
+ <AccountDisplay tokenLogos={{ TOKEN: tokenLogoUrl }} />
163
+ ```
164
+
165
+ ### Withdraw from an account balance
166
+
167
+ `AccountDisplay.onWithdrawClick` receives the rollup receipt-token ID when a
168
+ user clicks Withdraw on an idle rollup balance. The main Withdraw button calls
169
+ it without an ID. Pass the ID to `SpiceWithdraw.initialSourceAssetId` to open
170
+ the existing modal with that asset selected; the user chooses the destination
171
+ network inside the modal. Existing callbacks that take no arguments continue
172
+ to work.
173
+
174
+ ```tsx
175
+ const [withdrawOpen, setWithdrawOpen] = useState(false);
176
+ const [withdrawAssetId, setWithdrawAssetId] = useState<string>();
177
+
178
+ <AccountDisplay
179
+ onWithdrawClick={(receiptTokenId) => {
180
+ setWithdrawAssetId(receiptTokenId);
181
+ setWithdrawOpen(true);
182
+ }}
183
+ />
184
+ <SpiceWithdraw
185
+ isOpen={withdrawOpen}
186
+ onClose={() => setWithdrawOpen(false)}
187
+ initialSourceAssetId={withdrawAssetId}
188
+ buildSpicenetBatch={buildSpicenetWithdrawalBatch}
189
+ />
190
+ ```
191
+
192
+ Keep the integration's existing withdrawal batch builder and callbacks.
193
+ `initialSourceAssetId` selects a current balance by ID; it does not supply a
194
+ cached balance or change the receipt's supported withdrawal routes.
195
+
196
+ ### Action Fee Readiness
197
+
198
+ - Routed Supply, Pay and Lock actions must surface fee estimation before enabling submission.
199
+ - Eligible direct external actions still require an accepted plan but charge no Spicenet fee. Network gas remains payable in the external wallet; native Max reserves gas.
200
+ - Deposit gas and rollup withdrawal semantics remain distinct from action intent fees. Preserve their existing quote/readiness requirements.
201
+ - Account wallet withdrawal is a fee-only Supply action. Do not bypass its fee/readiness gates based on the label "withdraw".
202
+ - Custom actions use the shared controller's `canExecute`; an available balance or old quote alone is insufficient.
203
+
204
+ ### Fee funding for fee-only actions
205
+
206
+ - A fee-only action (`feeOnlyAction`) runs on what the executing wallet already holds; the SDK funds only the Spicenet fees, in the chain's fee token (`destinationToken`).
207
+ - With no `selectedAsset`, the SDK picks the fee source and the user is never asked. The action's input (`actionInput`) comes first, then its proceeds (`actionProceeds`), so the fee stays inside the action the user submitted; then other balances: same-chain embedded wallet before rollup, and within each, balances already in the fee token before balances that swap into it. The first source that simulates and covers the fee wins and is reported as `fees.fundingSource`; a source whose swap has no route, or that cannot cover the fee within slippage, is skipped for the next.
208
+ - Declare `actionInput` for every token the action consumes and honour the amount passed to `buildActionCalls`: when fees come from an input, the action is built for the remainder. Declare `actionProceeds` for a token the action leaves in the wallet. Both are optional; with neither, only balances can pay. Omit `actionProceeds` when the output is delivered to another owner.
209
+ - `feeFunding` overrides the level order per transaction, for example `["proceeds", "input", "balance"]`; the order inside the balance level is fixed. An empty list leaves the choice to the host's `selectedAsset`.
210
+ - A `selectedAsset` on a fee-only action is an explicit host choice and funds the fee from that balance as before.
211
+
212
+ ### Updating and releasing
213
+
214
+ Change the shared inventory/policy/controller owner and audit affected stock and custom
215
+ consumers. Use the central team's `workflow`, `ui-quality` and `shared/sdk.md` guidance;
216
+ keep skills in the skills repo rather than copying them here.
217
+
218
+ Read the central `shared/client-design-decisions.md` register before an upgrade. Map
219
+ applicable decision IDs to affected consumers and regression scenarios, and report each
220
+ result with exact candidate evidence. Preserve agreed behavior and ownership even when
221
+ types compile; a deliberate change needs an explicit product decision and migration plan.
222
+
223
+ Run focused regressions, `bun test`, `bun run typecheck` and `bun run build`, then validate
224
+ affected consumer builds and rendered/financial behavior on the exact candidate. Record
225
+ package identity, configuration, acceptance coverage and untested cases. Earlier candidate
226
+ results do not automatically apply to newer main or a new client.
112
227
 
113
- - `SpiceSupply` and `SpicePay` are fee-charging intent-execution flows and must surface fee estimation before enabling submission.
114
- - `SpiceLockModal` is also a fee-charging intent-execution flow and must surface fee estimation before enabling submission.
115
- - `SpiceDeposit` and `SpiceWithdraw` are treated as non-fee actions and should not use the fee-estimation gating UX.
116
- - Rule of thumb: every intent-execution flow other than deposit/withdraw should assume fees apply and should gate CTA enablement on successful fee estimation.
228
+ If core/API changes are needed, resolve those dependencies before their UI/app consumers.
229
+ An inventory/controller-only change does not inherently require a core release. After
230
+ explicit release authorization, publish a prerelease with a non-`latest` tag, verify its
231
+ registry artifact, and pin/test that exact version in each adopting app. Stable promotion,
232
+ client deployment and docs targeting are separate release decisions. This refactor adds
233
+ no automatic npm publishing.
117
234
 
118
235
  ### Building the Library
119
236
 
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- "use strict";const r=require("./privy-XbtFily9.js");require("react/jsx-runtime"),require("react"),require("@spicenet-io/spiceflow-core"),require("viem"),require("viem/actions"),require("@privy-io/react-auth"),require("wagmi"),require("@tanstack/react-query"),exports.PrivyLogin=r.PrivyLogin;
2
+ "use strict";const r=require("./privy-DgLAdE7U.js");require("react/jsx-runtime"),require("react"),require("@spicenet-io/spiceflow-core"),require("@tanstack/react-query"),require("viem"),require("@privy-io/react-auth"),require("wagmi"),require("viem/actions"),exports.PrivyLogin=r.PrivyLogin;
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{P as g}from"./privy-C4NTw6Dl.js";import"react/jsx-runtime";import"react";import"@spicenet-io/spiceflow-core";import"viem";import"viem/actions";import"@privy-io/react-auth";import"wagmi";import"@tanstack/react-query";export{g as PrivyLogin};
2
+ import{P as g}from"./privy-TGSRGTFo.js";import"react/jsx-runtime";import"react";import"@spicenet-io/spiceflow-core";import"@tanstack/react-query";import"viem";import"@privy-io/react-auth";import"wagmi";import"viem/actions";export{g as PrivyLogin};
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
- import { CustomSection } from "../types";
3
2
  import type { ResolvedDarkPalette } from "../../../utils/theme";
3
+ import { CustomSection } from "../types";
4
4
  interface AccountCustomSectionProps {
5
5
  section: CustomSection;
6
6
  dk: ResolvedDarkPalette;
@@ -5,7 +5,6 @@ interface AccountHeaderProps {
5
5
  status: "active" | "inactive";
6
6
  statusLabel?: string;
7
7
  totalUsdValue: number;
8
- hasUnpricedAssets?: boolean;
9
8
  breakdownSubtitle: string;
10
9
  showUsdSummary?: boolean;
11
10
  address?: string;
@@ -1,11 +1,7 @@
1
1
  import React from "react";
2
- import { SpiceAsset } from "../types";
3
2
  import type { ResolvedDarkPalette } from "../../../utils/theme";
4
- export interface DirectWithdrawState {
5
- key: string;
6
- step: "pending" | "error";
7
- message?: string;
8
- }
3
+ import type { DirectWithdrawState } from "../types";
4
+ import { SpiceAsset } from "../types";
9
5
  interface AccountIdleBalancesProps {
10
6
  spiceAssets: SpiceAsset[];
11
7
  loading: boolean;
@@ -14,6 +10,8 @@ interface AccountIdleBalancesProps {
14
10
  canDirectWithdraw?: boolean;
15
11
  onDirectWithdraw?: (asset: SpiceAsset) => void;
16
12
  directWithdrawState?: DirectWithdrawState | null;
13
+ onWithdrawClick?: (receiptTokenId?: string) => void;
14
+ limit?: number;
17
15
  }
18
16
  export declare const AccountIdleBalances: React.NamedExoticComponent<AccountIdleBalancesProps>;
19
17
  export {};
@@ -1,14 +1,13 @@
1
1
  import React from "react";
2
- import { SpiceAsset, CustomSection, AccountNotice } from "../types";
3
2
  import { VerifiedPendingDeposit } from "../../../hooks/usePendingDeposit";
4
3
  import type { ResolvedDarkPalette } from "../../../utils/theme";
5
- import { type DirectWithdrawState } from "./AccountIdleBalances";
4
+ import type { DirectWithdrawState } from "../types";
5
+ import { AccountNotice, CustomSection, SpiceAsset } from "../types";
6
6
  interface AccountPanelProps {
7
7
  appName: string;
8
8
  status: "active" | "inactive";
9
9
  statusLabel?: string;
10
10
  totalUsdValue: number;
11
- hasUnpricedAssets?: boolean;
12
11
  breakdownSubtitle: string;
13
12
  showUsdSummary?: boolean;
14
13
  address?: string;
@@ -18,7 +17,7 @@ interface AccountPanelProps {
18
17
  customSections: CustomSection[];
19
18
  notice?: AccountNotice | null;
20
19
  onDepositClick?: () => void;
21
- onWithdrawClick?: () => void;
20
+ onWithdrawClick?: (receiptTokenId?: string) => void;
22
21
  depositDisabled?: boolean;
23
22
  onCompleteDeposit?: (deposit: VerifiedPendingDeposit) => void;
24
23
  primaryColor?: string;
@@ -34,6 +33,7 @@ interface AccountPanelProps {
34
33
  canDirectWithdraw?: boolean;
35
34
  onDirectWithdraw?: (asset: SpiceAsset) => void;
36
35
  directWithdrawState?: DirectWithdrawState | null;
36
+ idleBalancesLimit?: number;
37
37
  }
38
38
  export declare const AccountPanel: React.NamedExoticComponent<AccountPanelProps>;
39
39
  export {};
@@ -1,12 +1,13 @@
1
- import type { CustomStyles } from "../../types/theme";
2
- import { VerifiedPendingDeposit } from "../../hooks/usePendingDeposit";
3
1
  import type React from "react";
2
+ import { VerifiedPendingDeposit } from "../../hooks/usePendingDeposit";
3
+ import type { CustomStyles } from "../../types/theme";
4
4
  export interface CustomSectionItem {
5
5
  tokenSymbol: string;
6
6
  tokenLogoURI?: string;
7
7
  label: React.ReactNode;
8
8
  displayValue: string;
9
9
  valueColor?: "green" | "red" | "default";
10
+ onClick?: () => void;
10
11
  }
11
12
  export interface CustomSection {
12
13
  title: string;
@@ -14,6 +15,9 @@ export interface CustomSection {
14
15
  totalValue?: number;
15
16
  }
16
17
  export interface SpiceAsset {
18
+ owner?: string;
19
+ location?: "external" | "embedded" | "rollup";
20
+ positionId?: string;
17
21
  tokenAddress: string;
18
22
  tokenSymbol: string;
19
23
  tokenDisplaySymbol?: string;
@@ -24,7 +28,9 @@ export interface SpiceAsset {
24
28
  balance: string;
25
29
  balanceFormatted: number;
26
30
  usdValue: number;
31
+ priceStatus?: "fresh" | "stale" | "unavailable";
27
32
  logoURI?: string;
33
+ receiptTokenId?: string;
28
34
  directWithdraw?: boolean;
29
35
  }
30
36
  export interface BreakdownLabel {
@@ -42,15 +48,24 @@ export interface AccountDisplayProps {
42
48
  customSections?: CustomSection[];
43
49
  extraAssets?: SpiceAsset[];
44
50
  tokenPrices?: Record<string, number>;
51
+ tokenLogos?: Record<string, string>;
45
52
  breakdownLabels?: BreakdownLabel[];
46
53
  notice?: AccountNotice | null;
47
54
  styles?: CustomStyles;
48
55
  dark?: boolean;
49
56
  onDepositSuccess?: () => void;
50
57
  onDepositClick?: () => void;
51
- onWithdrawClick?: () => void;
58
+ onWithdrawClick?: (receiptTokenId?: string) => void;
52
59
  onCompleteDeposit?: (deposit: VerifiedPendingDeposit) => void;
53
60
  showModeToggle?: boolean;
54
61
  defaultMode?: "7702" | "non7702";
55
62
  showUsdSummary?: boolean;
63
+ alwaysShowEmbeddedIdle?: boolean;
64
+ idleBalancesLimit?: number;
65
+ showDisconnect?: boolean;
66
+ }
67
+ export interface DirectWithdrawState {
68
+ key: string;
69
+ step: "pending" | "error";
70
+ message?: string;
56
71
  }
@@ -0,0 +1,2 @@
1
+ import type { Asset } from "../../../types/assets";
2
+ export declare function isEscrowCreditable(asset: Pick<Asset, "address" | "chainId" | "isNative">): boolean;
@@ -3,6 +3,7 @@ import { type FeeEstimateSummary, type ResolvedSwap } from "@spicenet-io/spicefl
3
3
  import type { ChainAuthorization, ChainBatch } from "../../../types/authorization";
4
4
  import type { Asset } from "../../../types/assets";
5
5
  export declare function isDirectLockSource(asset: Asset, lockChainId: number): boolean;
6
+ export declare function isInPlaceLockSource(asset: Asset, lockChainId: number): boolean;
6
7
  export declare function composeLockSwapBatches(batches: ChainBatch[], params: {
7
8
  chainId: number;
8
9
  recipient: Address;
@@ -1,7 +1,12 @@
1
1
  import { type Address } from "viem";
2
2
  import type { ChainBatch } from "../../../types/authorization";
3
- import type { SpiceSupplyProps } from "../../../types/supply";
3
+ import type { SpiceSupplyProps, SupplyBatchBuildOptions } from "../../../types/supply";
4
4
  import type { SupplyFeeQuote } from "./feePreview";
5
+ export declare class InsufficientFeeFundingBalanceError extends Error {
6
+ readonly requiredAmount: bigint;
7
+ readonly balance: bigint;
8
+ constructor(requiredAmount: bigint, balance: bigint);
9
+ }
5
10
  export declare function appendProceedsFees(batches: ChainBatch[], owner: Address, token: Address, gas: bigint, platform: bigint): ChainBatch[];
6
11
  export declare function simulateProceedsBatch(batches: ChainBatch[], owner: Address, token: Address, signal?: AbortSignal, platformFeeMaximum?: bigint): Promise<bigint>;
7
12
  export declare function estimateProceedsFunding(args: {
@@ -10,5 +15,7 @@ export declare function estimateProceedsFunding(args: {
10
15
  token: Address;
11
16
  signal?: AbortSignal;
12
17
  baseline: () => Promise<SupplyFeeQuote | null>;
13
- buildBatches: (amount: bigint) => Promise<ChainBatch[]>;
18
+ buildBatches: (amount: bigint, options?: SupplyBatchBuildOptions) => Promise<ChainBatch[]>;
19
+ fundShortfall?: boolean;
20
+ actionAmountFor?: (fee: bigint) => bigint;
14
21
  }): Promise<SupplyFeeQuote>;
@@ -1,29 +1,27 @@
1
+ import type { FeeEstimateSummary, ResolvedSwap } from "@spicenet-io/spiceflow-core";
1
2
  import { type Address } from "viem";
2
- import type { ResolvedSwap } from "@spicenet-io/spiceflow-core";
3
- import type { ChainBatch } from "../../../types/authorization";
3
+ import type { ExecutionOptions } from "../../../hooks/useSpiceExecution";
4
4
  import type { SelectedAsset } from "../../../types/assets";
5
- import type { SpiceSupplyProps, SupplyBatchBuildOptions } from "../../../types/supply";
5
+ import type { ChainBatch } from "../../../types/authorization";
6
+ import type { PivotRoute, SpiceSupplyProps, SupplyBatchBuildOptions } from "../../../types/supply";
6
7
  import type { ResolvedExactOutputSwap } from "../../../utils/swapQuotes";
7
- import type { ExecutionOptions } from "../../../hooks/useSpiceExecution";
8
- import type { FeeEstimateSummary } from "@spicenet-io/spiceflow-core";
9
8
  type EstimateFn = (chainBatches: ChainBatch[], tokenAddress: string, tokenTransferAmount: bigint, options?: ExecutionOptions) => Promise<FeeEstimateSummary>;
10
- export declare function buildEmbeddedEscrowDepositBatch(token: Address, amount: bigint, chainId: number): ChainBatch;
11
- export declare function isExternalSource(asset: SelectedAsset["asset"] | null | undefined, isNon7702: boolean): boolean;
9
+ export declare function getPivotEscrowAmount(sourceSwap: Pick<ResolvedSwap, "amountOutMinimum">, gasSkim: bigint): bigint;
12
10
  export declare function stripSpicenetFundingBatches(batches: ChainBatch[]): ChainBatch[];
13
11
  export declare function scaleTokenAmount(amount: bigint, fromDecimals: number, toDecimals: number): bigint;
14
- export declare function resolveSupplyTokenDecimals(asset: SelectedAsset["asset"], destination: SpiceSupplyProps["destinationToken"], token: Address): Promise<number>;
15
12
  export interface BatchBuilderContext {
16
13
  currentPaymentAmount: string;
14
+ isFeeInclusiveInput?: boolean;
15
+ feeOnlyAction?: boolean;
16
+ swapInputAmount?: bigint | null;
17
17
  destinationToken: SpiceSupplyProps["destinationToken"];
18
18
  embeddedWalletAddress: string | null | undefined;
19
19
  providerEmbeddedAddress: string | null | undefined;
20
20
  externalWalletAddress: string | null | undefined;
21
21
  address: string | null | undefined;
22
22
  recipient?: Address;
23
- swapOutputRecipient?: Address;
24
23
  isNon7702: boolean;
25
24
  isPayMode: boolean;
26
- feeOnlyAction?: boolean;
27
25
  resolvedChainId: number;
28
26
  buildActionCalls: SpiceSupplyProps["buildActionCalls"];
29
27
  feeExecutionMode: SpiceSupplyProps["feeExecutionMode"];
@@ -31,12 +29,24 @@ export interface BatchBuilderContext {
31
29
  selectedAsset: SelectedAsset | null;
32
30
  needsSwap: boolean;
33
31
  resolvedSwap: ResolvedSwap | null;
32
+ resolveInputSwap?: (amountIn: bigint, selectedSwap?: ResolvedSwap) => Promise<ResolvedSwap>;
34
33
  exactOutputSwap: ResolvedExactOutputSwap | null;
35
34
  quoteAmountOut: bigint | null;
36
35
  resolvedTokenIn: Address | null;
36
+ sourceSwap?: ResolvedSwap | null;
37
+ sourceExactOutputSwap?: ResolvedExactOutputSwap | null;
38
+ resolveSourceExactOutputSwap?: (amountOut: bigint) => Promise<ResolvedExactOutputSwap>;
39
+ pivot?: PivotRoute | null;
37
40
  requestTimestampMs?: number;
38
41
  }
39
- export declare function buildPayChainBatches(ctx: BatchBuilderContext, options?: SupplyBatchBuildOptions): Promise<ChainBatch[]>;
40
- export declare function buildSupplyChainBatches(ctx: BatchBuilderContext, options?: SupplyBatchBuildOptions): Promise<ChainBatch[]>;
42
+ export declare function isPivotPay(ctx: Pick<BatchBuilderContext, "isPayMode" | "selectedAsset" | "resolvedChainId" | "pivot">): ctx is typeof ctx & {
43
+ pivot: PivotRoute;
44
+ };
45
+ export declare function isPivotSupply(ctx: Pick<BatchBuilderContext, "isPayMode" | "selectedAsset" | "resolvedChainId" | "sourceSwap" | "pivot">): ctx is typeof ctx & {
46
+ sourceSwap: ResolvedSwap;
47
+ pivot: PivotRoute;
48
+ };
49
+ export declare const buildPayChainBatches: (ctx: BatchBuilderContext, options?: SupplyBatchBuildOptions) => Promise<ChainBatch[]>;
50
+ export declare const buildSupplyChainBatches: (ctx: BatchBuilderContext, options?: SupplyBatchBuildOptions) => Promise<ChainBatch[]>;
41
51
  export declare function estimateRequiredGrossFunding(requiredNetFunding: bigint, buildBatches: (grossFundingAmount: bigint) => ChainBatch[] | Promise<ChainBatch[]>, fundingToken: Address, estimate: EstimateFn, executionOptions?: Pick<ExecutionOptions, "useCustomTransfers" | "userOverride">): Promise<bigint>;
42
52
  export {};
@@ -1,23 +1,19 @@
1
- import { type SourceConversionExecution } from "./sourceConversion";
1
+ import type { ResolvedSwap } from "@spicenet-io/spiceflow-core";
2
2
  import type { Dispatch, MutableRefObject, SetStateAction } from "react";
3
3
  import { type Address } from "viem";
4
- import { type TransactionObserver } from "../../../execution/externalWalletClient";
5
- import { type SourceFundingState } from "../../../execution/sourceFunding";
4
+ import type { ExecutionRunner } from "../../../execution/runner";
5
+ import type { ExecutionProgress } from "../../../hooks/useSpiceExecution";
6
6
  import type { SelectedAsset } from "../../../types/assets";
7
- import type { BuildPayBatchesFn, BuildSupplyBatchesFn, SpiceSupplyProps } from "../../../types/supply";
8
- import { type SupplyFeeQuote } from "./feePreview";
7
+ import type { BuildPayBatchesFn, BuildSupplyBatchesFn, PivotRoute, SpiceSupplyProps } from "../../../types/supply";
9
8
  import type { ResolvedExactOutputSwap } from "../../../utils/swapQuotes";
10
- import type { ExecutionProgress } from "../../../hooks/useSpiceExecution";
11
- import type { ExecutionRunner } from "../../../execution/runner";
12
- export type SupplyStep = "idle" | "signing-delegation" | "signing-intent" | "submitting" | "executing" | "success" | "error";
9
+ import { type SupplyFeeQuote } from "./feePreview";
10
+ export type SupplyStep = "idle" | "building" | "signing-delegation" | "signing-intent" | "submitting" | "executing" | "success" | "error";
13
11
  export type PaymentResult = {
14
12
  status: "processing" | "success" | "failed";
15
13
  txHash?: string;
16
14
  error?: string;
17
15
  };
18
- export { isExternalSource } from "./buildBatches";
19
16
  export type ExecutorContext = {
20
- signal?: AbortSignal;
21
17
  selectedAsset: SelectedAsset | null;
22
18
  parsedAmount: number;
23
19
  currentPaymentAmount: string;
@@ -27,12 +23,18 @@ export type ExecutorContext = {
27
23
  feeOnlyAction?: boolean;
28
24
  actionProceeds?: SpiceSupplyProps["actionProceeds"];
29
25
  validateFeeQuote?: () => void;
26
+ executionTokenDecimals?: number;
27
+ signal?: AbortSignal;
30
28
  isNon7702: boolean;
29
+ directExternalAction?: boolean;
31
30
  isSourceDestToken: boolean;
32
31
  needsSwap: boolean;
33
32
  exactOutputSwap: ResolvedExactOutputSwap | null;
34
33
  selectedIsEquivalent: boolean;
35
34
  resolvedTokenIn: Address | null;
35
+ sourceSwap: ResolvedSwap | null;
36
+ sourceExactOutputSwap: ResolvedExactOutputSwap | null;
37
+ pivot: PivotRoute | null;
36
38
  embeddedWalletAddress: string | null | undefined;
37
39
  providerEmbeddedAddress: string | null | undefined;
38
40
  recipient?: Address;
@@ -51,14 +53,7 @@ export type ExecutorContext = {
51
53
  provider: string | null | undefined;
52
54
  resolvedChainId: number;
53
55
  executionTokenAddress: Address;
54
- executionTokenDecimals?: number;
55
56
  feeQuote: SupplyFeeQuote | null;
56
- fundingObserver?: TransactionObserver;
57
- sourceFunding?: SourceFundingState;
58
- sourceFundingRecoveryKey?: string;
59
- sourceConversion?: SourceConversionExecution;
60
- sourceConversionRequired?: boolean;
61
- onSourceFundingChange?: (state: SourceFundingState) => void;
62
57
  execution: ExecutionRunner & {
63
58
  buildPayChainBatches: BuildPayBatchesFn;
64
59
  buildSupplyChainBatches: BuildSupplyBatchesFn;
@@ -78,7 +73,5 @@ export type ExecutorContext = {
78
73
  abortControllerRef: MutableRefObject<AbortController | null>;
79
74
  };
80
75
  } & Pick<SpiceSupplyProps, "destinationToken" | "buildActionCalls" | "feeExecutionMode" | "buildSpicenetBatch" | "onPayExecute" | "onSuccess">;
81
- export declare function sourceFundingSelection(ctx: ExecutorContext): SelectedAsset | null;
82
- export declare function sourceFundingIdentity(ctx: ExecutorContext): string;
83
76
  export declare function executeSupply(ctx: ExecutorContext): Promise<void>;
84
77
  export declare function executePay(ctx: ExecutorContext): Promise<void>;
@@ -1,4 +1,6 @@
1
- import type { Address } from "viem";
1
+ import { type Address } from "viem";
2
+ import type { ChainBatch } from "../../../types/authorization";
3
+ export { InsufficientFeeFundingBalanceError } from "./actionProceeds";
2
4
  import type { FeePreviewContext, SupplyFeeQuote } from "./feePreview";
3
5
  export declare function resolveFeeFundingToken(asset: NonNullable<FeePreviewContext["selectedAsset"]>["asset"], chainId: number, feeToken: Address): Address | null;
4
6
  export interface FundingConversion {
@@ -7,5 +9,16 @@ export interface FundingConversion {
7
9
  amountInMax: bigint;
8
10
  amountOut: bigint;
9
11
  sourceAmountMax: bigint;
12
+ fromProceeds?: boolean;
13
+ fromInput?: boolean;
10
14
  }
11
- export declare function quoteConvertedFees(ctx: FeePreviewContext): Promise<SupplyFeeQuote>;
15
+ export declare function simulateInPlaceFees(ctx: FeePreviewContext, owner: Address, tokenOut: Address, batches: ChainBatch[]): Promise<{
16
+ gasFee: bigint;
17
+ gasQuoteSource: string;
18
+ simulationVerified?: boolean;
19
+ platformFee?: bigint;
20
+ }>;
21
+ export declare function quoteConvertedFees(ctx: FeePreviewContext, input?: {
22
+ token: Address;
23
+ amount: bigint;
24
+ }): Promise<SupplyFeeQuote>;
@@ -0,0 +1,21 @@
1
+ import type { Address } from "viem";
2
+ import type { Asset } from "../../../types/assets";
3
+ import type { FeeFundingLevel, FeeFundingSource, SpiceSupplyProps } from "../../../types/supply";
4
+ import type { FeePreviewContext, SupplyFeeQuote } from "./feePreview";
5
+ export declare const DEFAULT_FEE_FUNDING: FeeFundingLevel[];
6
+ type Candidate = FeeFundingSource & {
7
+ swap: boolean;
8
+ };
9
+ export declare function rankFeeFundingCandidates(args: {
10
+ feeToken: Address;
11
+ chainId: number;
12
+ inputs?: SpiceSupplyProps["actionInput"];
13
+ proceeds?: {
14
+ token: Address;
15
+ amount: bigint;
16
+ };
17
+ balances: Asset[];
18
+ order?: FeeFundingLevel[];
19
+ }): Candidate[];
20
+ export declare function quoteFeeFunding(ctx: FeePreviewContext, estimateFeePreview: (ctx: FeePreviewContext) => Promise<SupplyFeeQuote | null>): Promise<SupplyFeeQuote | null>;
21
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { type Address } from "viem";
2
- import type { ChainBatch } from "../../../types/authorization";
3
2
  import type { ExecutionOptions } from "../../../hooks/useSpiceExecution";
3
+ import type { ChainBatch } from "../../../types/authorization";
4
4
  import type { ExecutorContext } from "./executors";
5
5
  export declare function stripFeeOnlyCalls(batches: ChainBatch[], chainId: number, token: Address): ChainBatch[];
6
6
  export declare function feeOnlyExecutionOptions(ctx: ExecutorContext, token: Address, fundingCap: bigint): Pick<ExecutionOptions, "prepareForSigning" | "validateBeforeSubmit" | "resolveActionOutputCredits">;