@spicenet-io/spiceflow-ui 4.9.1 → 4.9.3-anydeposit.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 (30) hide show
  1. package/README.md +43 -0
  2. package/dist/auth-privy.js +1 -1
  3. package/dist/components/AccountDisplay/parts/AccountIdleBalances.d.ts +2 -5
  4. package/dist/components/AccountDisplay/parts/AccountPanel.d.ts +2 -2
  5. package/dist/components/AccountDisplay/types.d.ts +5 -2
  6. package/dist/components/SpiceDeposit/lib/escrowCredit.d.ts +2 -0
  7. package/dist/components/SpiceSupply/lib/buildBatches.d.ts +2 -0
  8. package/dist/components/SpiceSupply/lib/executors.d.ts +1 -0
  9. package/dist/components/SpiceSupply/lib/feePreview.d.ts +1 -0
  10. package/dist/components/SpiceWithdraw/lib/helpers.d.ts +1 -1
  11. package/dist/components/SpiceWithdraw/parts/WithdrawBalanceCardHeader.d.ts +0 -1
  12. package/dist/hooks/index.d.ts +2 -0
  13. package/dist/hooks/useDirectWithdraw.d.ts +8 -2
  14. package/dist/hooks/useIsUserWhitelisted.d.ts +12 -12
  15. package/dist/hooks/useSpiceAssets.d.ts +2 -1
  16. package/dist/hooks/useSpiceRollupPrices.d.ts +2 -0
  17. package/dist/hooks/useSupplyAssets.d.ts +8 -0
  18. package/dist/hooks/useWalletBalances.d.ts +2 -1
  19. package/dist/index.cjs.js +13 -13
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +15 -15
  22. package/dist/{privy-C_1pWb8P.js → privy-BIH6VVaM.js} +1 -1
  23. package/dist/types/assets.d.ts +1 -0
  24. package/dist/types/supply.d.ts +1 -1
  25. package/dist/types/withdraw.d.ts +1 -0
  26. package/dist/utils/directWithdraw.d.ts +0 -4
  27. package/dist/utils/fees.d.ts +7 -0
  28. package/dist/utils/prices/providerPrices.d.ts +12 -0
  29. package/package.json +4 -1
  30. package/dist/components/SpiceWithdraw/parts/WithdrawBalancePopover.d.ts +0 -15
package/README.md CHANGED
@@ -108,6 +108,49 @@ it becomes a `protocol` everyone can name.
108
108
 
109
109
  ## Development
110
110
 
111
+ ### Rollup balance pricing
112
+
113
+ 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.
114
+
115
+ 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.
116
+
117
+ ### Direct withdrawal in a custom balance row
118
+
119
+ `useSpiceDirectWithdraw()` uses the same embedded-wallet transfer and fee path as the account panel's direct Withdraw buttons. It selects the connected external wallet as recipient, exposes `canWithdraw` and `state`, and rejects duplicate submissions while pending. Pass the raw `bigint` balance to `withdraw({ tokenAddress, chainId, balance })` and refresh the host's balance after it resolves. Rejections are available as `state.message` for the host to render.
120
+
121
+ Custom account rows accept React content in `displayValue`, so a host can render its own button with that controller. Set the row's `asset: { tokenAddress, chainId }` when it represents an on-chain balance; the account panel then omits that token from discovered idle balances. Existing string values continue to work.
122
+
123
+ ### Withdraw from an account balance
124
+
125
+ `AccountDisplay.onWithdrawClick` receives the rollup receipt-token ID when a
126
+ user clicks Withdraw on an idle rollup balance. The main Withdraw button calls
127
+ it without an ID. Pass the ID to `SpiceWithdraw.initialSourceAssetId` to open
128
+ the existing modal with that asset selected; the user chooses the destination
129
+ network inside the modal. Existing callbacks that take no arguments continue
130
+ to work.
131
+
132
+ ```tsx
133
+ const [withdrawOpen, setWithdrawOpen] = useState(false);
134
+ const [withdrawAssetId, setWithdrawAssetId] = useState<string>();
135
+
136
+ <AccountDisplay
137
+ onWithdrawClick={(receiptTokenId) => {
138
+ setWithdrawAssetId(receiptTokenId);
139
+ setWithdrawOpen(true);
140
+ }}
141
+ />
142
+ <SpiceWithdraw
143
+ isOpen={withdrawOpen}
144
+ onClose={() => setWithdrawOpen(false)}
145
+ initialSourceAssetId={withdrawAssetId}
146
+ buildSpicenetBatch={buildSpicenetWithdrawalBatch}
147
+ />
148
+ ```
149
+
150
+ Keep the integration's existing withdrawal batch builder and callbacks.
151
+ `initialSourceAssetId` selects a current balance by ID; it does not supply a
152
+ cached balance or change the receipt's supported withdrawal routes.
153
+
111
154
  ### Fee-Charging Intent Flows
112
155
 
113
156
  - `SpiceSupply` and `SpicePay` are fee-charging intent-execution flows and must surface fee estimation before enabling submission.
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{P as g}from"./privy-C_1pWb8P.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-BIH6VVaM.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};
@@ -1,11 +1,7 @@
1
1
  import React from "react";
2
2
  import { SpiceAsset } from "../types";
3
3
  import type { ResolvedDarkPalette } from "../../../utils/theme";
4
- export interface DirectWithdrawState {
5
- key: string;
6
- step: "pending" | "error";
7
- message?: string;
8
- }
4
+ import type { DirectWithdrawState } from "../../../hooks/useDirectWithdraw";
9
5
  interface AccountIdleBalancesProps {
10
6
  spiceAssets: SpiceAsset[];
11
7
  loading: boolean;
@@ -14,6 +10,7 @@ interface AccountIdleBalancesProps {
14
10
  canDirectWithdraw?: boolean;
15
11
  onDirectWithdraw?: (asset: SpiceAsset) => void;
16
12
  directWithdrawState?: DirectWithdrawState | null;
13
+ onWithdrawClick?: (receiptTokenId?: string) => void;
17
14
  }
18
15
  export declare const AccountIdleBalances: React.NamedExoticComponent<AccountIdleBalancesProps>;
19
16
  export {};
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { SpiceAsset, CustomSection, AccountNotice } from "../types";
3
3
  import { VerifiedPendingDeposit } from "../../../hooks/usePendingDeposit";
4
4
  import type { ResolvedDarkPalette } from "../../../utils/theme";
5
- import { type DirectWithdrawState } from "./AccountIdleBalances";
5
+ import type { DirectWithdrawState } from "../../../hooks/useDirectWithdraw";
6
6
  interface AccountPanelProps {
7
7
  appName: string;
8
8
  status: "active" | "inactive";
@@ -17,7 +17,7 @@ interface AccountPanelProps {
17
17
  customSections: CustomSection[];
18
18
  notice?: AccountNotice | null;
19
19
  onDepositClick?: () => void;
20
- onWithdrawClick?: () => void;
20
+ onWithdrawClick?: (receiptTokenId?: string) => void;
21
21
  depositDisabled?: boolean;
22
22
  onCompleteDeposit?: (deposit: VerifiedPendingDeposit) => void;
23
23
  primaryColor?: string;
@@ -5,7 +5,8 @@ export interface CustomSectionItem {
5
5
  tokenSymbol: string;
6
6
  tokenLogoURI?: string;
7
7
  label: string;
8
- displayValue: string;
8
+ displayValue: React.ReactNode;
9
+ asset?: Pick<SpiceAsset, "tokenAddress" | "chainId">;
9
10
  valueColor?: "green" | "red" | "default";
10
11
  }
11
12
  export interface CustomSection {
@@ -24,7 +25,9 @@ export interface SpiceAsset {
24
25
  balance: string;
25
26
  balanceFormatted: number;
26
27
  usdValue: number;
28
+ priceStatus?: "fresh" | "stale" | "unavailable";
27
29
  logoURI?: string;
30
+ receiptTokenId?: string;
28
31
  directWithdraw?: boolean;
29
32
  }
30
33
  export interface BreakdownLabel {
@@ -48,7 +51,7 @@ export interface AccountDisplayProps {
48
51
  dark?: boolean;
49
52
  onDepositSuccess?: () => void;
50
53
  onDepositClick?: () => void;
51
- onWithdrawClick?: () => void;
54
+ onWithdrawClick?: (receiptTokenId?: string) => void;
52
55
  onCompleteDeposit?: (deposit: VerifiedPendingDeposit) => void;
53
56
  showModeToggle?: boolean;
54
57
  defaultMode?: "7702" | "non7702";
@@ -0,0 +1,2 @@
1
+ import type { Asset } from "../../../types/assets";
2
+ export declare function isEscrowCreditable(asset: Pick<Asset, "address" | "chainId" | "isNative">): boolean;
@@ -7,6 +7,7 @@ import type { ResolvedExactOutputSwap } from "../../../utils/swapQuotes";
7
7
  import type { ExecutionOptions } from "../../../hooks/useSpiceExecution";
8
8
  import type { FeeEstimateSummary } from "@spicenet-io/spiceflow-core";
9
9
  type EstimateFn = (chainBatches: ChainBatch[], tokenAddress: string, tokenTransferAmount: bigint, options?: ExecutionOptions) => Promise<FeeEstimateSummary>;
10
+ export declare function isExternalInPlacePaySource(selectedAsset: SelectedAsset | null, isNon7702: boolean, resolvedChainId: number): boolean;
10
11
  export declare function stripSpicenetFundingBatches(batches: ChainBatch[]): ChainBatch[];
11
12
  export declare function scaleTokenAmount(amount: bigint, fromDecimals: number, toDecimals: number): bigint;
12
13
  export interface BatchBuilderContext {
@@ -26,6 +27,7 @@ export interface BatchBuilderContext {
26
27
  selectedAsset: SelectedAsset | null;
27
28
  needsSwap: boolean;
28
29
  resolvedSwap: ResolvedSwap | null;
30
+ resolveInputSwap?: (amountIn: bigint) => Promise<ResolvedSwap>;
29
31
  exactOutputSwap: ResolvedExactOutputSwap | null;
30
32
  quoteAmountOut: bigint | null;
31
33
  resolvedTokenIn: Address | null;
@@ -18,6 +18,7 @@ export type ExecutorContext = {
18
18
  currentPaymentAmount: string;
19
19
  isInsufficientBalance: boolean;
20
20
  isPayMode: boolean;
21
+ isFeeInclusiveInput?: boolean;
21
22
  isNon7702: boolean;
22
23
  isSourceDestToken: boolean;
23
24
  needsSwap: boolean;
@@ -49,6 +49,7 @@ export interface FeePreviewContext {
49
49
  signal?: AbortSignal;
50
50
  selectedAsset: SelectedAsset | null;
51
51
  isPayMode: boolean;
52
+ isFeeInclusiveInput?: boolean;
52
53
  parsedAmount: number;
53
54
  needsSwap: boolean;
54
55
  exactOutputSwap: ResolvedExactOutputSwap | null;
@@ -2,5 +2,5 @@ import type { ChainBatch } from "../../../types/authorization";
2
2
  export declare function normalizeTokenLabel(value?: string | null): string;
3
3
  export declare function formatTokenAmount(rawAmount: bigint, decimals: number): string;
4
4
  export declare function scaleAmountBetweenDecimals(amount: bigint, fromDecimals: number, toDecimals: number): bigint;
5
- export declare function estimateUsd(amount: number, symbol?: string): string;
5
+ export declare function estimateUsd(amount: number, price?: number, stale?: boolean): string;
6
6
  export declare function buildWithdrawFeeEstimateKey(batches: ChainBatch[], tokenAddress?: string | null): string | null;
@@ -4,7 +4,6 @@ interface WithdrawBalanceCardHeaderProps {
4
4
  label: string;
5
5
  spiceAssetsLoading: boolean;
6
6
  totalSelectedBalance: number;
7
- onOpenBalancePopover: (anchor: HTMLElement | null) => void;
8
7
  dark: boolean;
9
8
  dk: ResolvedDarkPalette;
10
9
  }
@@ -6,6 +6,8 @@ export type { UseWalletReturn, WalletState, WalletActions } from "./useWallet";
6
6
  export { useSpiceAssets } from "./useSpiceAssets";
7
7
  export type { UseSpiceAssetsConfig, UseSpiceAssetsReturn, } from "./useSpiceAssets";
8
8
  export { useSpiceExecution } from "./useSpiceExecution";
9
+ export { useDirectWithdraw as useSpiceDirectWithdraw } from "./useDirectWithdraw";
10
+ export type { DirectWithdrawParams, DirectWithdrawState, } from "./useDirectWithdraw";
9
11
  export type { ExecutionProgress, ExecutionStep, ExecutionOptions, OnProgress, } from "./useSpiceExecution";
10
12
  export { useLockDuration } from "./useLockDuration";
11
13
  export type { UseLockDurationReturn } from "./useLockDuration";
@@ -4,9 +4,15 @@ export interface DirectWithdrawParams {
4
4
  tokenAddress: Address | string;
5
5
  chainId: number;
6
6
  balance: bigint;
7
- recipient: Address | string;
8
7
  onProgress?: (progress: ExecutionProgress) => void;
9
8
  }
9
+ export interface DirectWithdrawState {
10
+ key: string;
11
+ step: "pending" | "error";
12
+ message?: string;
13
+ }
10
14
  export declare function useDirectWithdraw(): {
11
- withdraw: ({ tokenAddress, chainId, balance, recipient, onProgress, }: DirectWithdrawParams) => Promise<string>;
15
+ withdraw: ({ tokenAddress, chainId, balance, onProgress, }: DirectWithdrawParams) => Promise<string>;
16
+ canWithdraw: boolean;
17
+ state: DirectWithdrawState | null;
12
18
  };
@@ -43,8 +43,8 @@ export declare function useIsUserWhitelisted({ walletAddress, campaignId, campai
43
43
  isRefetching: boolean;
44
44
  isStale: boolean;
45
45
  isEnabled: boolean;
46
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
47
- fetchStatus: import("@tanstack/query-core").FetchStatus;
46
+ refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
47
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
48
48
  promise: Promise<PartnerWhitelistCheckResponse>;
49
49
  isWhitelisted: boolean;
50
50
  whitelistCheck: PartnerWhitelistCheckResponse | undefined;
@@ -82,8 +82,8 @@ export declare function useIsUserWhitelisted({ walletAddress, campaignId, campai
82
82
  isRefetching: boolean;
83
83
  isStale: boolean;
84
84
  isEnabled: boolean;
85
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
86
- fetchStatus: import("@tanstack/query-core").FetchStatus;
85
+ refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
86
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
87
87
  promise: Promise<PartnerWhitelistCheckResponse>;
88
88
  isWhitelisted: boolean;
89
89
  whitelistCheck: PartnerWhitelistCheckResponse | undefined;
@@ -121,8 +121,8 @@ export declare function useIsUserWhitelisted({ walletAddress, campaignId, campai
121
121
  isRefetching: boolean;
122
122
  isStale: boolean;
123
123
  isEnabled: boolean;
124
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
125
- fetchStatus: import("@tanstack/query-core").FetchStatus;
124
+ refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
125
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
126
126
  promise: Promise<PartnerWhitelistCheckResponse>;
127
127
  isWhitelisted: boolean;
128
128
  whitelistCheck: PartnerWhitelistCheckResponse | undefined;
@@ -160,8 +160,8 @@ export declare function useIsUserWhitelisted({ walletAddress, campaignId, campai
160
160
  isRefetching: boolean;
161
161
  isStale: boolean;
162
162
  isEnabled: boolean;
163
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
164
- fetchStatus: import("@tanstack/query-core").FetchStatus;
163
+ refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
164
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
165
165
  promise: Promise<PartnerWhitelistCheckResponse>;
166
166
  isWhitelisted: boolean;
167
167
  whitelistCheck: PartnerWhitelistCheckResponse | undefined;
@@ -199,8 +199,8 @@ export declare function useIsUserWhitelisted({ walletAddress, campaignId, campai
199
199
  isRefetching: boolean;
200
200
  isStale: boolean;
201
201
  isEnabled: boolean;
202
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
203
- fetchStatus: import("@tanstack/query-core").FetchStatus;
202
+ refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
203
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
204
204
  promise: Promise<PartnerWhitelistCheckResponse>;
205
205
  isWhitelisted: boolean;
206
206
  whitelistCheck: PartnerWhitelistCheckResponse | undefined;
@@ -238,8 +238,8 @@ export declare function useIsUserWhitelisted({ walletAddress, campaignId, campai
238
238
  isRefetching: boolean;
239
239
  isStale: boolean;
240
240
  isEnabled: boolean;
241
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
242
- fetchStatus: import("@tanstack/query-core").FetchStatus;
241
+ refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<PartnerWhitelistCheckResponse, Error>>;
242
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
243
243
  promise: Promise<PartnerWhitelistCheckResponse>;
244
244
  isWhitelisted: boolean;
245
245
  whitelistCheck: PartnerWhitelistCheckResponse | undefined;
@@ -5,6 +5,7 @@ export interface UseSpiceAssetsConfig {
5
5
  supportedChains?: number[];
6
6
  enabled?: boolean;
7
7
  refetchInterval?: number;
8
+ priceEnabled?: boolean;
8
9
  }
9
10
  export interface UseSpiceAssetsReturn {
10
11
  assets: Asset[];
@@ -14,4 +15,4 @@ export interface UseSpiceAssetsReturn {
14
15
  refetch: () => Promise<void>;
15
16
  getAssetsByChain: (chainId: number) => Asset[];
16
17
  }
17
- export declare const useSpiceAssets: ({ address, supportedChains, enabled, refetchInterval, }: UseSpiceAssetsConfig) => UseSpiceAssetsReturn;
18
+ export declare const useSpiceAssets: ({ address, supportedChains, enabled, refetchInterval, priceEnabled, }: UseSpiceAssetsConfig) => UseSpiceAssetsReturn;
@@ -0,0 +1,2 @@
1
+ import type { Asset } from "../types/assets";
2
+ export declare function useSpiceRollupPrices(assets: Asset[], enabled: boolean, supportedChains?: number[]): Asset[];
@@ -1,9 +1,17 @@
1
1
  import { type Address } from "viem";
2
2
  import type { Asset } from "../types/assets";
3
+ export declare function compareSupplyAssets(a: Asset & {
4
+ _source?: string;
5
+ }, b: Asset & {
6
+ _source?: string;
7
+ }, destToken: string, destChain: number): number;
3
8
  export declare function isSupportedSupplyAsset(asset: Pick<Asset, "address" | "chainTokens">, supportedSourceAssets?: string[]): boolean;
4
9
  export declare function isSpendableSupplyAsset(asset: Pick<Asset, "address" | "chainTokens" | "chainId"> & {
5
10
  _source?: string;
6
11
  }, destinationChainId: number, supportedSourceAssets?: string[]): boolean;
12
+ export declare function isSpendableExternalAsset(asset: Pick<Asset, "address" | "chainTokens" | "chainId"> & {
13
+ _source?: string;
14
+ }, destinationToken: Pick<DestinationToken, "address" | "chainId">, supportedSourceAssets?: string[]): boolean;
7
15
  type DestinationToken = {
8
16
  address: Address;
9
17
  decimals: number;
@@ -8,6 +8,7 @@ export interface UseAssetsConfig {
8
8
  fetchBalances: (address: Address, supportedChains?: number[]) => Promise<MultiChainBalances>;
9
9
  enabled?: boolean;
10
10
  refreshInterval?: number;
11
+ priceEnabled?: boolean;
11
12
  }
12
13
  export interface UseAssetsReturn {
13
14
  assets: Asset[];
@@ -17,4 +18,4 @@ export interface UseAssetsReturn {
17
18
  getAssetsByChain: (chainId: number) => Asset[];
18
19
  getNativeAssets: () => Asset[];
19
20
  }
20
- export declare const useWalletBalances: ({ address, supportedChains, fetchBalances, enabled, refreshInterval, }: UseAssetsConfig) => UseAssetsReturn;
21
+ export declare const useWalletBalances: ({ address, supportedChains, fetchBalances, enabled, refreshInterval, priceEnabled, }: UseAssetsConfig) => UseAssetsReturn;