From 1c90623a07edda86acc4b3f01f9d03ba68ff8df7 Mon Sep 17 00:00:00 2001 From: Kien Ngo Date: Thu, 28 Nov 2024 19:32:20 +0700 Subject: [PATCH] update --- .../src/app/connect/ui/page.tsx | 64 ++++ apps/playground-web/src/app/navLinks.ts | 22 ++ apps/playground-web/src/app/page.tsx | 6 + .../headless-ui/account-examples.tsx | 335 ++++++++++++++++++ packages/thirdweb/src/exports/react.ts | 2 +- 5 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 apps/playground-web/src/app/connect/ui/page.tsx create mode 100644 apps/playground-web/src/components/headless-ui/account-examples.tsx diff --git a/apps/playground-web/src/app/connect/ui/page.tsx b/apps/playground-web/src/app/connect/ui/page.tsx new file mode 100644 index 00000000000..cf3bf5e7b78 --- /dev/null +++ b/apps/playground-web/src/app/connect/ui/page.tsx @@ -0,0 +1,64 @@ +import { APIHeader } from "@/components/blocks/APIHeader"; +import { + AccountAddressBasic, + AccountAddressFormat, + AccountBalanceBasic, + AccountBalanceCustomToken, + AccountBalanceFormat, + AccountBalanceUSD, + AccountBalanceUSDFormatted, +} from "@/components/headless-ui/account-examples"; +import ThirdwebProvider from "@/components/thirdweb-provider"; +import { metadataBase } from "@/lib/constants"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + metadataBase, + title: "Integrate Fiat & Cross-Chain Crypto Payments | thirdweb Pay", + description: + "The easiest way for users to transact in your app. Onramp users in clicks and generate revenue for each user transaction. Integrate for free.", +}; + +export default function Page() { + return ( + +
+ + Lorem ipsum, dolor sit amet consectetur adipisicing elit. + Accusantium reprehenderit corrupti sapiente nobis impedit, beatae + sit unde nihil, facilis vitae sunt. Aperiam sed vero repudiandae + nisi maiores repellat molestiae illum. + + } + docsLink="https://portal.thirdweb.com/react/v5/connecting-wallets/ui-components" + heroLink="/pay.png" + /> + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ ); +} diff --git a/apps/playground-web/src/app/navLinks.ts b/apps/playground-web/src/app/navLinks.ts index d870b0e4707..638242f6eea 100644 --- a/apps/playground-web/src/app/navLinks.ts +++ b/apps/playground-web/src/app/navLinks.ts @@ -85,4 +85,26 @@ export const navLinks: SidebarLink[] = [ name: "Blockchain API", href: "/connect/blockchain-api", }, + { + name: "Headless UI", + expanded: true, + links: [ + { + name: "Account", + href: "/connect/ui", + }, + { + name: "NFT", + href: "/connect/ui/nft", + }, + { + name: "Token", + href: "/connect/ui/Token", + }, + { + name: "Transaction", + href: "/connect/ui/transaction", + }, + ], + }, ]; diff --git a/apps/playground-web/src/app/page.tsx b/apps/playground-web/src/app/page.tsx index 9c9651a6230..1a84adf3d7a 100644 --- a/apps/playground-web/src/app/page.tsx +++ b/apps/playground-web/src/app/page.tsx @@ -60,6 +60,12 @@ function WalletsSection() { description="Performant, and reliable blockchain API" icon={CodeIcon} /> + ); diff --git a/apps/playground-web/src/components/headless-ui/account-examples.tsx b/apps/playground-web/src/components/headless-ui/account-examples.tsx new file mode 100644 index 00000000000..853638a14d6 --- /dev/null +++ b/apps/playground-web/src/components/headless-ui/account-examples.tsx @@ -0,0 +1,335 @@ +"use client"; + +import { THIRDWEB_CLIENT } from "@/lib/client"; +import { ethereum } from "thirdweb/chains"; +import { + AccountAddress, + AccountBalance, + type AccountBalanceFormatParams, + AccountProvider, +} from "thirdweb/react"; +import { shortenAddress } from "thirdweb/utils"; +import { CodeExample } from "../code/code-example"; + +const vitalikAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; + +/** + * Show full wallet address with AccountAddress + */ +export function AccountAddressBasic() { + return ( + <> +
+

+ AccountAddress +

+

+ Show the wallet address of the account. +

+
+ + + + + } + code={`import { AccountProvider, AccountAddress } from "thirdweb/react"; + +function App() { + return + + +}`} + lang="tsx" + /> + + ); +} + +/** + * Shorten wallet address with AccountAddress + */ +export function AccountAddressFormat() { + return ( + <> +
+

+ Shorten the wallet address using the formatFn prop. +

+
+ + + + + } + code={`import { AccountProvider, AccountAddress } from "thirdweb/react"; +import { shortenAddress } from "thirdweb/utils"; + +function App() { + return + + +}`} + lang="tsx" + /> + + ); +} + +/** + * AccountBalance: Fetch native balance on Ethereum mainnet + */ +export function AccountBalanceBasic() { + return ( + <> +
+

+ AccountBalance +

+

+ Display the current native of the wallet. +

+
+ + + Loading...} + /> + + } + code={`import { AccountProvider, AccountAddress } from "thirdweb/react"; +import { shortenAddress } from "thirdweb/utils"; + +function App() { + return + Loading...} + /> + +}`} + lang="tsx" + /> + + ); +} + +/** + * AccountBalance: Fetch USDC balance on mainnet + */ +export function AccountBalanceCustomToken() { + return ( + <> +
+

+ Display the current balance of a custom token +

+
+ + + Loading...} + /> + + } + code={`import { AccountProvider, AccountAddress } from "thirdweb/react"; +import { shortenAddress } from "thirdweb/utils"; + +const USDC_ETHEREUM = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; + +function App() { + return + Loading...} + /> + +}`} + lang="tsx" + /> + + ); +} + +/** + * AccountBalance: Round up the token balance + */ +export function AccountBalanceFormat() { + return ( + <> +
+

+ Round up the wallet balance using the formatFn prop. +

+
+ + + + `${Math.ceil(props.tokenBalance * 1000) / 1000} ${props.tokenSymbol}` + } + loadingComponent={Loading...} + /> + + } + code={`import { AccountProvider, AccountAddress, type AccountBalanceFormatParams } from "thirdweb/react"; + +function App() { + return + Loading...} + formatFn={(props: AccountBalanceFormatParams) => \`\${Math.ceil(props.tokenBalance * 1000) / 1000} \${props.tokenSymbol}\`} /> + +}`} + lang="tsx" + /> + + ); +} + +/** + * AccountBalance: Show USD balance + */ +export function AccountBalanceUSD() { + return ( + <> +
+

+ Display the USD value of the token balance. +

+
+ + + Loading...} + /> + + } + code={`import { AccountProvider, AccountAddress } from "thirdweb/react"; + +function App() { + return + Loading...} + /> + +}`} + lang="tsx" + /> + + ); +} + +function formatNumber(value: number, decimalPlaces: number) { + if (value === 0) return 0; + const precision = 10 ** decimalPlaces; + const threshold = 1 / 10 ** decimalPlaces; // anything below this if rounded will result in zero - so use ceil instead + const fn: "ceil" | "round" = value < threshold ? "ceil" : "round"; + return Math[fn]((value + Number.EPSILON) * precision) / precision; +} + +function formatAccountBalanceForButton( + props: AccountBalanceFormatParams, +): string { + // IMPORTANT: Need to check if fiatValue exists + // because not all tokens are resovable to a fiat value + if (props.fiatBalance && props.fiatSymbol) { + // Need to keep them short to avoid UI overflow issues + const formattedTokenBalance = formatNumber(props.tokenBalance, 1); + const formattedFiatBalance = formatNumber(props.fiatBalance, 0); + // Also + return `${formattedTokenBalance} ${props.tokenSymbol} (${props.fiatSymbol}${formattedFiatBalance})`; + } + const formattedTokenBalance = formatNumber( + props.tokenBalance, + props.tokenBalance < 1 ? 5 : 4, + ); + return `${formattedTokenBalance} ${props.tokenSymbol}`; +} + +export function AccountBalanceUSDFormatted() { + return ( + <> +
+

+ Round up the token & fiat balance using the formatFn prop. +

+
+ + + Loading...} + formatFn={formatAccountBalanceForButton} + /> + + } + code={`import { AccountProvider, AccountAddress } from "thirdweb/react"; + +function formatNumber(value: number, decimalPlaces: number) { + if (value === 0) return 0; + const precision = 10 ** decimalPlaces; + const threshold = 1 / 10 ** decimalPlaces; // anything below this if rounded will result in zero - so use ceil instead + const fn: "ceil" | "round" = value < threshold ? "ceil" : "round"; + return Math[fn]((value + Number.EPSILON) * precision) / precision; +} + +function formatAccountBalanceForButton( + props: AccountBalanceFormatParams, +): string { + // IMPORTANT: Need to check if fiatValue exists + // because not all tokens are resovable to a fiat value + if (props.fiatBalance && props.fiatSymbol) { + // Need to keep them short to avoid UI overflow issues + const formattedTokenBalance = formatNumber(props.tokenBalance, 1); + const formattedFiatBalance = formatNumber(props.fiatBalance, 0); + return \`\${formattedTokenBalance} \${props.tokenSymbol} (\${props.fiatSymbol}\${formattedFiatBalance})\`; + } + const formattedTokenBalance = formatNumber( + props.tokenBalance, + props.tokenBalance < 1 ? 5 : 4, + ); + return \`\${formattedTokenBalance} \${props.tokenSymbol}\`; +} + +function App() { + return + Loading...} + /> + +}`} + lang="tsx" + /> + + ); +} diff --git a/packages/thirdweb/src/exports/react.ts b/packages/thirdweb/src/exports/react.ts index 826d832d592..880249c4261 100644 --- a/packages/thirdweb/src/exports/react.ts +++ b/packages/thirdweb/src/exports/react.ts @@ -221,7 +221,7 @@ export { export { AccountBalance, type AccountBalanceProps, - type AccountBalanceFormatParams + type AccountBalanceFormatParams, } from "../react/web/ui/prebuilt/Account/balance.js"; export { AccountName,