diff --git a/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts b/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts index c2e7e7083a3..bc1e6502d0d 100644 --- a/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts +++ b/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts @@ -1,4 +1,3 @@ -import { useQuery } from "@tanstack/react-query"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import type { status as OnrampStatus } from "../../../bridge/OnrampStatus.js"; import { ApiError } from "../../../bridge/types/Errors.js"; @@ -10,14 +9,9 @@ import type { Status } from "../../../bridge/types/Status.js"; import { getCachedChain } from "../../../chains/utils.js"; import type { ThirdwebClient } from "../../../client/client.js"; import { waitForReceipt } from "../../../transaction/actions/wait-for-tx-receipt.js"; -import { stringify } from "../../../utils/json.js"; import type { Account, Wallet } from "../../../wallets/interfaces/wallet.js"; import type { WindowAdapter } from "../adapters/WindowAdapter.js"; -import { - type BridgePrepareRequest, - type BridgePrepareResult, - useBridgePrepare, -} from "./useBridgePrepare.js"; +import type { BridgePrepareResult } from "./useBridgePrepare.js"; /** * Type for completed status results from Bridge.status and Onramp.status @@ -35,8 +29,7 @@ export type CompletedStatusResult = * Options for the step executor hook */ interface StepExecutorOptions { - /** Prepared quote returned by Bridge.prepare */ - request: BridgePrepareRequest; + preparedQuote: BridgePrepareResult; /** Wallet instance providing getAccount() & sendTransaction */ wallet?: Wallet; /** Window adapter for opening on-ramp URLs (web / RN) */ @@ -67,7 +60,7 @@ interface StepExecutorResult { currentTxIndex?: number; progress: number; // 0–100 onrampStatus?: "pending" | "executing" | "completed" | "failed"; - executionState: "fetching" | "idle" | "executing" | "auto-starting"; + executionState: "idle" | "executing" | "auto-starting"; steps?: RouteStep[]; error?: ApiError; start: () => void; @@ -100,16 +93,14 @@ export function useStepExecutor( options: StepExecutorOptions, ): StepExecutorResult { const { - request, wallet, windowAdapter, client, autoStart = false, onComplete, + preparedQuote, } = options; - const { data: preparedQuote, isLoading } = useBridgePrepare(request); - // Flatten all transactions upfront const flatTxs = useMemo( () => (preparedQuote?.steps ? flattenRouteSteps(preparedQuote.steps) : []), @@ -121,7 +112,7 @@ export function useStepExecutor( undefined, ); const [executionState, setExecutionState] = useState< - "fetching" | "idle" | "executing" | "auto-starting" + "idle" | "executing" | "auto-starting" >("idle"); const [error, setError] = useState(undefined); const [completedTxs, setCompletedTxs] = useState>(new Set()); @@ -129,22 +120,6 @@ export function useStepExecutor( "pending" | "executing" | "completed" | "failed" | undefined >(preparedQuote?.type === "onramp" ? "pending" : undefined); - useQuery({ - queryFn: async () => { - if (!isLoading) { - setExecutionState("idle"); - } else { - setExecutionState("fetching"); - } - return executionState; - }, - queryKey: [ - "bridge-quote-execution-state", - stringify(preparedQuote?.steps), - isLoading, - ], - }); - // Cancellation tracking const abortControllerRef = useRef(null); diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx index 7b29dafca23..f146a0d0eba 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx @@ -379,6 +379,7 @@ export function BridgeOrchestrator({ {state.value === "execute" && quote && state.context.request && ( { diff --git a/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx b/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx index d2c289eaab1..f139c0ecd8b 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx @@ -12,7 +12,10 @@ import { radius, spacing, } from "../../../core/design-system/index.js"; -import type { BridgePrepareRequest } from "../../../core/hooks/useBridgePrepare.js"; +import type { + BridgePrepareRequest, + BridgePrepareResult, +} from "../../../core/hooks/useBridgePrepare.js"; import { type CompletedStatusResult, useStepExecutor, @@ -62,6 +65,11 @@ interface StepRunnerProps { * Called when user clicks the back button */ onBack?: () => void; + + /** + * Prepared quote to use + */ + preparedQuote: BridgePrepareResult; } export function StepRunner({ @@ -74,6 +82,7 @@ export function StepRunner({ onCancel, onBack, autoStart, + preparedQuote, }: StepRunnerProps) { const theme = useCustomTheme(); @@ -94,8 +103,8 @@ export function StepRunner({ onComplete: (completedStatuses: CompletedStatusResult[]) => { onComplete(completedStatuses); }, - request, wallet, + preparedQuote, windowAdapter, }); diff --git a/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx index b585e34a1a7..89bc35afe58 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx @@ -448,6 +448,7 @@ function SwapWidgetContent(props: SwapWidgetProps) { { setScreen({ diff --git a/packages/thirdweb/src/stories/Bridge/StepRunner.stories.tsx b/packages/thirdweb/src/stories/Bridge/StepRunner.stories.tsx index 6f6fc34812f..bcab65c8a31 100644 --- a/packages/thirdweb/src/stories/Bridge/StepRunner.stories.tsx +++ b/packages/thirdweb/src/stories/Bridge/StepRunner.stories.tsx @@ -7,7 +7,11 @@ import type { CompletedStatusResult } from "../../react/core/hooks/useStepExecut import { StepRunner } from "../../react/web/ui/Bridge/StepRunner.js"; import type { Wallet } from "../../wallets/interfaces/wallet.js"; import { ModalThemeWrapper, storyClient } from "../utils.js"; -import { STORY_MOCK_WALLET, simpleBuyRequest } from "./fixtures.js"; +import { + STORY_MOCK_WALLET, + simpleBuyQuote, + simpleBuyRequest, +} from "./fixtures.js"; // Mock window adapter const mockWindowAdapter: WindowAdapter = { @@ -32,7 +36,7 @@ const StepRunnerWithTheme = (props: StepRunnerWithThemeProps) => { const { theme, ...componentProps } = props; return ( - + ); }; @@ -59,29 +63,8 @@ const meta = { }, component: StepRunnerWithTheme, parameters: { - docs: { - description: { - component: - "**StepRunner** executes prepared route steps sequentially, showing real-time progress and transaction status.\n\n" + - "## Features\n" + - "- **Real Execution**: Uses useStepExecutor hook for actual transaction processing\n" + - "- **Progress Tracking**: Visual progress bar and step-by-step status updates\n" + - "- **Error Handling**: Retry functionality for failed transactions\n" + - "- **Transaction Batching**: Optimizes multiple transactions when possible\n" + - "- **Onramp Support**: Handles fiat-to-crypto onramp flows\n\n" + - "## Props\n" + - "- `steps`: Array of RouteStep objects from Bridge.prepare()\n" + - "- `wallet`: Connected wallet for transaction signing\n" + - "- `client`: ThirdwebClient instance\n" + - "- `windowAdapter`: Platform-specific window/URL handler\n" + - "- `onramp`: Optional onramp configuration\n\n" + - "## Integration\n" + - "This component is typically used within the BridgeOrchestrator after route preparation.", - }, - }, layout: "centered", }, - tags: ["autodocs"], title: "Bridge/StepRunner", } satisfies Meta;