Skip to content

Commit 751bd0a

Browse files
committed
add success and error screens
1 parent c917607 commit 751bd0a

File tree

1 file changed

+70
-13
lines changed

1 file changed

+70
-13
lines changed

packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { useState } from "react";
3+
import { useCallback, useState } from "react";
44
import type { Buy, Sell } from "../../../../../bridge/index.js";
55
import type { TokenWithPrices } from "../../../../../bridge/types/Token.js";
66
import type { ThirdwebClient } from "../../../../../client/client.js";
@@ -12,11 +12,14 @@ import type {
1212
BridgePrepareRequest,
1313
BridgePrepareResult,
1414
} from "../../../../core/hooks/useBridgePrepare.js";
15+
import type { CompletedStatusResult } from "../../../../core/hooks/useStepExecutor.js";
1516
import { webWindowAdapter } from "../../../adapters/WindowAdapter.js";
1617
import { EmbedContainer } from "../../ConnectWallet/Modal/ConnectEmbed.js";
1718
import { DynamicHeight } from "../../components/DynamicHeight.js";
1819
import type { LocaleId } from "../../types.js";
20+
import { ErrorBanner } from "../ErrorBanner.js";
1921
import { PaymentDetails } from "../payment-details/PaymentDetails.js";
22+
import { SuccessScreen } from "../payment-success/SuccessScreen.js";
2023
import { QuoteLoader } from "../QuoteLoader.js";
2124
import { StepRunner } from "../StepRunner.js";
2225
import { useActiveWalletInfo } from "./hooks.js";
@@ -102,6 +105,17 @@ type SwapWidgetScreen =
102105
preparedQuote: BridgePrepareResult;
103106
buyToken: TokenWithPrices;
104107
sellToken: TokenWithPrices;
108+
}
109+
| {
110+
id: "5:success";
111+
completedStatuses: CompletedStatusResult[];
112+
preparedQuote: BridgePrepareResult;
113+
buyToken: TokenWithPrices;
114+
sellToken: TokenWithPrices;
115+
}
116+
| {
117+
id: "error";
118+
error: Error;
105119
};
106120

107121
function SwapWidgetContent(props: SwapWidgetProps) {
@@ -111,6 +125,18 @@ function SwapWidgetContent(props: SwapWidgetProps) {
111125
// preload requests
112126
useBridgeChains(props.client);
113127

128+
const handleError = useCallback(
129+
(error: Error) => {
130+
console.error(error);
131+
props.onError?.(error);
132+
setScreen({
133+
id: "error",
134+
error,
135+
});
136+
},
137+
[props.onError],
138+
);
139+
114140
// if wallet suddenly disconnects, show screen 1
115141
if (screen.id === "1:swap-ui" || !activeWalletInfo) {
116142
return (
@@ -138,17 +164,14 @@ function SwapWidgetContent(props: SwapWidgetProps) {
138164
screen.quote.destinationAmount,
139165
screen.buyToken.decimals,
140166
)}
141-
onError={() => {
142-
// TODO
143-
}}
167+
onError={handleError}
144168
onQuoteReceived={(preparedQuote, request) => {
145169
setScreen({
146170
...screen,
147171
id: "3:preview",
148172
preparedQuote,
149173
request,
150174
});
151-
// TODO
152175
}}
153176
receiver={activeWalletInfo.activeAccount.address}
154177
onBack={() => setScreen({ id: "1:swap-ui" })}
@@ -183,9 +206,7 @@ function SwapWidgetContent(props: SwapWidgetProps) {
183206
id: "4:execute",
184207
});
185208
}}
186-
onError={(_error) => {
187-
// TODO
188-
}}
209+
onError={handleError}
189210
paymentMethod={{
190211
quote: screen.quote,
191212
type: "wallet",
@@ -214,11 +235,13 @@ function SwapWidgetContent(props: SwapWidgetProps) {
214235
id: "3:preview",
215236
});
216237
}}
217-
onCancel={() => {
218-
// TODO
219-
}}
220-
onComplete={() => {
221-
// TODO
238+
onCancel={props.onCancel}
239+
onComplete={(completedStatuses) => {
240+
setScreen({
241+
...screen,
242+
id: "5:success",
243+
completedStatuses,
244+
});
222245
}}
223246
request={screen.request}
224247
wallet={activeWalletInfo.activeWallet}
@@ -227,5 +250,39 @@ function SwapWidgetContent(props: SwapWidgetProps) {
227250
);
228251
}
229252

253+
if (screen.id === "5:success") {
254+
return (
255+
<SuccessScreen
256+
client={props.client}
257+
completedStatuses={screen.completedStatuses}
258+
onDone={() => {
259+
setScreen({ id: "1:swap-ui" });
260+
}}
261+
preparedQuote={screen.preparedQuote}
262+
uiOptions={{
263+
destinationToken: screen.buyToken,
264+
mode: "fund_wallet",
265+
currency: props.currency,
266+
}}
267+
windowAdapter={webWindowAdapter}
268+
hasPaymentId={false} // TODO Question: Do we need to expose this as prop?
269+
/>
270+
);
271+
}
272+
273+
if (screen.id === "error") {
274+
<ErrorBanner
275+
client={props.client}
276+
error={screen.error}
277+
onCancel={() => {
278+
setScreen({ id: "1:swap-ui" });
279+
props.onCancel?.();
280+
}}
281+
onRetry={() => {
282+
setScreen({ id: "1:swap-ui" });
283+
}}
284+
/>;
285+
}
286+
230287
return null;
231288
}

0 commit comments

Comments
 (0)