Skip to content

Commit 00b7ebb

Browse files
committed
updates
1 parent b4a82a3 commit 00b7ebb

File tree

4 files changed

+135
-20
lines changed

4 files changed

+135
-20
lines changed

packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ import type { TokenWithPrices } from "../../../../bridge/index.js";
77
import type { Chain } from "../../../../chains/types.js";
88
import type { ThirdwebClient } from "../../../../client/client.js";
99
import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js";
10+
import { getToken } from "../../../../pay/convert/get-token.js";
1011
import type { SupportedFiatCurrency } from "../../../../pay/convert/type.js";
1112
import type { PurchaseData } from "../../../../pay/types.js";
1213
import type { WaitForReceiptOptions } from "../../../../transaction/actions/wait-for-tx-receipt.js";
13-
import type { PreparedTransaction } from "../../../../transaction/prepare-transaction.js";
14-
import type { Address } from "../../../../utils/address.js";
14+
import {
15+
type PreparedTransaction,
16+
prepareTransaction,
17+
} from "../../../../transaction/prepare-transaction.js";
18+
import { type Address, checksumAddress } from "../../../../utils/address.js";
19+
import { stringify } from "../../../../utils/json.js";
20+
import { toUnits } from "../../../../utils/units.js";
1521
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
1622
import type { SmartWalletOptions } from "../../../../wallets/smart/types.js";
1723
import type { AppMetadata } from "../../../../wallets/types.js";
@@ -38,7 +44,6 @@ import { Spinner } from "../components/Spinner.js";
3844
import { Text } from "../components/text.js";
3945
import { ExecutingTxScreen } from "../TransactionButton/ExecutingScreen.js";
4046
import type { LocaleId } from "../types.js";
41-
import { useTokenQuery } from "./common/token-query.js";
4247
import { ErrorBanner } from "./ErrorBanner.js";
4348
import { PaymentDetails } from "./payment-details/PaymentDetails.js";
4449
import { PaymentSelection } from "./payment-selection/PaymentSelection.js";
@@ -334,6 +339,15 @@ export function TransactionWidget(props: TransactionWidgetProps) {
334339
);
335340
}
336341

342+
type TransactionQueryResult =
343+
| {
344+
transaction: PreparedTransaction;
345+
type: "success";
346+
}
347+
| {
348+
type: "unsupported_token";
349+
};
350+
337351
export function TransactionWidgetContentWrapper(props: TransactionWidgetProps) {
338352
useQuery({
339353
queryFn: () => {
@@ -349,10 +363,49 @@ export function TransactionWidgetContentWrapper(props: TransactionWidgetProps) {
349363
});
350364

351365
const localQuery = useConnectLocale(props.locale || "en_US");
352-
const tokenQuery = useTokenQuery({
353-
tokenAddress: props.tokenAddress,
354-
chainId: props.transaction.chain.id,
355-
client: props.client,
366+
367+
const txQuery = useQuery({
368+
queryFn: async (): Promise<TransactionQueryResult> => {
369+
let erc20Value = props.transaction.erc20Value;
370+
371+
if (props.amount) {
372+
// Get token decimals for conversion
373+
const tokenAddress = props.tokenAddress || NATIVE_TOKEN_ADDRESS;
374+
const token = await getToken(
375+
props.client,
376+
checksumAddress(tokenAddress),
377+
props.transaction.chain.id,
378+
).catch((e) => {
379+
if (e instanceof Error && e.message.includes("not supported")) {
380+
return null;
381+
}
382+
throw e;
383+
});
384+
if (!token) {
385+
return {
386+
type: "unsupported_token",
387+
};
388+
}
389+
390+
erc20Value = {
391+
amountWei: toUnits(props.amount, token.decimals),
392+
tokenAddress: checksumAddress(tokenAddress),
393+
};
394+
}
395+
396+
const transaction = prepareTransaction({
397+
...props.transaction,
398+
erc20Value,
399+
});
400+
401+
return {
402+
transaction,
403+
type: "success",
404+
};
405+
},
406+
407+
queryKey: ["transaction-query", stringify(props)],
408+
retry: 1,
356409
});
357410

358411
// if branding is disabled for widget, disable it for connect options too
@@ -369,7 +422,7 @@ export function TransactionWidgetContentWrapper(props: TransactionWidgetProps) {
369422
return props.connectOptions;
370423
}, [props.connectOptions, props.showThirdwebBranding]);
371424

372-
if (tokenQuery.isPending || !localQuery.data) {
425+
if (txQuery.isPending || !localQuery.data) {
373426
return (
374427
<div
375428
style={{
@@ -382,7 +435,7 @@ export function TransactionWidgetContentWrapper(props: TransactionWidgetProps) {
382435
<Spinner color="secondaryText" size="xl" />
383436
</div>
384437
);
385-
} else if (tokenQuery.error) {
438+
} else if (txQuery.error) {
386439
return (
387440
<div
388441
style={{
@@ -396,25 +449,25 @@ export function TransactionWidgetContentWrapper(props: TransactionWidgetProps) {
396449
<AccentFailIcon size={iconSize["3xl"]} />
397450
<Spacer y="lg" />
398451
<Text color="secondaryText" size="md">
399-
{tokenQuery.error.message}
452+
{txQuery.error.message}
400453
</Text>
401454
</div>
402455
);
403-
} else if (tokenQuery.data?.type === "unsupported_token") {
456+
} else if (txQuery.data?.type === "unsupported_token") {
404457
return (
405458
<UnsupportedTokenScreen
406459
chain={props.transaction.chain}
407460
client={props.client}
408461
tokenAddress={props.tokenAddress || NATIVE_TOKEN_ADDRESS}
409462
/>
410463
);
411-
} else if (tokenQuery.data?.type === "success") {
464+
} else if (txQuery.data?.type === "success") {
412465
return (
413466
<TransactionWidgetContent
414467
{...props}
415468
connectOptions={connectOptions}
416469
connectLocale={localQuery.data}
417-
destinationToken={tokenQuery.data.token}
470+
transaction={txQuery.data.transaction}
418471
currency={props.currency || "USD"}
419472
paymentMethods={props.paymentMethods || ["crypto", "card"]}
420473
showThirdwebBranding={
@@ -486,7 +539,6 @@ function TransactionWidgetContent(
486539
"currency" | "showThirdwebBranding" | "paymentMethods"
487540
> & {
488541
connectLocale: ConnectLocale;
489-
destinationToken: TokenWithPrices;
490542
},
491543
) {
492544
const [screen, setScreen] = useState<TransactionWidgetScreen>({

packages/thirdweb/src/stories/Bridge/TransactionPayment.stories.tsx renamed to packages/thirdweb/src/stories/Bridge/TransactionWidget/TransactionPayment.stories.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import type { Meta, StoryObj } from "@storybook/react";
2-
import { TransactionPayment } from "../../react/web/ui/Bridge/TransactionPayment.js";
3-
import { ModalThemeWrapper, storyClient } from "../utils.js";
4-
import { TRANSACTION_UI_OPTIONS } from "./fixtures.js";
2+
import { TransactionPayment } from "../../../react/web/ui/Bridge/TransactionPayment.js";
3+
import { ModalThemeWrapper, storyClient } from "../../utils.js";
4+
import { TRANSACTION_UI_OPTIONS } from "../fixtures.js";
55

66
const meta: Meta<typeof TransactionPayment> = {
77
args: {
88
client: storyClient,
99
onExecuteTransaction: () => {},
1010
onContinue: (_amount, _token, _receiverAddress) => {},
1111
currency: "USD",
12-
...TRANSACTION_UI_OPTIONS.ethTransfer,
1312
},
1413
component: TransactionPayment,
1514
decorators: [
@@ -19,7 +18,7 @@ const meta: Meta<typeof TransactionPayment> = {
1918
</ModalThemeWrapper>
2019
),
2120
],
22-
title: "Bridge/TransactionPayment",
21+
title: "Bridge/Transaction/screens/TransactionPayment",
2322
};
2423

2524
export default meta;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import {
3+
TransactionWidget,
4+
type TransactionWidgetProps,
5+
} from "../../../react/web/ui/Bridge/TransactionWidget.js";
6+
import { storyClient } from "../../utils.js";
7+
import { TRANSACTION_UI_OPTIONS } from "../fixtures.js";
8+
9+
const meta: Meta<typeof StoryVariant> = {
10+
args: {
11+
client: storyClient,
12+
onSuccess: () => {},
13+
onError: () => {},
14+
onCancel: () => {},
15+
currency: "USD",
16+
...TRANSACTION_UI_OPTIONS.ethTransfer,
17+
},
18+
component: StoryVariant,
19+
title: "Bridge/Transaction/TransactionWidget",
20+
};
21+
22+
export default meta;
23+
type Story = StoryObj<typeof meta>;
24+
25+
export const EthereumTransfer: Story = {
26+
args: {
27+
...TRANSACTION_UI_OPTIONS.ethTransfer,
28+
},
29+
};
30+
31+
export const ERC20TokenTransfer: Story = {
32+
args: {
33+
...TRANSACTION_UI_OPTIONS.erc20Transfer,
34+
},
35+
};
36+
37+
export const ContractInteraction: Story = {
38+
args: {
39+
...TRANSACTION_UI_OPTIONS.contractInteraction,
40+
},
41+
};
42+
43+
export const CustomButtonLabel: Story = {
44+
args: {
45+
...TRANSACTION_UI_OPTIONS.customButton,
46+
},
47+
};
48+
49+
function StoryVariant(props: TransactionWidgetProps) {
50+
return (
51+
<div
52+
style={{
53+
display: "flex",
54+
flexDirection: "column",
55+
gap: "40px",
56+
alignItems: "center",
57+
}}
58+
>
59+
<TransactionWidget {...props} theme="dark" />
60+
<TransactionWidget {...props} theme="light" />
61+
</div>
62+
);
63+
}

packages/thirdweb/src/stories/Bridge/fixtures.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,6 @@ const PRODUCT_METADATA = {
680680
},
681681
};
682682

683-
// Type aliases for better type safety
684683
type FundWalletUIOptions = {
685684
destinationToken: TokenWithPrices;
686685
metadata: {
@@ -691,6 +690,7 @@ type FundWalletUIOptions = {
691690
initialAmount: string | undefined;
692691
buttonLabel: string | undefined;
693692
};
693+
694694
type DirectPaymentUIOptions = {
695695
metadata: {
696696
description: string | undefined;
@@ -700,6 +700,7 @@ type DirectPaymentUIOptions = {
700700
paymentInfo: DirectPaymentInfo;
701701
buttonLabel: string | undefined;
702702
};
703+
703704
type TransactionUIOptions = {
704705
metadata: {
705706
description: string | undefined;

0 commit comments

Comments
 (0)