Skip to content

Commit 6be9459

Browse files
authored
Refactor: UB widget inputs (#7390)
1 parent 492c6d0 commit 6be9459

File tree

11 files changed

+52
-90
lines changed

11 files changed

+52
-90
lines changed

.changeset/quick-foxes-raise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Use decimal string for BuyWidget amount

apps/playground-web/src/app/connect/pay/components/CodeGen.tsx

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import { THIRDWEB_CLIENT } from "@/lib/client";
2-
import { useQuery } from "@tanstack/react-query";
31
import { Suspense, lazy } from "react";
4-
import { defineChain, getContract, toUnits } from "thirdweb";
5-
import { getCurrencyMetadata } from "thirdweb/extensions/erc20";
62
import { CodeLoading } from "../../../../components/code/code.client";
73
import type { BridgeComponentsPlaygroundOptions } from "./types";
84

@@ -13,36 +9,11 @@ const CodeClient = lazy(
139
export function CodeGen(props: {
1410
options: BridgeComponentsPlaygroundOptions;
1511
}) {
16-
const { options } = props;
17-
const { data: amount } = useQuery({
18-
queryKey: [
19-
"amount",
20-
options.payOptions.buyTokenAmount,
21-
options.payOptions.buyTokenChain,
22-
options.payOptions.buyTokenAddress,
23-
],
24-
queryFn: async () => {
25-
if (!options.payOptions.buyTokenAmount) {
26-
return;
27-
}
28-
const contract = getContract({
29-
chain: defineChain(options.payOptions.buyTokenChain.id),
30-
address: options.payOptions.buyTokenAddress,
31-
client: THIRDWEB_CLIENT,
32-
});
33-
const token = await getCurrencyMetadata({
34-
contract,
35-
});
36-
37-
return toUnits(options.payOptions.buyTokenAmount, token.decimals);
38-
},
39-
});
40-
4112
return (
4213
<div className="flex w-full grow flex-col">
4314
<Suspense fallback={<CodeLoading />}>
4415
<CodeClient
45-
code={getCode(props.options, amount)}
16+
code={getCode(props.options)}
4617
lang="tsx"
4718
loader={<CodeLoading />}
4819
className="grow"
@@ -52,7 +23,7 @@ export function CodeGen(props: {
5223
);
5324
}
5425

55-
function getCode(options: BridgeComponentsPlaygroundOptions, amount?: bigint) {
26+
function getCode(options: BridgeComponentsPlaygroundOptions) {
5627
const imports = {
5728
react: ["PayEmbed"] as string[],
5829
thirdweb: [] as string[],
@@ -104,7 +75,7 @@ function Example() {
10475
<${componentName}
10576
client={client}
10677
chain={defineChain(${options.payOptions.buyTokenChain.id})}
107-
amount={${amount}n}${options.payOptions.buyTokenAddress ? `\n\t token="${options.payOptions.buyTokenAddress}"` : ""}${options.payOptions.sellerAddress ? `\n\t seller="${options.payOptions.sellerAddress}"` : ""}${options.payOptions.title ? `\n\t ${options.payOptions.widget === "checkout" ? "name" : "title"}="${options.payOptions.title}"` : ""}${options.payOptions.image ? `\n\t image="${options.payOptions.image}"` : ""}${options.payOptions.description ? `\n\t description="${options.payOptions.description}"` : ""}${
78+
amount="${options.payOptions.buyTokenAmount}"${options.payOptions.buyTokenAddress ? `\n\t token="${options.payOptions.buyTokenAddress}"` : ""}${options.payOptions.sellerAddress ? `\n\t seller="${options.payOptions.sellerAddress}"` : ""}${options.payOptions.title ? `\n\t ${options.payOptions.widget === "checkout" ? "name" : "title"}="${options.payOptions.title}"` : ""}${options.payOptions.image ? `\n\t image="${options.payOptions.image}"` : ""}${options.payOptions.description ? `\n\t description="${options.payOptions.description}"` : ""}${
10879
options.payOptions.widget === "transaction"
10980
? `\n\t transaction={claimTo({
11081
contract: nftContract,

apps/playground-web/src/app/connect/pay/components/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type BridgeComponentsPlaygroundOptions = {
1313
image: string | undefined;
1414
description: string | undefined;
1515

16-
buyTokenAddress: Address;
16+
buyTokenAddress?: Address;
1717
buyTokenAmount: string;
1818
buyTokenChain: Chain;
1919

apps/playground-web/src/app/connect/pay/embed/RightSection.tsx

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
"use client";
2-
import { useQuery } from "@tanstack/react-query";
32
import { usePathname } from "next/navigation";
43
import { useState } from "react";
5-
import { getContract, toUnits } from "thirdweb";
4+
import { getContract } from "thirdweb";
65
import { base } from "thirdweb/chains";
7-
import { getCurrencyMetadata } from "thirdweb/extensions/erc20";
86
import { claimTo } from "thirdweb/extensions/erc1155";
97
import {
108
BuyWidget,
@@ -43,18 +41,6 @@ export function RightSection(props: {
4341
}
4442

4543
const account = useActiveAccount();
46-
const { data: tokenData } = useQuery({
47-
queryKey: ["token", props.options.payOptions.buyTokenAddress],
48-
queryFn: () =>
49-
getCurrencyMetadata({
50-
contract: getContract({
51-
address: props.options.payOptions.buyTokenAddress,
52-
chain: props.options.payOptions.buyTokenChain,
53-
client: THIRDWEB_CLIENT,
54-
}),
55-
}),
56-
enabled: !!props.options.payOptions.buyTokenAddress,
57-
});
5844

5945
const themeObj =
6046
props.options.theme.type === "dark"
@@ -74,10 +60,7 @@ export function RightSection(props: {
7460
title={props.options.payOptions.title}
7561
tokenAddress={props.options.payOptions.buyTokenAddress}
7662
chain={props.options.payOptions.buyTokenChain}
77-
amount={toUnits(
78-
props.options.payOptions.buyTokenAmount,
79-
tokenData?.decimals || 18,
80-
)}
63+
amount={props.options.payOptions.buyTokenAmount}
8164
/>
8265
);
8366
}
@@ -90,10 +73,7 @@ export function RightSection(props: {
9073
name={props.options.payOptions.title}
9174
tokenAddress={props.options.payOptions.buyTokenAddress}
9275
chain={props.options.payOptions.buyTokenChain}
93-
amount={toUnits(
94-
props.options.payOptions.buyTokenAmount,
95-
tokenData?.decimals || 18,
96-
)}
76+
amount={props.options.payOptions.buyTokenAmount}
9777
seller={props.options.payOptions.sellerAddress}
9878
presetOptions={[1, 2, 3]}
9979
purchaseData={{

apps/playground-web/src/app/connect/pay/embed/page.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"use client";
22
import { use, useState } from "react";
3-
import { NATIVE_TOKEN_ADDRESS } from "thirdweb";
43
import { arbitrum } from "thirdweb/chains";
5-
import { checksumAddress } from "thirdweb/utils";
64
import type { BridgeComponentsPlaygroundOptions } from "../components/types";
75
import { LeftSection } from "./LeftSection";
86
import { RightSection } from "./RightSection";
@@ -19,7 +17,7 @@ const defaultConnectOptions: BridgeComponentsPlaygroundOptions = {
1917
title: "",
2018
image: "",
2119
description: "",
22-
buyTokenAddress: checksumAddress(NATIVE_TOKEN_ADDRESS),
20+
buyTokenAddress: undefined,
2321
buyTokenAmount: "0.002",
2422
buyTokenChain: arbitrum,
2523
sellerAddress: "0x0000000000000000000000000000000000000000",

apps/playground-web/src/components/pay/direct-payment.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
"use client";
2-
import { toUnits } from "thirdweb";
32
import { base } from "thirdweb/chains";
43
import { CheckoutWidget } from "thirdweb/react";
54
import { THIRDWEB_CLIENT } from "../../lib/client";
@@ -11,7 +10,7 @@ export function BuyMerchPreview() {
1110
client={THIRDWEB_CLIENT}
1211
theme="light"
1312
chain={base}
14-
amount={toUnits("2", 6)}
13+
amount={"2"}
1514
tokenAddress="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
1615
seller="0xEb0effdFB4dC5b3d5d3aC6ce29F3ED213E95d675"
1716
feePayer="seller"

apps/playground-web/src/components/pay/transaction-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function PayTransactionPreview() {
4949
tokenId: 2n,
5050
to: account?.address || "",
5151
})}
52-
amount={100n}
52+
amount={"0.1"}
5353
title={nft?.metadata?.name}
5454
description={nft?.metadata?.description}
5555
image={nft?.metadata?.image}

apps/playground-web/src/components/universal-bridge/buy.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { THIRDWEB_CLIENT } from "@/lib/client";
44
import { useTheme } from "next-themes";
5-
import { NATIVE_TOKEN_ADDRESS, toWei } from "thirdweb";
5+
import { NATIVE_TOKEN_ADDRESS } from "thirdweb";
66
import { arbitrum } from "thirdweb/chains";
77
import { BuyWidget } from "thirdweb/react";
88

@@ -18,7 +18,7 @@ export function StyledBuyWidgetPreview() {
1818
title="Get Funds"
1919
tokenAddress={NATIVE_TOKEN_ADDRESS}
2020
chain={arbitrum}
21-
amount={toWei("0.002")}
21+
amount={"0.1"}
2222
/>
2323
</div>
2424
);

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
isAddress,
1313
} from "../../../../utils/address.js";
1414
import { stringify } from "../../../../utils/json.js";
15-
import { toTokens } from "../../../../utils/units.js";
1615
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
1716
import type { SmartWalletOptions } from "../../../../wallets/smart/types.js";
1817
import type { AppMetadata } from "../../../../wallets/types.js";
@@ -112,9 +111,9 @@ export type BuyWidgetProps = {
112111
tokenAddress?: Address;
113112

114113
/**
115-
* The amount to buy **(in wei)**.
114+
* The amount to buy **(as a decimal string)**, e.g. "1.5" for 1.5 tokens.
116115
*/
117-
amount: bigint;
116+
amount: string;
118117

119118
/**
120119
* The title to display in the widget.
@@ -178,12 +177,11 @@ type UIOptionsResult =
178177
*
179178
* ```tsx
180179
* import { ethereum } from "thirdweb/chains";
181-
* import { toWei } from "thirdweb";
182180
*
183181
* <BuyWidget
184182
* client={client}
185183
* chain={ethereum}
186-
* amount={toWei("0.1")}
184+
* amount="0.1"
187185
* />
188186
* ```
189187
*
@@ -195,7 +193,7 @@ type UIOptionsResult =
195193
* <BuyWidget
196194
* client={client}
197195
* chain={ethereum}
198-
* amount={toWei("100")}
196+
* amount="100"
199197
* tokenAddress="0xA0b86a33E6417E4df2057B2d3C6d9F7cc11b0a70"
200198
* />
201199
* ```
@@ -208,7 +206,7 @@ type UIOptionsResult =
208206
* <BuyWidget
209207
* client={client}
210208
* chain={ethereum}
211-
* amount={toWei("0.1")}
209+
* amount="0.1"
212210
* theme={darkTheme({
213211
* colors: {
214212
* modalBg: "red",
@@ -227,7 +225,7 @@ type UIOptionsResult =
227225
* <BuyWidget
228226
* client={client}
229227
* chain={ethereum}
230-
* amount={toWei("0.1")}
228+
* amount="0.1"
231229
* title="Buy ETH"
232230
* />
233231
* ```
@@ -240,7 +238,7 @@ type UIOptionsResult =
240238
* <BuyWidget
241239
* client={client}
242240
* chain={ethereum}
243-
* amount={toWei("0.1")}
241+
* amount="0.1"
244242
* connectOptions={{
245243
* connectModal: {
246244
* size: 'compact',
@@ -279,7 +277,7 @@ export function BuyWidget(props: BuyWidgetProps) {
279277
data: {
280278
mode: "fund_wallet",
281279
destinationToken: ETH,
282-
initialAmount: toTokens(props.amount, ETH.decimals),
280+
initialAmount: props.amount,
283281
},
284282
};
285283
}
@@ -303,7 +301,7 @@ export function BuyWidget(props: BuyWidgetProps) {
303301
data: {
304302
mode: "fund_wallet",
305303
destinationToken: token,
306-
initialAmount: toTokens(props.amount, token.decimals),
304+
initialAmount: props.amount,
307305
metadata: {
308306
title: props.title,
309307
},

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js";
88
import { getToken } from "../../../../pay/convert/get-token.js";
99
import { type Address, checksumAddress } from "../../../../utils/address.js";
1010
import { stringify } from "../../../../utils/json.js";
11-
import { toTokens } from "../../../../utils/units.js";
1211
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
1312
import type { SmartWalletOptions } from "../../../../wallets/smart/types.js";
1413
import type { AppMetadata } from "../../../../wallets/types.js";
@@ -108,9 +107,9 @@ export type CheckoutWidgetProps = {
108107
tokenAddress?: Address;
109108

110109
/**
111-
* The price of the item **(in wei)**.
110+
* The price of the item **(as a decimal string)**, e.g. "1.5" for 1.5 tokens.
112111
*/
113-
amount: bigint;
112+
amount: string;
114113

115114
/**
116115
* The wallet address or ENS funds will be paid to.
@@ -282,7 +281,7 @@ export function CheckoutWidget(props: CheckoutWidgetProps) {
282281
},
283282
paymentInfo: {
284283
token,
285-
amount: toTokens(props.amount, token.decimals),
284+
amount: props.amount,
286285
sellerAddress: props.seller,
287286
feePayer: props.feePayer === "seller" ? "receiver" : "sender", // User is sender, seller is receiver
288287
},

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import type { Token } from "../../../../bridge/index.js";
55
import type { Chain } from "../../../../chains/types.js";
66
import type { ThirdwebClient } from "../../../../client/client.js";
77
import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js";
8+
import { getToken } from "../../../../pay/convert/get-token.js";
89
import {
910
type PreparedTransaction,
1011
prepareTransaction,
1112
} from "../../../../transaction/prepare-transaction.js";
1213
import { type Address, checksumAddress } from "../../../../utils/address.js";
1314
import { stringify } from "../../../../utils/json.js";
15+
import { toUnits } from "../../../../utils/units.js";
1416
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
1517
import type { SmartWalletOptions } from "../../../../wallets/smart/types.js";
1618
import type { AppMetadata } from "../../../../wallets/types.js";
@@ -105,9 +107,9 @@ export type TransactionWidgetProps = {
105107
tokenAddress?: Address;
106108

107109
/**
108-
* The price of the item **(in wei)**.
110+
* The price of the item **(as a decimal string)**, e.g. "1.5" for 1.5 tokens.
109111
*/
110-
amount?: bigint;
112+
amount?: string;
111113

112114
/**
113115
* A title for the transaction.
@@ -196,8 +198,8 @@ type UIOptionsResult =
196198
* to: "0x...",
197199
* chain: ethereum,
198200
* client: client,
199-
* value: toUnits("0.001", 18),
200201
* })}
202+
* amount="0.1"
201203
* />
202204
* ```
203205
*
@@ -276,16 +278,26 @@ export function TransactionWidget(props: TransactionWidgetProps) {
276278
const bridgeDataQuery = useQuery({
277279
queryKey: ["bridgeData", stringify(props)],
278280
queryFn: async (): Promise<UIOptionsResult> => {
281+
let erc20Value = props.transaction.erc20Value;
282+
283+
if (props.amount) {
284+
// Get token decimals for conversion
285+
const tokenAddress = props.tokenAddress || NATIVE_TOKEN_ADDRESS;
286+
const token = await getToken(
287+
props.client,
288+
checksumAddress(tokenAddress),
289+
props.transaction.chain.id,
290+
);
291+
292+
erc20Value = {
293+
amountWei: toUnits(props.amount, token.decimals),
294+
tokenAddress: checksumAddress(tokenAddress),
295+
};
296+
}
297+
279298
const transaction = prepareTransaction({
280299
...props.transaction,
281-
erc20Value: props.amount
282-
? {
283-
amountWei: props.amount,
284-
tokenAddress: checksumAddress(
285-
props.tokenAddress || NATIVE_TOKEN_ADDRESS,
286-
),
287-
}
288-
: props.transaction.erc20Value,
300+
erc20Value,
289301
});
290302

291303
return {

0 commit comments

Comments
 (0)