Skip to content

Commit 772eb0c

Browse files
[SDK] Handle different fiat currencies in payment widgets (#7578)
1 parent 5c6dd87 commit 772eb0c

File tree

29 files changed

+269
-107
lines changed

29 files changed

+269
-107
lines changed

.changeset/ready-loops-search.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+
Handle different fiat currencies in payment widgets

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function Example() {
7373
<${componentName}
7474
client={client}
7575
chain={defineChain(${options.payOptions.buyTokenChain.id})}
76-
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}"` : ""}${options.payOptions.paymentMethods && options.payOptions.paymentMethods.length > 0 ? `\n\t paymentMethods={${JSON.stringify(options.payOptions.paymentMethods)}}` : ""}${
76+
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}"` : ""}${options.payOptions.paymentMethods && options.payOptions.paymentMethods.length > 0 ? `\n\t paymentMethods={${JSON.stringify(options.payOptions.paymentMethods)}}` : ""}${options.payOptions.currency ? `\n\t currency="${options.payOptions.currency}"` : ""}${
7777
options.payOptions.widget === "transaction"
7878
? `\n\t transaction={claimTo({
7979
contract: nftContract,

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,34 @@ import type { Chain } from "thirdweb/chains";
22
import type { ThemeOverrides } from "thirdweb/react";
33
import type { Address } from "thirdweb/utils";
44

5+
const CURRENCIES = [
6+
"USD",
7+
"EUR",
8+
"GBP",
9+
"JPY",
10+
"KRW",
11+
"CNY",
12+
"INR",
13+
"NOK",
14+
"SEK",
15+
"CHF",
16+
"AUD",
17+
"CAD",
18+
"NZD",
19+
"MXN",
20+
"BRL",
21+
"CLP",
22+
"CZK",
23+
"DKK",
24+
"HKD",
25+
"HUF",
26+
"IDR",
27+
"ILS",
28+
"ISK",
29+
] as const;
30+
31+
type SupportedFiatCurrency = (typeof CURRENCIES)[number] | (string & {});
32+
533
export type BridgeComponentsPlaygroundOptions = {
634
theme: {
735
type: "dark" | "light";
@@ -26,6 +54,8 @@ export type BridgeComponentsPlaygroundOptions = {
2654

2755
paymentMethods: ("crypto" | "card")[];
2856

57+
currency?: SupportedFiatCurrency;
58+
2959
showThirdwebBranding: boolean;
3060
};
3161
};

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ import { CustomRadioGroup } from "@/components/ui/CustomRadioGroup";
1717
import { Checkbox } from "@/components/ui/checkbox";
1818
import { Input } from "@/components/ui/input";
1919
import { Label } from "@/components/ui/label";
20+
import {
21+
Select,
22+
SelectContent,
23+
SelectItem,
24+
SelectTrigger,
25+
SelectValue,
26+
} from "@/components/ui/select";
2027
import { TokenSelector } from "@/components/ui/TokenSelector";
2128
import { THIRDWEB_CLIENT } from "@/lib/client";
2229
import type { TokenMetadata } from "@/lib/types";
@@ -134,6 +141,51 @@ export function LeftSection(props: {
134141
/>
135142
</section>
136143

144+
<section className="flex flex-col gap-3">
145+
<Label htmlFor="currency">Display Currency</Label>
146+
<Select
147+
value={payOptions.currency || "USD"}
148+
onValueChange={(value) => {
149+
setOptions((v) => ({
150+
...v,
151+
payOptions: {
152+
...v.payOptions,
153+
currency: value,
154+
},
155+
}));
156+
}}
157+
>
158+
<SelectTrigger>
159+
<SelectValue placeholder="Select currency" />
160+
</SelectTrigger>
161+
<SelectContent>
162+
<SelectItem value="USD">USD - US Dollar</SelectItem>
163+
<SelectItem value="EUR">EUR - Euro</SelectItem>
164+
<SelectItem value="GBP">GBP - British Pound</SelectItem>
165+
<SelectItem value="JPY">JPY - Japanese Yen</SelectItem>
166+
<SelectItem value="KRW">KRW - Korean Won</SelectItem>
167+
<SelectItem value="CNY">CNY - Chinese Yuan</SelectItem>
168+
<SelectItem value="INR">INR - Indian Rupee</SelectItem>
169+
<SelectItem value="NOK">NOK - Norwegian Krone</SelectItem>
170+
<SelectItem value="SEK">SEK - Swedish Krona</SelectItem>
171+
<SelectItem value="CHF">CHF - Swiss Franc</SelectItem>
172+
<SelectItem value="AUD">AUD - Australian Dollar</SelectItem>
173+
<SelectItem value="CAD">CAD - Canadian Dollar</SelectItem>
174+
<SelectItem value="NZD">NZD - New Zealand Dollar</SelectItem>
175+
<SelectItem value="MXN">MXN - Mexican Peso</SelectItem>
176+
<SelectItem value="BRL">BRL - Brazilian Real</SelectItem>
177+
<SelectItem value="CLP">CLP - Chilean Peso</SelectItem>
178+
<SelectItem value="CZK">CZK - Czech Koruna</SelectItem>
179+
<SelectItem value="DKK">DKK - Danish Krone</SelectItem>
180+
<SelectItem value="HKD">HKD - Hong Kong Dollar</SelectItem>
181+
<SelectItem value="HUF">HUF - Hungarian Forint</SelectItem>
182+
<SelectItem value="IDR">IDR - Indonesian Rupiah</SelectItem>
183+
<SelectItem value="ILS">ILS - Israeli Shekel</SelectItem>
184+
<SelectItem value="ISK">ISK - Icelandic Krona</SelectItem>
185+
</SelectContent>
186+
</Select>
187+
</section>
188+
137189
{/* Shared Chain and Token Selection - Always visible for Buy and Checkout modes */}
138190
{(!payOptions.widget ||
139191
payOptions.widget === "buy" ||

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export function RightSection(props: {
6464
theme={themeObj}
6565
title={props.options.payOptions.title}
6666
tokenAddress={props.options.payOptions.buyTokenAddress}
67+
currency={props.options.payOptions.currency}
6768
showThirdwebBranding={props.options.payOptions.showThirdwebBranding}
6869
/>
6970
);
@@ -88,6 +89,7 @@ export function RightSection(props: {
8889
seller={props.options.payOptions.sellerAddress}
8990
theme={themeObj}
9091
tokenAddress={props.options.payOptions.buyTokenAddress}
92+
currency={props.options.payOptions.currency}
9193
showThirdwebBranding={props.options.payOptions.showThirdwebBranding}
9294
/>
9395
);
@@ -108,6 +110,7 @@ export function RightSection(props: {
108110
to: account?.address || "",
109111
tokenId: 2n,
110112
})}
113+
currency={props.options.payOptions.currency}
111114
showThirdwebBranding={props.options.payOptions.showThirdwebBranding}
112115
/>
113116
);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const defaultConnectOptions: BridgeComponentsPlaygroundOptions = {
1818
title: "",
1919
transactionData: "",
2020
widget: "buy",
21+
currency: "USD",
2122
showThirdwebBranding: true,
2223
},
2324
theme: {

packages/thirdweb/src/bridge/types/Token.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ export type Token = {
77
symbol: string;
88
name: string;
99
iconUri?: string;
10-
priceUsd: number;
10+
prices: Record<string, number>;
1111
};

packages/thirdweb/src/pay/buyWithCrypto/getQuote.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,14 @@ export async function getBuyWithCryptoQuote(
300300
Number(
301301
Value.format(quote.originAmount, firstStep.originToken.decimals),
302302
) *
303-
firstStep.originToken.priceUsd *
303+
(firstStep.originToken.prices["USD"] || 0) *
304304
100,
305305
amountWei: quote.originAmount.toString(),
306306
token: {
307307
chainId: firstStep.originToken.chainId,
308308
decimals: firstStep.originToken.decimals,
309309
name: firstStep.originToken.name,
310-
priceUSDCents: firstStep.originToken.priceUsd * 100,
310+
priceUSDCents: (firstStep.originToken.prices["USD"] || 0) * 100,
311311
symbol: firstStep.originToken.symbol,
312312
tokenAddress: firstStep.originToken.address,
313313
},
@@ -323,7 +323,7 @@ export async function getBuyWithCryptoQuote(
323323
chainId: firstStep.originToken.chainId,
324324
decimals: firstStep.originToken.decimals,
325325
name: firstStep.originToken.name,
326-
priceUSDCents: firstStep.originToken.priceUsd * 100,
326+
priceUSDCents: (firstStep.originToken.prices["USD"] || 0) * 100,
327327
symbol: firstStep.originToken.symbol,
328328
tokenAddress: firstStep.originToken.address,
329329
},
@@ -337,7 +337,7 @@ export async function getBuyWithCryptoQuote(
337337
Number(
338338
Value.format(quote.originAmount, firstStep.originToken.decimals),
339339
) *
340-
firstStep.originToken.priceUsd *
340+
(firstStep.originToken.prices["USD"] || 0) *
341341
100,
342342
gasCostUSDCents: 0,
343343
slippageBPS: 0,
@@ -348,7 +348,7 @@ export async function getBuyWithCryptoQuote(
348348
firstStep.destinationToken.decimals,
349349
),
350350
) *
351-
firstStep.destinationToken.priceUsd *
351+
(firstStep.destinationToken.prices["USD"] || 0) *
352352
100,
353353
toAmountUSDCents:
354354
Number(
@@ -357,7 +357,7 @@ export async function getBuyWithCryptoQuote(
357357
firstStep.destinationToken.decimals,
358358
),
359359
) *
360-
firstStep.destinationToken.priceUsd *
360+
(firstStep.destinationToken.prices["USD"] || 0) *
361361
100,
362362
},
363363
fromAddress: quote.intent.sender,
@@ -372,7 +372,7 @@ export async function getBuyWithCryptoQuote(
372372
chainId: firstStep.originToken.chainId,
373373
decimals: firstStep.originToken.decimals,
374374
name: firstStep.originToken.name,
375-
priceUSDCents: firstStep.originToken.priceUsd * 100,
375+
priceUSDCents: (firstStep.originToken.prices["USD"] || 0) * 100,
376376
symbol: firstStep.originToken.symbol,
377377
tokenAddress: firstStep.originToken.address,
378378
},
@@ -395,7 +395,7 @@ export async function getBuyWithCryptoQuote(
395395
chainId: firstStep.destinationToken.chainId,
396396
decimals: firstStep.destinationToken.decimals,
397397
name: firstStep.destinationToken.name,
398-
priceUSDCents: firstStep.destinationToken.priceUsd * 100,
398+
priceUSDCents: (firstStep.destinationToken.prices["USD"] || 0) * 100,
399399
symbol: firstStep.destinationToken.symbol,
400400
tokenAddress: firstStep.destinationToken.address,
401401
},

packages/thirdweb/src/pay/buyWithCrypto/getTransfer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,14 @@ export async function getBuyWithCryptoTransfer(
198198
Number(
199199
Value.format(quote.originAmount, firstStep.originToken.decimals),
200200
) *
201-
firstStep.originToken.priceUsd *
201+
(firstStep.originToken.prices["USD"] || 0) *
202202
100,
203203
amountWei: quote.originAmount.toString(),
204204
token: {
205205
chainId: firstStep.originToken.chainId,
206206
decimals: firstStep.originToken.decimals,
207207
name: firstStep.originToken.name,
208-
priceUSDCents: firstStep.originToken.priceUsd * 100,
208+
priceUSDCents: (firstStep.originToken.prices["USD"] || 0) * 100,
209209
symbol: firstStep.originToken.symbol,
210210
tokenAddress: firstStep.originToken.address,
211211
},
@@ -226,7 +226,7 @@ export async function getBuyWithCryptoTransfer(
226226
firstStep.originToken.decimals,
227227
),
228228
) *
229-
firstStep.originToken.priceUsd *
229+
(firstStep.originToken.prices["USD"] || 0) *
230230
100
231231
: 0,
232232
amountWei:
@@ -237,7 +237,7 @@ export async function getBuyWithCryptoTransfer(
237237
chainId: firstStep.originToken.chainId,
238238
decimals: firstStep.originToken.decimals,
239239
name: firstStep.originToken.name,
240-
priceUSDCents: firstStep.originToken.priceUsd * 100,
240+
priceUSDCents: (firstStep.originToken.prices["USD"] || 0) * 100,
241241
symbol: firstStep.originToken.symbol,
242242
tokenAddress: firstStep.originToken.address,
243243
},

packages/thirdweb/src/pay/buyWithFiat/getQuote.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,12 +367,12 @@ export async function getBuyWithFiatQuote(
367367
decimals: number;
368368
symbol: string;
369369
name: string;
370-
priceUsd: number;
370+
prices: Record<string, number>;
371371
}): PayTokenInfo => ({
372372
chainId: token.chainId,
373373
decimals: token.decimals,
374374
name: token.name,
375-
priceUSDCents: Math.round(token.priceUsd * 100),
375+
priceUSDCents: Math.round((token.prices["USD"] || 0) * 100),
376376
symbol: token.symbol,
377377
tokenAddress: token.address,
378378
});
@@ -408,7 +408,7 @@ export async function getBuyWithFiatQuote(
408408
const onRampTokenObject = {
409409
amount: onRampTokenAmount,
410410
amountUSDCents: Math.round(
411-
Number(onRampTokenAmount) * onRampTokenRaw.priceUsd * 100,
411+
Number(onRampTokenAmount) * (onRampTokenRaw.prices["USD"] || 0) * 100,
412412
),
413413
amountWei: onRampTokenAmountWei.toString(),
414414
token: tokenToPayTokenInfo(onRampTokenRaw),
@@ -434,7 +434,7 @@ export async function getBuyWithFiatQuote(
434434
routingTokenObject = {
435435
amount: routingAmount,
436436
amountUSDCents: Math.round(
437-
Number(routingAmount) * routingTokenRaw.priceUsd * 100,
437+
Number(routingAmount) * (routingTokenRaw.prices["USD"] || 0) * 100,
438438
),
439439
amountWei: routingAmountWei.toString(),
440440
token: tokenToPayTokenInfo(routingTokenRaw),

0 commit comments

Comments
 (0)