thirdweb 5.108.15 → 5.109.1-nightly-b1a780832ed97d80399a650beab537a89c628278-20251018000336

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 (117) hide show
  1. package/dist/cjs/exports/react.js.map +1 -1
  2. package/dist/cjs/extensions/erc20/read/getCurrencyMetadata.js +31 -7
  3. package/dist/cjs/extensions/erc20/read/getCurrencyMetadata.js.map +1 -1
  4. package/dist/cjs/react/web/ui/Bridge/BuyWidget.js +19 -6
  5. package/dist/cjs/react/web/ui/Bridge/BuyWidget.js.map +1 -1
  6. package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js +4 -1
  7. package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
  8. package/dist/cjs/react/web/ui/Bridge/FundWallet.js +8 -22
  9. package/dist/cjs/react/web/ui/Bridge/FundWallet.js.map +1 -1
  10. package/dist/cjs/react/web/ui/Bridge/bridge-widget/bridge-widget.js +12 -0
  11. package/dist/cjs/react/web/ui/Bridge/bridge-widget/bridge-widget.js.map +1 -1
  12. package/dist/cjs/react/web/ui/Bridge/swap-widget/SearchInput.js +1 -1
  13. package/dist/cjs/react/web/ui/Bridge/swap-widget/SearchInput.js.map +1 -1
  14. package/dist/cjs/react/web/ui/Bridge/swap-widget/SwapWidget.js +4 -1
  15. package/dist/cjs/react/web/ui/Bridge/swap-widget/SwapWidget.js.map +1 -1
  16. package/dist/cjs/react/web/ui/Bridge/swap-widget/select-token-ui.js +1 -1
  17. package/dist/cjs/react/web/ui/Bridge/swap-widget/select-token-ui.js.map +1 -1
  18. package/dist/cjs/react/web/ui/Bridge/swap-widget/swap-ui.js +1 -1
  19. package/dist/cjs/react/web/ui/Bridge/swap-widget/swap-ui.js.map +1 -1
  20. package/dist/cjs/react/web/ui/components/Modal.js +3 -1
  21. package/dist/cjs/react/web/ui/components/Modal.js.map +1 -1
  22. package/dist/cjs/script-exports/bridge-widget-script.js.map +1 -1
  23. package/dist/cjs/stories/Bridge/BridgeWidget/bridge-widget-script.stories.js +13 -13
  24. package/dist/cjs/stories/Bridge/BridgeWidget/bridge-widget-script.stories.js.map +1 -1
  25. package/dist/cjs/stories/Bridge/Swap/SwapWidget.Prefill.stories.js +14 -9
  26. package/dist/cjs/stories/Bridge/Swap/SwapWidget.Prefill.stories.js.map +1 -1
  27. package/dist/cjs/stories/Bridge/Swap/SwapWidget.stories.js +12 -12
  28. package/dist/cjs/stories/Bridge/Swap/SwapWidget.stories.js.map +1 -1
  29. package/dist/cjs/stories/BuyWidget.stories.js +6 -4
  30. package/dist/cjs/stories/BuyWidget.stories.js.map +1 -1
  31. package/dist/cjs/version.js +1 -1
  32. package/dist/cjs/version.js.map +1 -1
  33. package/dist/esm/exports/react.js.map +1 -1
  34. package/dist/esm/extensions/erc20/read/getCurrencyMetadata.js +31 -7
  35. package/dist/esm/extensions/erc20/read/getCurrencyMetadata.js.map +1 -1
  36. package/dist/esm/react/web/ui/Bridge/BuyWidget.js +20 -7
  37. package/dist/esm/react/web/ui/Bridge/BuyWidget.js.map +1 -1
  38. package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js +4 -1
  39. package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
  40. package/dist/esm/react/web/ui/Bridge/FundWallet.js +8 -22
  41. package/dist/esm/react/web/ui/Bridge/FundWallet.js.map +1 -1
  42. package/dist/esm/react/web/ui/Bridge/bridge-widget/bridge-widget.js +12 -0
  43. package/dist/esm/react/web/ui/Bridge/bridge-widget/bridge-widget.js.map +1 -1
  44. package/dist/esm/react/web/ui/Bridge/swap-widget/SearchInput.js +1 -1
  45. package/dist/esm/react/web/ui/Bridge/swap-widget/SearchInput.js.map +1 -1
  46. package/dist/esm/react/web/ui/Bridge/swap-widget/SwapWidget.js +4 -1
  47. package/dist/esm/react/web/ui/Bridge/swap-widget/SwapWidget.js.map +1 -1
  48. package/dist/esm/react/web/ui/Bridge/swap-widget/select-token-ui.js +1 -1
  49. package/dist/esm/react/web/ui/Bridge/swap-widget/select-token-ui.js.map +1 -1
  50. package/dist/esm/react/web/ui/Bridge/swap-widget/swap-ui.js +1 -1
  51. package/dist/esm/react/web/ui/Bridge/swap-widget/swap-ui.js.map +1 -1
  52. package/dist/esm/react/web/ui/components/Modal.js +3 -1
  53. package/dist/esm/react/web/ui/components/Modal.js.map +1 -1
  54. package/dist/esm/script-exports/bridge-widget-script.js.map +1 -1
  55. package/dist/esm/stories/Bridge/BridgeWidget/bridge-widget-script.stories.js +15 -15
  56. package/dist/esm/stories/Bridge/BridgeWidget/bridge-widget-script.stories.js.map +1 -1
  57. package/dist/esm/stories/Bridge/Swap/SwapWidget.Prefill.stories.js +16 -11
  58. package/dist/esm/stories/Bridge/Swap/SwapWidget.Prefill.stories.js.map +1 -1
  59. package/dist/esm/stories/Bridge/Swap/SwapWidget.stories.js +14 -14
  60. package/dist/esm/stories/Bridge/Swap/SwapWidget.stories.js.map +1 -1
  61. package/dist/esm/stories/BuyWidget.stories.js +6 -4
  62. package/dist/esm/stories/BuyWidget.stories.js.map +1 -1
  63. package/dist/esm/version.js +1 -1
  64. package/dist/esm/version.js.map +1 -1
  65. package/dist/scripts/bridge-widget.d.ts +185 -3
  66. package/dist/scripts/bridge-widget.js +101 -101
  67. package/dist/types/exports/react.d.ts +3 -0
  68. package/dist/types/exports/react.d.ts.map +1 -1
  69. package/dist/types/extensions/erc20/read/getCurrencyMetadata.d.ts.map +1 -1
  70. package/dist/types/react/web/ui/Bridge/BuyWidget.d.ts +5 -1
  71. package/dist/types/react/web/ui/Bridge/BuyWidget.d.ts.map +1 -1
  72. package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts +5 -1
  73. package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts.map +1 -1
  74. package/dist/types/react/web/ui/Bridge/FundWallet.d.ts +15 -5
  75. package/dist/types/react/web/ui/Bridge/FundWallet.d.ts.map +1 -1
  76. package/dist/types/react/web/ui/Bridge/bridge-widget/bridge-widget.d.ts +9 -2
  77. package/dist/types/react/web/ui/Bridge/bridge-widget/bridge-widget.d.ts.map +1 -1
  78. package/dist/types/react/web/ui/Bridge/swap-widget/SearchInput.d.ts +1 -0
  79. package/dist/types/react/web/ui/Bridge/swap-widget/SearchInput.d.ts.map +1 -1
  80. package/dist/types/react/web/ui/Bridge/swap-widget/SwapWidget.d.ts +5 -1
  81. package/dist/types/react/web/ui/Bridge/swap-widget/SwapWidget.d.ts.map +1 -1
  82. package/dist/types/react/web/ui/Bridge/swap-widget/swap-ui.d.ts.map +1 -1
  83. package/dist/types/react/web/ui/components/Modal.d.ts +1 -0
  84. package/dist/types/react/web/ui/components/Modal.d.ts.map +1 -1
  85. package/dist/types/script-exports/bridge-widget-script.d.ts +9 -2
  86. package/dist/types/script-exports/bridge-widget-script.d.ts.map +1 -1
  87. package/dist/types/stories/Bridge/BridgeWidget/bridge-widget-script.stories.d.ts.map +1 -1
  88. package/dist/types/stories/Bridge/Swap/SwapWidget.Prefill.stories.d.ts +0 -3
  89. package/dist/types/stories/Bridge/Swap/SwapWidget.Prefill.stories.d.ts.map +1 -1
  90. package/dist/types/stories/Bridge/Swap/SwapWidget.stories.d.ts.map +1 -1
  91. package/dist/types/stories/BuyWidget.stories.d.ts +0 -3
  92. package/dist/types/stories/BuyWidget.stories.d.ts.map +1 -1
  93. package/dist/types/version.d.ts +1 -1
  94. package/dist/types/version.d.ts.map +1 -1
  95. package/package.json +1 -1
  96. package/src/exports/react.ts +3 -2
  97. package/src/extensions/erc20/read/getCurrencyMetadata.test.ts +39 -0
  98. package/src/extensions/erc20/read/getCurrencyMetadata.ts +34 -7
  99. package/src/extensions/erc7702/account/sessionkey.test.ts +4 -2
  100. package/src/react/web/ui/Bridge/BuyWidget.tsx +34 -8
  101. package/src/react/web/ui/Bridge/CheckoutWidget.tsx +8 -2
  102. package/src/react/web/ui/Bridge/FundWallet.tsx +17 -33
  103. package/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsx +22 -2
  104. package/src/react/web/ui/Bridge/swap-widget/SearchInput.tsx +2 -0
  105. package/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx +8 -2
  106. package/src/react/web/ui/Bridge/swap-widget/select-token-ui.tsx +1 -0
  107. package/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx +1 -0
  108. package/src/react/web/ui/components/Modal.tsx +10 -1
  109. package/src/script-exports/bridge-widget-script.tsx +9 -2
  110. package/src/stories/Bridge/BridgeWidget/bridge-widget-script.stories.tsx +25 -18
  111. package/src/stories/Bridge/Swap/SwapWidget.Prefill.stories.tsx +26 -10
  112. package/src/stories/Bridge/Swap/SwapWidget.stories.tsx +24 -17
  113. package/src/stories/BuyWidget.stories.tsx +8 -4
  114. package/src/version.ts +1 -1
  115. package/src/wallets/in-app/web/lib/in-app-integration.test.ts +2 -1
  116. package/src/wallets/smart/smart-wallet-integration-v07.test.ts +2 -1
  117. package/src/wallets/smart/smart-wallet-integration.test.ts +2 -1
@@ -6,6 +6,7 @@ import { trackPayEvent } from "../../../../analytics/track/pay.js";
6
6
  import type { TokenWithPrices } from "../../../../bridge/index.js";
7
7
  import type { Chain } from "../../../../chains/types.js";
8
8
  import type { ThirdwebClient } from "../../../../client/client.js";
9
+ import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js";
9
10
  import type { SupportedFiatCurrency } from "../../../../pay/convert/type.js";
10
11
  import type { PurchaseData } from "../../../../pay/types.js";
11
12
  import type { Address } from "../../../../utils/address.js";
@@ -28,7 +29,11 @@ import connectLocaleEn from "../ConnectWallet/locale/en.js";
28
29
  import { EmbedContainer } from "../ConnectWallet/Modal/ConnectEmbed.js";
29
30
  import { DynamicHeight } from "../components/DynamicHeight.js";
30
31
  import { ErrorBanner } from "./ErrorBanner.js";
31
- import { FundWallet } from "./FundWallet.js";
32
+ import {
33
+ type AmountSelection,
34
+ FundWallet,
35
+ type SelectedToken,
36
+ } from "./FundWallet.js";
32
37
  import { PaymentDetails } from "./payment-details/PaymentDetails.js";
33
38
  import { PaymentSelection } from "./payment-selection/PaymentSelection.js";
34
39
  import { SuccessScreen } from "./payment-success/SuccessScreen.js";
@@ -158,7 +163,10 @@ export type BuyWidgetProps = {
158
163
  /**
159
164
  * Callback triggered when the purchase is successful.
160
165
  */
161
- onSuccess?: (quote: BuyOrOnrampPrepareResult) => void;
166
+ onSuccess?: (data: {
167
+ quote: BuyOrOnrampPrepareResult;
168
+ statuses: CompletedStatusResult[];
169
+ }) => void;
162
170
 
163
171
  /**
164
172
  * Callback triggered when the purchase encounters an error.
@@ -454,6 +462,22 @@ function BridgeWidgetContent(
454
462
  [props.onCancel],
455
463
  );
456
464
 
465
+ const [amountSelection, setAmountSelection] = useState<AmountSelection>({
466
+ type: "token",
467
+ value: props.amount ?? "",
468
+ });
469
+
470
+ const [selectedToken, setSelectedToken] = useState<SelectedToken>(() => {
471
+ if (!props.chain?.id) {
472
+ return undefined;
473
+ }
474
+
475
+ return {
476
+ chainId: props.chain.id,
477
+ tokenAddress: props.tokenAddress || NATIVE_TOKEN_ADDRESS,
478
+ };
479
+ });
480
+
457
481
  if (screen.id === "1:buy-ui" || !activeWalletInfo) {
458
482
  return (
459
483
  <FundWallet
@@ -479,11 +503,10 @@ function BridgeWidgetContent(
479
503
  }}
480
504
  buttonLabel={props.buttonLabel}
481
505
  currency={props.currency}
482
- initialSelection={{
483
- tokenAddress: props.tokenAddress,
484
- chainId: props.chain?.id,
485
- amount: props.amount,
486
- }}
506
+ selectedToken={selectedToken}
507
+ setSelectedToken={setSelectedToken}
508
+ amountSelection={amountSelection}
509
+ setAmountSelection={setAmountSelection}
487
510
  />
488
511
  );
489
512
  }
@@ -616,7 +639,10 @@ function BridgeWidgetContent(
616
639
  screen.preparedQuote.type === "buy" ||
617
640
  screen.preparedQuote.type === "onramp"
618
641
  ) {
619
- props.onSuccess?.(screen.preparedQuote);
642
+ props.onSuccess?.({
643
+ quote: screen.preparedQuote,
644
+ statuses: completedStatuses,
645
+ });
620
646
  }
621
647
  setScreen({
622
648
  id: "6:success",
@@ -170,7 +170,10 @@ export type CheckoutWidgetProps = {
170
170
  /**
171
171
  * Callback triggered when the purchase is successful.
172
172
  */
173
- onSuccess?: (quote: BridgePrepareResult) => void;
173
+ onSuccess?: (data: {
174
+ quote: BridgePrepareResult;
175
+ statuses: CompletedStatusResult[];
176
+ }) => void;
174
177
 
175
178
  /**
176
179
  * Callback triggered when the purchase encounters an error.
@@ -660,7 +663,10 @@ function CheckoutWidgetContent(
660
663
  handleCancel(screen.preparedQuote);
661
664
  }}
662
665
  onComplete={(completedStatuses) => {
663
- props.onSuccess?.(screen.preparedQuote);
666
+ props.onSuccess?.({
667
+ quote: screen.preparedQuote,
668
+ statuses: completedStatuses,
669
+ });
664
670
  setScreen({
665
671
  id: "6:success",
666
672
  preparedQuote: screen.preparedQuote,
@@ -4,7 +4,6 @@ import { ArrowDownIcon } from "@radix-ui/react-icons";
4
4
  import { useState } from "react";
5
5
  import type { TokenWithPrices } from "../../../../bridge/types/Token.js";
6
6
  import type { ThirdwebClient } from "../../../../client/client.js";
7
- import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js";
8
7
  import {
9
8
  getFiatSymbol,
10
9
  type SupportedFiatCurrency,
@@ -86,11 +85,10 @@ type FundWalletProps = {
86
85
  */
87
86
  showThirdwebBranding: boolean;
88
87
 
89
- initialSelection: {
90
- tokenAddress: string | undefined;
91
- chainId: number | undefined;
92
- amount: string | undefined;
93
- };
88
+ selectedToken: SelectedToken | undefined;
89
+ setSelectedToken: (token: SelectedToken | undefined) => void;
90
+ amountSelection: AmountSelection;
91
+ setAmountSelection: (amountSelection: AmountSelection) => void;
94
92
 
95
93
  /**
96
94
  * The currency to use for the payment.
@@ -116,14 +114,14 @@ type FundWalletProps = {
116
114
  };
117
115
  };
118
116
 
119
- type SelectedToken =
117
+ export type SelectedToken =
120
118
  | {
121
119
  chainId: number;
122
120
  tokenAddress: string;
123
121
  }
124
122
  | undefined;
125
123
 
126
- type AmountSelection =
124
+ export type AmountSelection =
127
125
  | {
128
126
  type: "usd";
129
127
  value: string;
@@ -134,10 +132,6 @@ type AmountSelection =
134
132
  };
135
133
 
136
134
  export function FundWallet(props: FundWalletProps) {
137
- const [amountSelection, setAmountSelection] = useState<AmountSelection>({
138
- type: "token",
139
- value: props.initialSelection.amount ?? "",
140
- });
141
135
  const theme = useCustomTheme();
142
136
  const activeWalletInfo = useActiveWalletInfo();
143
137
  const receiver =
@@ -154,20 +148,9 @@ export function FundWallet(props: FundWalletProps) {
154
148
  checksumAddress(activeWalletInfo?.activeAccount?.address)
155
149
  : true);
156
150
 
157
- const [selectedToken, setSelectedToken] = useState<SelectedToken>(() => {
158
- if (!props.initialSelection.chainId) {
159
- return undefined;
160
- }
161
-
162
- return {
163
- chainId: props.initialSelection.chainId,
164
- tokenAddress: props.initialSelection.tokenAddress || NATIVE_TOKEN_ADDRESS,
165
- };
166
- });
167
-
168
151
  const tokenQuery = useTokenQuery({
169
- tokenAddress: selectedToken?.tokenAddress,
170
- chainId: selectedToken?.chainId,
152
+ tokenAddress: props.selectedToken?.tokenAddress,
153
+ chainId: props.selectedToken?.chainId,
171
154
  client: props.client,
172
155
  });
173
156
 
@@ -175,8 +158,8 @@ export function FundWallet(props: FundWalletProps) {
175
158
  tokenQuery.data?.type === "success" ? tokenQuery.data.token : undefined;
176
159
 
177
160
  const tokenBalanceQuery = useTokenBalance({
178
- chainId: selectedToken?.chainId,
179
- tokenAddress: selectedToken?.tokenAddress,
161
+ chainId: props.selectedToken?.chainId,
162
+ tokenAddress: props.selectedToken?.tokenAddress,
180
163
  client: props.client,
181
164
  walletAddress: activeWalletInfo?.activeAccount?.address,
182
165
  });
@@ -222,14 +205,15 @@ export function FundWallet(props: FundWalletProps) {
222
205
  transform: "none",
223
206
  }}
224
207
  setOpen={(v) => setIsTokenSelectionOpen(v)}
208
+ autoFocusCrossIcon={false}
225
209
  >
226
210
  <SelectToken
227
211
  activeWalletInfo={activeWalletInfo}
228
212
  onClose={() => setIsTokenSelectionOpen(false)}
229
213
  client={props.client}
230
- selectedToken={selectedToken}
214
+ selectedToken={props.selectedToken}
231
215
  setSelectedToken={(token) => {
232
- setSelectedToken(token);
216
+ props.setSelectedToken(token);
233
217
  setIsTokenSelectionOpen(false);
234
218
  }}
235
219
  />
@@ -240,11 +224,11 @@ export function FundWallet(props: FundWalletProps) {
240
224
  <TokenSection
241
225
  title={actionLabel}
242
226
  presetOptions={props.presetOptions}
243
- amountSelection={amountSelection}
244
- setAmount={setAmountSelection}
227
+ amountSelection={props.amountSelection}
228
+ setAmount={props.setAmountSelection}
245
229
  activeWalletInfo={activeWalletInfo}
246
230
  selectedToken={
247
- selectedToken
231
+ props.selectedToken
248
232
  ? {
249
233
  data:
250
234
  tokenQuery.data?.type === "success"
@@ -310,7 +294,7 @@ export function FundWallet(props: FundWalletProps) {
310
294
 
311
295
  const fiatPricePerToken = destinationToken.prices[props.currency];
312
296
  const { tokenValue } = getAmounts(
313
- amountSelection,
297
+ props.amountSelection,
314
298
  fiatPricePerToken,
315
299
  );
316
300
 
@@ -1,4 +1,6 @@
1
+ import { useQuery } from "@tanstack/react-query";
1
2
  import { useState } from "react";
3
+ import { trackPayEvent } from "../../../../../analytics/track/pay.js";
2
4
  import { defineChain } from "../../../../../chains/utils.js";
3
5
  import type { ThirdwebClient } from "../../../../../client/client.js";
4
6
  import type { SupportedFiatCurrency } from "../../../../../pay/convert/type.js";
@@ -13,6 +15,7 @@ import {
13
15
  spacing,
14
16
  type Theme,
15
17
  } from "../../../../core/design-system/index.js";
18
+ import type { CompletedStatusResult } from "../../../../core/hooks/useStepExecutor.js";
16
19
  import { EmbedContainer } from "../../ConnectWallet/Modal/ConnectEmbed.js";
17
20
  import { Container } from "../../components/basic.js";
18
21
  import { Button } from "../../components/buttons.js";
@@ -82,7 +85,10 @@ export type BridgeWidgetProps = {
82
85
  /** Optional style overrides applied to the Swap tab content container. */
83
86
  style?: React.CSSProperties;
84
87
  /** Callback invoked when a swap is successful. */
85
- onSuccess?: (quote: SwapPreparedQuote) => void;
88
+ onSuccess?: (data: {
89
+ quote: SwapPreparedQuote;
90
+ statuses: CompletedStatusResult[];
91
+ }) => void;
86
92
  /** Callback invoked when an error occurs during swapping. */
87
93
  onError?: (error: Error, quote: SwapPreparedQuote) => void;
88
94
  /** Callback invoked when the user cancels the swap. */
@@ -172,7 +178,10 @@ export type BridgeWidgetProps = {
172
178
  quote: BuyOrOnrampPrepareResult | undefined,
173
179
  ) => void;
174
180
  /** Callback triggered when the purchase is successful. */
175
- onSuccess?: (quote: BuyOrOnrampPrepareResult) => void;
181
+ onSuccess?: (data: {
182
+ quote: BuyOrOnrampPrepareResult;
183
+ statuses: CompletedStatusResult[];
184
+ }) => void;
176
185
  /** Optional class name applied to the Buy tab content container. */
177
186
  className?: string;
178
187
  /** The user's ISO 3166 alpha-2 country code. Used to determine onramp provider support. */
@@ -242,6 +251,17 @@ export type BridgeWidgetProps = {
242
251
  export function BridgeWidget(props: BridgeWidgetProps) {
243
252
  const [tab, setTab] = useState<"swap" | "buy">("swap");
244
253
 
254
+ useQuery({
255
+ queryFn: () => {
256
+ trackPayEvent({
257
+ client: props.client,
258
+ event: "ub:ui:bridge_widget:render",
259
+ });
260
+ return true;
261
+ },
262
+ queryKey: ["bridge_widget:render"],
263
+ });
264
+
245
265
  return (
246
266
  <CustomThemeProvider theme={props.theme}>
247
267
  <EmbedContainer
@@ -11,6 +11,7 @@ export function SearchInput(props: {
11
11
  value: string;
12
12
  onChange: (value: string) => void;
13
13
  placeholder: string;
14
+ autoFocus?: boolean;
14
15
  }) {
15
16
  return (
16
17
  <div
@@ -41,6 +42,7 @@ export function SearchInput(props: {
41
42
  paddingLeft: "44px",
42
43
  }}
43
44
  onChange={(e) => props.onChange(e.target.value)}
45
+ autoFocus={props.autoFocus}
44
46
  />
45
47
  </div>
46
48
  );
@@ -145,7 +145,10 @@ export type SwapWidgetProps = {
145
145
  /**
146
146
  * Callback to be called when the swap is successful.
147
147
  */
148
- onSuccess?: (quote: SwapPreparedQuote) => void;
148
+ onSuccess?: (data: {
149
+ quote: SwapPreparedQuote;
150
+ statuses: CompletedStatusResult[];
151
+ }) => void;
149
152
  /**
150
153
  * Callback to be called when user encounters an error when swapping.
151
154
  */
@@ -465,7 +468,10 @@ function SwapWidgetContent(
465
468
  }}
466
469
  onCancel={() => props.onCancel?.(screen.preparedQuote)}
467
470
  onComplete={(completedStatuses) => {
468
- props.onSuccess?.(screen.preparedQuote);
471
+ props.onSuccess?.({
472
+ quote: screen.preparedQuote,
473
+ statuses: completedStatuses,
474
+ });
469
475
  setScreen({
470
476
  ...screen,
471
477
  id: "4:success",
@@ -496,6 +496,7 @@ function TokenSelectionScreen(props: {
496
496
  value={props.search}
497
497
  onChange={props.setSearch}
498
498
  placeholder="Search by token or address"
499
+ autoFocus={!props.isMobile}
499
500
  />
500
501
  </Container>
501
502
 
@@ -204,6 +204,7 @@ export function SwapUI(props: SwapUIProps) {
204
204
  <Container p="md">
205
205
  <Modal
206
206
  hide={false}
207
+ autoFocusCrossIcon={false}
207
208
  className="tw-modal__swap-widget"
208
209
  size={isMobile ? "compact" : "wide"}
209
210
  title="Select Token"
@@ -41,6 +41,7 @@ export const Modal: React.FC<{
41
41
  title: string;
42
42
  hide?: boolean;
43
43
  crossContainerStyles?: React.CSSProperties;
44
+ autoFocusCrossIcon?: boolean;
44
45
  }> = (props) => {
45
46
  const [open, setOpen] = useState(props.open);
46
47
  const contentRef = useRef<HTMLDivElement>(null);
@@ -143,7 +144,15 @@ export const Modal: React.FC<{
143
144
  }}
144
145
  >
145
146
  <Dialog.Close asChild>
146
- <IconButton aria-label="Close" autoFocus type="button">
147
+ <IconButton
148
+ aria-label="Close"
149
+ autoFocus={
150
+ props.autoFocusCrossIcon === undefined
151
+ ? true
152
+ : props.autoFocusCrossIcon
153
+ }
154
+ type="button"
155
+ >
147
156
  <Cross2Icon
148
157
  height={iconSize.md}
149
158
  style={{
@@ -7,6 +7,7 @@ import {
7
7
  type Theme,
8
8
  type ThemeOverrides,
9
9
  } from "../react/core/design-system/index.js";
10
+ import type { CompletedStatusResult } from "../react/core/hooks/useStepExecutor.js";
10
11
  import type { BuyOrOnrampPrepareResult } from "../react/web/ui/Bridge/BuyWidget.js";
11
12
  import { BridgeWidget } from "../react/web/ui/Bridge/bridge-widget/bridge-widget.js";
12
13
  import type { SwapPreparedQuote } from "../react/web/ui/Bridge/swap-widget/types.js";
@@ -23,7 +24,10 @@ export type BridgeWidgetScriptProps = {
23
24
  swap?: {
24
25
  className?: string;
25
26
  style?: React.CSSProperties;
26
- onSuccess?: (quote: SwapPreparedQuote) => void;
27
+ onSuccess?: (data: {
28
+ quote: SwapPreparedQuote;
29
+ statuses: CompletedStatusResult[];
30
+ }) => void;
27
31
  onError?: (error: Error, quote: SwapPreparedQuote) => void;
28
32
  onCancel?: (quote: SwapPreparedQuote) => void;
29
33
  onDisconnect?: () => void;
@@ -51,7 +55,10 @@ export type BridgeWidgetScriptProps = {
51
55
  error: Error,
52
56
  quote: BuyOrOnrampPrepareResult | undefined,
53
57
  ) => void;
54
- onSuccess?: (quote: BuyOrOnrampPrepareResult) => void;
58
+ onSuccess?: (data: {
59
+ quote: BuyOrOnrampPrepareResult;
60
+ statuses: CompletedStatusResult[];
61
+ }) => void;
55
62
  className?: string;
56
63
  country?: string;
57
64
  presetOptions?: [number, number, number];
@@ -1,27 +1,18 @@
1
1
  import type { Meta } from "@storybook/react";
2
- import { BridgeWidgetScript } from "../../../script-exports/bridge-widget-script.js";
2
+ import {
3
+ BridgeWidgetScript,
4
+ type BridgeWidgetScriptProps,
5
+ } from "../../../script-exports/bridge-widget-script.js";
3
6
  import { storyClient } from "../../utils.js";
4
7
 
5
8
  const meta: Meta<typeof BridgeWidgetScript> = {
6
9
  title: "Bridge/BridgeWidgetScript",
7
- parameters: {
8
- layout: "centered",
9
- },
10
- decorators: [
11
- (Story) => {
12
- return (
13
- <div>
14
- <Story />
15
- </div>
16
- );
17
- },
18
- ],
19
10
  };
20
11
  export default meta;
21
12
 
22
13
  export function BasicUsage() {
23
14
  return (
24
- <BridgeWidgetScript
15
+ <Variant
25
16
  clientId={storyClient.clientId}
26
17
  buy={{ chainId: 8453, amount: "0.1" }}
27
18
  />
@@ -30,7 +21,7 @@ export function BasicUsage() {
30
21
 
31
22
  export function LightTheme() {
32
23
  return (
33
- <BridgeWidgetScript
24
+ <Variant
34
25
  clientId={storyClient.clientId}
35
26
  theme="light"
36
27
  buy={{ chainId: 8453, amount: "0.1" }}
@@ -40,7 +31,7 @@ export function LightTheme() {
40
31
 
41
32
  export function CurrencySet() {
42
33
  return (
43
- <BridgeWidgetScript
34
+ <Variant
44
35
  clientId={storyClient.clientId}
45
36
  currency="JPY"
46
37
  buy={{ chainId: 8453, amount: "0.1" }}
@@ -50,7 +41,7 @@ export function CurrencySet() {
50
41
 
51
42
  export function NoThirdwebBranding() {
52
43
  return (
53
- <BridgeWidgetScript
44
+ <Variant
54
45
  clientId={storyClient.clientId}
55
46
  theme="light"
56
47
  buy={{ chainId: 8453, amount: "0.1" }}
@@ -61,7 +52,7 @@ export function NoThirdwebBranding() {
61
52
 
62
53
  export function CustomTheme() {
63
54
  return (
64
- <BridgeWidgetScript
55
+ <Variant
65
56
  clientId={storyClient.clientId}
66
57
  buy={{ chainId: 8453, amount: "0.1" }}
67
58
  theme={{
@@ -77,3 +68,19 @@ export function CustomTheme() {
77
68
  />
78
69
  );
79
70
  }
71
+
72
+ function Variant(props: BridgeWidgetScriptProps) {
73
+ return (
74
+ <div
75
+ style={{
76
+ display: "flex",
77
+ flexDirection: "column",
78
+ gap: "40px",
79
+ alignItems: "center",
80
+ }}
81
+ >
82
+ <BridgeWidgetScript {...props} theme="dark" />
83
+ <BridgeWidgetScript {...props} theme="light" />
84
+ </div>
85
+ );
86
+ }
@@ -1,19 +1,19 @@
1
1
  import type { Meta } from "@storybook/react-vite";
2
2
  import { NATIVE_TOKEN_ADDRESS } from "../../../constants/addresses.js";
3
- import { SwapWidget } from "../../../react/web/ui/Bridge/swap-widget/SwapWidget.js";
3
+ import {
4
+ SwapWidget,
5
+ type SwapWidgetProps,
6
+ } from "../../../react/web/ui/Bridge/swap-widget/SwapWidget.js";
4
7
  import { storyClient } from "../../utils.js";
5
8
 
6
9
  const meta = {
7
- parameters: {
8
- layout: "centered",
9
- },
10
10
  title: "Bridge/Swap/SwapWidget/Prefill",
11
11
  } satisfies Meta<typeof SwapWidget>;
12
12
  export default meta;
13
13
 
14
14
  export function Buy_NativeToken() {
15
15
  return (
16
- <SwapWidget
16
+ <Variant
17
17
  client={storyClient}
18
18
  prefill={{
19
19
  buyToken: {
@@ -26,7 +26,7 @@ export function Buy_NativeToken() {
26
26
 
27
27
  export function Buy_Base_USDC() {
28
28
  return (
29
- <SwapWidget
29
+ <Variant
30
30
  client={storyClient}
31
31
  prefill={{
32
32
  buyToken: {
@@ -40,7 +40,7 @@ export function Buy_Base_USDC() {
40
40
 
41
41
  export function Buy_NativeToken_With_Amount() {
42
42
  return (
43
- <SwapWidget
43
+ <Variant
44
44
  client={storyClient}
45
45
  prefill={{
46
46
  buyToken: {
@@ -55,7 +55,7 @@ export function Buy_NativeToken_With_Amount() {
55
55
 
56
56
  export function Sell_NativeToken() {
57
57
  return (
58
- <SwapWidget
58
+ <Variant
59
59
  client={storyClient}
60
60
  prefill={{
61
61
  sellToken: {
@@ -82,7 +82,7 @@ export function Sell_Base_USDC() {
82
82
 
83
83
  export function Sell_NativeToken_With_Amount() {
84
84
  return (
85
- <SwapWidget
85
+ <Variant
86
86
  client={storyClient}
87
87
  prefill={{
88
88
  sellToken: {
@@ -97,7 +97,7 @@ export function Sell_NativeToken_With_Amount() {
97
97
 
98
98
  export function Buy_And_Sell_NativeToken() {
99
99
  return (
100
- <SwapWidget
100
+ <Variant
101
101
  client={storyClient}
102
102
  prefill={{
103
103
  // base native token
@@ -114,3 +114,19 @@ export function Buy_And_Sell_NativeToken() {
114
114
  />
115
115
  );
116
116
  }
117
+
118
+ function Variant(props: SwapWidgetProps) {
119
+ return (
120
+ <div
121
+ style={{
122
+ display: "flex",
123
+ flexDirection: "column",
124
+ gap: "40px",
125
+ alignItems: "center",
126
+ }}
127
+ >
128
+ <SwapWidget {...props} theme="dark" />
129
+ <SwapWidget {...props} theme="light" />
130
+ </div>
131
+ );
132
+ }
@@ -1,22 +1,13 @@
1
1
  import type { Meta } from "@storybook/react";
2
2
  import { lightTheme } from "../../../react/core/design-system/index.js";
3
- import { SwapWidget } from "../../../react/web/ui/Bridge/swap-widget/SwapWidget.js";
3
+ import {
4
+ SwapWidget,
5
+ type SwapWidgetProps,
6
+ } from "../../../react/web/ui/Bridge/swap-widget/SwapWidget.js";
4
7
  import { storyClient } from "../../utils.js";
5
8
 
6
9
  const meta: Meta<typeof SwapWidget> = {
7
- parameters: {
8
- layout: "centered",
9
- },
10
10
  title: "Bridge/Swap/SwapWidget",
11
- decorators: [
12
- (Story) => {
13
- return (
14
- <div>
15
- <Story />
16
- </div>
17
- );
18
- },
19
- ],
20
11
  };
21
12
  export default meta;
22
13
 
@@ -26,7 +17,7 @@ export function BasicUsage() {
26
17
 
27
18
  export function CurrencySet() {
28
19
  return (
29
- <SwapWidget
20
+ <Variant
30
21
  client={storyClient}
31
22
  currency="JPY"
32
23
  persistTokenSelections={false}
@@ -36,7 +27,7 @@ export function CurrencySet() {
36
27
 
37
28
  export function LightMode() {
38
29
  return (
39
- <SwapWidget
30
+ <Variant
40
31
  client={storyClient}
41
32
  currency="JPY"
42
33
  theme="light"
@@ -47,7 +38,7 @@ export function LightMode() {
47
38
 
48
39
  export function NoThirdwebBranding() {
49
40
  return (
50
- <SwapWidget
41
+ <Variant
51
42
  client={storyClient}
52
43
  currency="JPY"
53
44
  showThirdwebBranding={false}
@@ -58,7 +49,7 @@ export function NoThirdwebBranding() {
58
49
 
59
50
  export function CustomTheme() {
60
51
  return (
61
- <SwapWidget
52
+ <Variant
62
53
  client={storyClient}
63
54
  currency="JPY"
64
55
  persistTokenSelections={false}
@@ -74,3 +65,19 @@ export function CustomTheme() {
74
65
  />
75
66
  );
76
67
  }
68
+
69
+ function Variant(props: SwapWidgetProps) {
70
+ return (
71
+ <div
72
+ style={{
73
+ display: "flex",
74
+ flexDirection: "column",
75
+ gap: "40px",
76
+ alignItems: "center",
77
+ }}
78
+ >
79
+ <SwapWidget {...props} theme="dark" />
80
+ <SwapWidget {...props} theme="light" />
81
+ </div>
82
+ );
83
+ }
@@ -9,9 +9,6 @@ import {
9
9
  import { storyClient } from "./utils.js";
10
10
 
11
11
  const meta = {
12
- parameters: {
13
- layout: "centered",
14
- },
15
12
  title: "Bridge/Buy/BuyWidget",
16
13
  } satisfies Meta<typeof BuyWidget>;
17
14
  export default meta;
@@ -143,7 +140,14 @@ export function LargeAmount() {
143
140
 
144
141
  function Variant(props: BuyWidgetProps) {
145
142
  return (
146
- <div style={{ display: "flex", flexDirection: "column", gap: "40px" }}>
143
+ <div
144
+ style={{
145
+ display: "flex",
146
+ flexDirection: "column",
147
+ gap: "40px",
148
+ alignItems: "center",
149
+ }}
150
+ >
147
151
  <BuyWidget {...props} theme="dark" />
148
152
  <BuyWidget {...props} theme="light" />
149
153
  </div>