Compare commits

...
Author SHA1 Message Date
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
66b9bf3c6b Version Packages (#7694)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-24 02:00:52 -07:00
Joaquim VergesandGitHub cf22c23b45 [SDK] Optimize 4337 signature performance (#7693) 2025-07-24 00:47:45 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
170b020e17 Version Packages (#7682)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-23 19:25:46 -07:00
Joaquim VergesandGitHub 8260af3a92 [Dashboard] Replace modular contracts with Arbitrum Stylus contracts in explore page (#7685) 2025-07-22 19:15:42 -07:00
Joaquim VergesandGitHub b9154cc9e7 [API] Init API wrapper package (#7684) 2025-07-22 18:46:02 -07:00
Joaquim VergesandGitHub 08955f1588 [SDK] Expose getAuthToken from inApp and ecosystem wallets (#7683) 2025-07-22 18:26:46 -07:00
gregandGitHub 756295241a [SDK] Feature: Adds optional transactionId parameter to Bridge.status (#7681) 2025-07-22 15:11:04 -07:00
Joaquim VergesandGitHub 249679481e [Docs] Update redirects for wallets and payments paths (#7680) 2025-07-22 15:09:00 -07:00
Joaquim VergesandGitHub a491de4d7c [Docs] Refactor Contract and Tokens docs (#7676) 2025-07-22 17:20:00 +12:00
gregandGitHub 898efc56a9 [Portal] Fix: Test Jam Feedback (#7677) 2025-07-21 21:32:26 -07:00
c0e7ae95de Add external wallet filter and display (#7669)
Co-authored-by: Cursor Agent <[email protected]>
2025-07-21 20:39:26 -07:00
Joaquim VergesandGitHub 1e8190a1f9 [Docs] Add frontend/backend tabs for transaction sending examples (#7670) 2025-07-21 19:36:18 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
aac187a76c Version Packages (#7662)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-21 16:35:51 -07:00
Manan TankandGitHub 03390c1e25 Portal: homepage UI improvements (#7667) 2025-07-21 16:35:29 -07:00
8d3b9c6a33 [Portal] Fix: update sidebar overflow behavior in DocLayout component (#7653)
Co-authored-by: Joaquim Verges <[email protected]>
2025-07-21 14:47:24 -07:00
MananTank ddef88866f [PRO-249] Portal: Update OG images (#7664)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the metadata and image attributes across various pages in the `thirdweb` portal, particularly in the payments and vault sections. It modifies titles, icons, and descriptions to enhance clarity and consistency.

### Detailed summary
- Changed `metadata` for payments to use "payments" icon and updated titles.
- Updated vault metadata to include a new image with the "vault" icon.
- Modified various page descriptions for clarity and consistency.
- Added a new script for formatting in `package.json`.
- Removed unused code in `api/og/route.tsx`.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Added and updated metadata images and titles across several pages, including "Contracts", "Vault", and various "Payments" pages for improved visual representation.
  * Introduced support for a new "vault" icon in metadata image options.

* **Style**
  * Improved formatting and removed extraneous blank lines in code examples and UI components for better readability.
  * Cleaned up whitespace in multiple example code snippets.

* **Chores**
  * Added a new formatting script for consistent code style across the project.

* **Refactor**
  * Simplified Open Graph image layouts by removing certain UI elements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-07-21 20:42:32 +00:00
Manan TankandGitHub 8133fab9e4 [TOOL-5083] Portal: Fix header on mobile viewport (#7661) 2025-07-21 13:41:30 -07:00
Joaquim VergesandGitHub 37414eb54a [SDK] Fix native token fallback when insight query fails (#7666) 2025-07-21 13:39:29 -07:00
MananTank 22bf68a6f0 [TOOL-5075] SDK: Fix various alignment issues in components (#7657)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing various alignment issues in React components within the `thirdweb` package, enhancing hover states and visual consistency across different UI elements.

### Detailed summary
- Updated hover styles in several components to improve visual feedback.
- Adjusted `all` property to "unset" for better styling control.
- Modified colors and borders in `OTPLoginUI.tsx`, `ReceiveFunds.tsx`, `DepositScreen.tsx`, and others for consistency.
- Enhanced button styles in `MenuButton.tsx`, `WalletEntryButton.tsx`, and `NetworkSelector.tsx`.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Bug Fixes**
  * Resolved various alignment issues in React components to improve visual consistency across the interface.

* **Chores**
  * Updated internal documentation to reflect the latest patch addressing alignment fixes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-07-21 17:58:07 +00:00
EimanandGitHub 68dd4dc17e fixed playground import (#7660) 2025-07-21 10:46:58 -07:00
saminacodes ecf6dbf2aa Update portal label to TypeScript SDK (#7658)
```
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

[Portal] Fix: Update SDK title for TypeScript reference pages

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Updates the SDK title displayed on TypeScript reference pages from "Connect SDK" to "TypeScript SDK" for improved clarity and accuracy.

## How to test

Navigate to any `/references/typescript/v*/` page (e.g., `/references/typescript/v5/`). Verify the header displays "TypeScript SDK".

-->
```

---

**Open Background Agent:**
[Web](https://www.cursor.com/agents?id=bc-2dec36af-4b62-431c-b277-891c1b46bb48) · [Cursor](https://cursor.com/background-agent?bcId=bc-2dec36af-4b62-431c-b277-891c1b46bb48)

[Slack Thread](https://thirdwebdev.slack.com/archives/C04DYC3G5NZ/p1753110978408999?thread_ts=1753110978.408999&cid=C04DYC3G5NZ)

Learn more about [Background Agents](https://docs.cursor.com/background-agents)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on renaming references from `Connect SDK` to `TypeScript SDK` and `thirdweb SDK` across multiple files in the project, enhancing clarity and consistency in the documentation and codebase.

### Detailed summary
- Updated `label` from `Connect SDKs` to `thirdweb SDKs`.
- Changed `name` from `Connect SDK` to `TypeScript SDK`.
- Modified `sdkTitle` from `Connect SDK` to `TypeScript SDK`.
- Adjusted example descriptions and titles to reflect `TypeScript SDK`.
- Updated installation instructions to refer to `TypeScript SDK`.
- Revised descriptions related to wallet support to mention `thirdweb SDKs`.
- Changed references in guides and documentation from `Connect SDK` to `TypeScript SDK`.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Updated SDK naming from "Connect SDK" to "TypeScript SDK" and "thirdweb SDK" across documentation, guides, UI labels, and sidebar links for improved clarity and consistency.

* **Chores**
  * Removed the "Engine" API link from the main navigation header.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-07-21 16:52:47 +00:00
Phillip HoandGitHub 01daaceb21 only one file (#7659) 2025-07-21 23:23:18 +08:00
388 changed files with 9027 additions and 1712 deletions
@@ -661,7 +661,7 @@ export const CodeOverview: React.FC<CodeOverviewProps> = ({
rel="noopener noreferrer"
target="_blank"
>
Connect SDK
thirdweb SDK
</UnderlineLink>{" "}
in your applications. This will ensure account contracts are
deployed for your users only when they need it.
@@ -90,144 +90,6 @@ const MARKETS = {
name: "Marketplace",
} satisfies ExploreCategory;
const MODULAR_CONTRACTS = {
contracts: [
// erc721 drop
[
"thirdweb.eth/ERC721CoreInitializable",
[
"deployer.thirdweb.eth/ClaimableERC721",
"deployer.thirdweb.eth/BatchMetadataERC721",
"deployer.thirdweb.eth/RoyaltyERC721",
],
{
description: "ERC721 NFTs that anyone can mint.",
title: "Modular NFT Drop",
},
],
// erc721 token
[
"thirdweb.eth/ERC721CoreInitializable",
[
"deployer.thirdweb.eth/MintableERC721",
"deployer.thirdweb.eth/BatchMetadataERC721",
"deployer.thirdweb.eth/TransferableERC721",
],
{
description: "ERC721 NFTs that only owners can mint.",
title: "Modular NFT Collection",
},
],
// open edition 721
[
"thirdweb.eth/ERC721CoreInitializable",
[
"deployer.thirdweb.eth/ClaimableERC721",
"deployer.thirdweb.eth/OpenEditionMetadataERC721",
"deployer.thirdweb.eth/RoyaltyERC721",
],
{
description: "ERC721 NFTs with identical metadata.",
title: "Modular Open Edition",
},
],
// erc1155 drop
[
"thirdweb.eth/ERC1155CoreInitializable",
[
"deployer.thirdweb.eth/ClaimableERC1155",
"deployer.thirdweb.eth/BatchMetadataERC1155",
"deployer.thirdweb.eth/RoyaltyERC1155",
"deployer.thirdweb.eth/SequentialTokenIdERC1155",
],
{
description: "ERC1155 NFTs that others can mint.",
title: "Modular Edition Drop",
},
],
// erc1155 token
[
"thirdweb.eth/ERC1155CoreInitializable",
[
"deployer.thirdweb.eth/MintableERC1155",
"deployer.thirdweb.eth/BatchMetadataERC1155",
"deployer.thirdweb.eth/TransferableERC1155",
"deployer.thirdweb.eth/SequentialTokenIdERC1155",
],
{
description: "ERC1155 NFTs that only owners can mint.",
title: "Modular Edition",
},
],
// erc20 drop
[
"thirdweb.eth/ERC20CoreInitializable",
[
"deployer.thirdweb.eth/ClaimableERC20",
"deployer.thirdweb.eth/TransferableERC20",
],
{
description: "ERC20 Tokens that others can mint.",
title: "Modular Token Drop",
},
],
// erc20 token
[
"thirdweb.eth/ERC20CoreInitializable",
[
"deployer.thirdweb.eth/MintableERC20",
"deployer.thirdweb.eth/TransferableERC20",
],
{
description: "ERC20 Tokens that only owners can mint.",
title: "Modular Token",
},
],
],
description:
"Collection of highly customizable and upgradeable smart contracts built with the modular contracts framework.",
displayName: "Modular Contracts",
id: "modular-contracts",
name: "modular",
} satisfies ExploreCategory;
const SUPERCHAIN = {
contracts: [
// erc20 token + superchain
[
"thirdweb.eth/ERC20CoreInitializable",
[
"deployer.thirdweb.eth/MintableERC20",
"deployer.thirdweb.eth/TransferableERC20",
"deployer.thirdweb.eth/SuperChainInterop",
],
{
description: "ERC20 Tokens that only owners can mint.",
title: "Modular Superchain Token",
},
],
// erc20 drop + superchain
[
"thirdweb.eth/ERC20CoreInitializable",
[
"deployer.thirdweb.eth/ClaimableERC20",
"deployer.thirdweb.eth/TransferableERC20",
"deployer.thirdweb.eth/SuperChainInterop",
],
{
description: "ERC20 Tokens that others can mint.",
title: "Modular Superchain Token Drop",
},
],
],
description: "Modular contracts with OP Superchain support",
displayName: "Modular Superchain Contracts",
id: "modular-superchain-contracts",
isBeta: true,
name: "Modular Superchain Contracts",
showInExplore: true,
} satisfies ExploreCategory;
const AIRDROP = {
contracts: ["thirdweb.eth/Airdrop"],
description:
@@ -313,12 +175,26 @@ const SMART_WALLET = {
showInExplore: true,
} satisfies ExploreCategory;
const STYLUS = {
contracts: [
"0x6453a486d52e0EB6E79Ec4491038E2522a926936/StylusAirdropERC1155",
"0x6453a486d52e0EB6E79Ec4491038E2522a926936/StylusAirdropERC721",
"0x6453a486d52e0EB6E79Ec4491038E2522a926936/StylusAirdropERC20",
],
description:
"Airdrop your NFTs or tokens to a large number of recipients. Built with Arbitrum Stylus.",
displayName: "Arbitrum Stylus Contracts",
id: "stylus",
name: "Stylus",
showInExplore: true,
isBeta: true,
} satisfies ExploreCategory;
const CATEGORIES: Record<string, ExploreCategory> = {
[POPULAR.id]: POPULAR,
[MODULAR_CONTRACTS.id]: MODULAR_CONTRACTS,
[SUPERCHAIN.id]: SUPERCHAIN,
[NFTS.id]: NFTS,
[MARKETS.id]: MARKETS,
[STYLUS.id]: STYLUS,
[DROPS.id]: DROPS,
[SMART_WALLET.id]: SMART_WALLET,
[AIRDROP.id]: AIRDROP,
@@ -308,7 +308,7 @@ ${Object.keys(populatedTransaction)
rel="noopener noreferrer"
target="_blank"
>
Connect SDK example
TypeScript SDK example
</a>
<CodeClient code={state.codeExample} lang="ts" />
</div>
@@ -69,7 +69,7 @@ const PROBLEM_AREAS: ProblemAreaItem[] = [
<DescriptionInputWrapper />
</>
),
label: "Connect SDKs",
label: "thirdweb SDKs",
},
{
component: (
@@ -488,7 +488,7 @@ export function TransactionCharts(props: {
autoUpdate: false,
instanceUrl: props.instanceUrl,
queryParams: {
limit: 10000,
limit: 2000,
page: 1,
},
});
@@ -55,6 +55,7 @@ export function AdvancedSearchInput(props: {
<SelectItem value="phone">Phone</SelectItem>
<SelectItem value="id">ID</SelectItem>
<SelectItem value="address">Address</SelectItem>
<SelectItem value="externalWallet">External Wallet</SelectItem>
</SelectContent>
</Select>
@@ -52,6 +52,11 @@ export function SearchResults(props: {
const email = mainDetail?.email as string | undefined;
const phone = mainDetail?.phone as string | undefined;
// Get external wallet addresses from linkedAccounts where type is 'siwe'
const externalWalletAccounts =
user.linkedAccounts?.filter((account) => account.type === "siwe") ||
[];
return (
<Card key={user.id}>
<CardHeader>
@@ -96,6 +101,29 @@ export function SearchResults(props: {
</div>
)}
{externalWalletAccounts.length > 0 && (
<div className="col-span-full">
<p className="text-sm font-medium text-muted-foreground">
External Wallets
</p>
<div className="space-y-1">
{externalWalletAccounts.map((account, index) => {
const address = account.details?.address as
| string
| undefined;
return address ? (
<div key={`${user.id}-external-${index}`}>
<WalletAddress
address={address}
client={props.client}
/>
</div>
) : null;
})}
</div>
</div>
)}
{createdAt && (
<div>
<p className="text-sm font-medium text-muted-foreground">
@@ -36,6 +36,10 @@ const getUserIdentifier = (accounts: WalletUser["linkedAccounts"]) => {
);
};
const getExternalWallets = (accounts: WalletUser["linkedAccounts"]) => {
return accounts?.filter((account) => account.type === "siwe") || [];
};
const columnHelper = createColumnHelper<WalletUser>();
export function InAppWalletUsersPageContent(
@@ -69,6 +73,36 @@ export function InAppWalletUsersPageContent(
header: "Address",
id: "address",
}),
columnHelper.accessor("linkedAccounts", {
cell: (cell) => {
const externalWallets = getExternalWallets(cell.getValue());
if (externalWallets.length === 0) {
return <span className="text-muted-foreground text-xs">None</span>;
}
return (
<div className="space-y-1">
{externalWallets.slice(0, 2).map((account) => {
const address = account.details?.address as string | undefined;
return address ? (
<div
key={`external-${address}-${account.details?.id}`}
className="text-xs"
>
<WalletAddress address={address} client={props.client} />
</div>
) : null;
})}
{externalWallets.length > 2 && (
<span className="text-muted-foreground text-xs">
+{externalWallets.length - 2} more
</span>
)}
</div>
);
},
header: "External Wallets",
id: "external_wallets",
}),
columnHelper.accessor("wallets", {
cell: (cell) => {
const value = cell.getValue()[0]?.createdAt;
@@ -172,11 +206,18 @@ export function InAppWalletUsersPageContent(
});
const csv = Papa.unparse(
usersWallets.map((row) => {
const externalWallets = getExternalWallets(row.linkedAccounts);
const externalWalletAddresses = externalWallets
.map((account) => account.details?.address)
.filter(Boolean)
.join(", ");
return {
address: row.wallets[0]?.address || "Uninitialized",
created: row.wallets[0]?.createdAt
? format(new Date(row.wallets[0].createdAt), "MMM dd, yyyy")
: "Wallet not created yet",
external_wallets: externalWalletAddresses || "None",
login_methods: row.linkedAccounts.map((acc) => acc.type).join(", "),
user_identifier: getUserIdentifier(row.linkedAccounts),
};
@@ -33,6 +33,9 @@ export async function searchUsers(
case "address":
url.searchParams.append("address", query);
break;
case "externalWallet":
url.searchParams.append("externalWalletAddress", query);
break;
}
const response = await fetch(url.toString(), {
@@ -1 +1,6 @@
export type SearchType = "email" | "phone" | "id" | "address";
export type SearchType =
| "email"
| "phone"
| "id"
| "address"
| "externalWallet";
@@ -22,10 +22,10 @@ export function EmptyState() {
<AnimatedIcons />
<div className="flex flex-col gap-0.5 text-center">
<h3 className="font-semibold text-2xl text-foreground">
Get Started with the Connect SDK
Get Started with the TypeScript SDK
</h3>
<p className="text-base text-muted-foreground">
Add the Connect SDK to your app to start collecting analytics.
Add the TypeScript SDK to your app to start collecting analytics.
</p>
</div>
<div className="flex flex-wrap items-center justify-center gap-2">
@@ -40,7 +40,7 @@ function BuyOnchainAsset() {
return (
<CodeExample
code={`import { claimTo } from "thirdweb/extensions/erc1155";
import { PayEmbed, useActiveAccount } from "thirdweb/react";
import { TransactionWidget, useActiveAccount } from "thirdweb/react";
function App() {
const account = useActiveAccount();
+1
View File
@@ -70,6 +70,7 @@
"private": true,
"scripts": {
"build": "next build",
"format": "biome format ./src --write",
"create-index": "pnpm tsx scripts/createEmptySearchIndex.ts",
"dev": "next dev",
"extract-llm-content": "pnpm tsx scripts/extractLLMData.ts",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

+10 -6
View File
@@ -339,6 +339,11 @@ const solidityRedirects = {
"/solidity/extensions/primarysale":
"/contracts/build/extensions/general/PrimarySale",
"/solidity/extensions/royalty": "/contracts/build/extensions/general/Royalty",
// contracts -> tokens
"/contracts/deploy/:path*": "/contracts/deploy",
"/contracts/build": "/tokens/build",
"/contracts/build/:path*": "/tokens/build/:path*",
};
const extensionsTable = "/typescript/v4/extensions#all-available-extensions";
@@ -712,6 +717,7 @@ const walletRedirects = {
const paymentRedirects = {
"/pay": "/payments",
"/pay/:path*": "/payments",
"/checkouts": "/payments",
"/checkouts/api-reference": "/payments/nft-checkout/api-reference",
"/checkouts/checkout-link": "/payments/nft-checkout/checkout-link",
@@ -920,7 +926,6 @@ const otherRedirects = {
"/connect/account-abstraction": "/connect/account-abstraction/overview",
// connect
"/connect/connect": "/connect/sign-in",
"/connect/ecosystems/:path*": "/connect/wallet/overview",
"/connect/embedded-wallet/how-to/get-embedded-wallet-details-on-server":
"/connect/in-app-wallet/how-to/get-in-app-wallet-details-on-server",
"/connect/in-app-wallet/how-to/get-in-app-wallet-details-on-server":
@@ -1016,15 +1021,14 @@ const otherRedirects = {
"/unity/wallets/providers/account-abstraction",
"/wallet/get-started/overview": "/connect/wallet/overview",
// connect > wallets
"/connect/:path*": "/wallets/:path*",
"/connect/wallet/:path*": "/wallets/:path*",
"/connect/auth/:path*": "/wallets/auth/:path*",
"/connect/connect/:path*": "/wallets/connect/:path*",
"/connect/embedded-wallet/:path*": "/wallets/embedded-wallet/:path*",
"/connect": "/wallets",
"/connect/wallet/sign-in-methods/configure": "/wallets/users",
"/connect/wallet/server": "/wallets/server",
"/connect/account-abstraction/get-started": "/wallets/sponsor-gas",
"/connect/account-abstraction/:path*": "/wallets/sponsor-gas",
"/connect/pay/:path*": "/payments",
"/connect/ecosystems/:path*": "/wallets/ecosystem/set-up",
"/connect/:path*": "/wallets",
"/wallets/in-app-wallet/custom-auth/configuration": "/wallets/custom-auth",
"/connect/wallets/user-management/link-multiple-identity":
"/wallets/link-profiles",
+21 -34
View File
@@ -8,7 +8,7 @@ import {
TableOfContentsIcon,
} from "lucide-react";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { DocSearch } from "@/components/others/DocSearch";
import { Button } from "@/components/ui/button";
@@ -48,12 +48,8 @@ const links = [
name: "Contracts",
},
{
href: "/insight",
name: "Insight",
},
{
href: "/vault",
name: "Vault",
href: "/tokens",
name: "Tokens",
},
];
@@ -86,7 +82,7 @@ export const connectLinks: Array<{
icon: React.FC<{ className?: string }>;
}> = [
{
href: "/connect",
href: "/wallets",
icon: TableOfContentsIcon,
name: "Overview",
},
@@ -123,10 +119,6 @@ export const connectLinks: Array<{
] as const;
const apisLinks = [
{
href: "https://engine.thirdweb.com/reference",
name: "Engine",
},
{
href: "https://insight.thirdweb.com/reference",
name: "Insight",
@@ -140,7 +132,7 @@ const apisLinks = [
name: "Payments",
},
{
href: "/connect/account-abstraction/api",
href: "/bundler",
name: "Bundler",
},
];
@@ -195,13 +187,12 @@ const supportLinks = [
export function Header() {
const [showBurgerMenu, setShowBurgerMenu] = useState(false);
const router = useRouter();
const pathname = usePathname();
return (
<header className="flex w-full flex-col gap-2 border-b bg-background pt-4 px-4 lg:px-8 overflow-hidden">
<header className="flex w-full flex-col gap-2 border-b bg-background p-4 xl:pb-0 lg:px-8 overflow-hidden">
{/* Top row */}
<div className="container flex items-center justify-between gap-6">
{/* Top row */}
<div className="flex items-center gap-2">
<Link
aria-label="thirdweb Docs"
@@ -223,7 +214,7 @@ export function Header() {
href="https://github.com/thirdweb-dev"
target="_blank"
>
<GithubIcon className="mx-3 size-6" />
<GithubIcon className="size-6 lg:size-5" />
</Link>
</div>
@@ -236,25 +227,21 @@ export function Header() {
</div>
<div className="hidden xl:block">
<Button
onClick={() => {
router.push("/chat");
}}
>
<MessageCircleIcon className="mr-2 size-4" />
Ask AI
<Button asChild>
<Link href="/chat">
<MessageCircleIcon className="mr-2 size-4" />
Ask AI
</Link>
</Button>
</div>
<div className="flex items-center gap-1 xl:hidden">
<ThemeSwitcher className="border-none bg-transparent" />
<DocSearch variant="icon" />
<Button
className="p-2"
onClick={() => router.push("/chat")}
variant="ghost"
>
<MessageCircleIcon className="size-7" />
<Button className="p-2" asChild variant="ghost">
<Link href="/chat">
<MessageCircleIcon className="size-6" />
</Link>
</Button>
<Button
className="p-2"
@@ -268,13 +255,13 @@ export function Header() {
</div>
{/* Bottom row - hidden on mobile */}
<div className="container hidden items-center justify-between gap-6 xl:flex">
<div className="container hidden items-center justify-between gap-6 xl:flex mt-1">
<nav className="flex grow gap-5">
<ul className="flex flex-row items-center gap-5">
<ul className="flex flex-row items-center gap-0 mb-1">
{links.map((link) => {
return (
<li
className="flex items-center py-4 relative overflow-hidden"
className="flex items-center py-2 relative px-2.5 hover:text-foreground"
key={link.href}
onClick={() => {
setShowBurgerMenu(false);
@@ -285,7 +272,7 @@ export function Header() {
>
<NavLink href={link.href} name={link.name} />
{pathname.includes(link.href) && (
<div className="bg-violet-700 h-1 inset-x-0.5 rounded-full absolute -bottom-0.5" />
<div className="bg-violet-700 h-[2px] inset-x-0 rounded-full absolute -bottom-1" />
)}
</li>
);
@@ -12,7 +12,7 @@ export const metadata = createMetadata({
# API Keys
Each thirdweb project is equipped with an API key to use thirdweb's infrastructure services including [Storage](/infrastructure/storage/overview), [RPC Edge](/infrastructure/rpc-edge/overview), [Account Abstraction infrastructure](/connect/account-abstraction), and [In-App Wallets](/connect/in-app-wallet/overview).
Each thirdweb project is equipped with an API key to use thirdweb's infrastructure services including [Storage](/infrastructure/storage/overview), [RPC Edge](/infrastructure/rpc-edge/overview), [Account Abstraction infrastructure](/bundler), and [In-App Wallets](/wallets).
## Services
-51
View File
@@ -64,37 +64,6 @@ export async function GET(request: Request) {
width: "50%",
}}
>
<div
style={{
alignItems: "center",
display: "flex",
gap: "10px",
marginBottom: "40px",
}}
>
<img
alt=""
height={50 / 1.7}
src={`${BAST_URL}/icons/thirdweb-logo.svg`}
style={{
display: "flex",
}}
width={300 / 1.7}
/>
<div
style={{
color: "white",
fontFamily: "Inter",
fontSize: "26px",
fontWeight: 600,
marginTop: "2px",
}}
>
Docs
</div>
</div>
<div
style={{
display: "flex",
@@ -107,26 +76,6 @@ export async function GET(request: Request) {
>
{title}
</div>
<div
style={{
display: "flex",
}}
>
<div
style={{
background: "white",
borderRadius: "10px",
color: "black",
fontFamily: "Inter",
fontSize: "24px",
fontWeight: 600,
padding: "14px 20px",
}}
>
Read More
</div>
</div>
</div>
<img
+15
View File
@@ -0,0 +1,15 @@
import { DocLayout } from "@/components/Layouts/DocLayout";
export default async function Layout(props: { children: React.ReactNode }) {
return (
<DocLayout
editPageButton={true}
sideBar={{
name: "Bundler",
links: [],
}}
>
{props.children}
</DocLayout>
);
}
+490
View File
@@ -0,0 +1,490 @@
# Thirdweb Bundler - API Reference
The Thirdweb Bundler is a service that provides Account Abstraction (ERC-4337 and EIP-7702) bundler functionality with integrated paymaster services, zkSync chains support, and EIP-7702 transaction delegation.
## Table of Contents
- [Url format](#url-format)
- [Authentication](#authentication)
- [Request Format](#request-format)
- [Paymaster Methods](#paymaster-methods)
- [User Operation Methods](#user-operation-methods)
- [Gas Price Methods](#gas-price-methods)
- [Status and Tracking Methods](#status-and-tracking-methods)
- [zkSync-Specific Methods](#zksync-specific-methods)
- [EIP-7702 Methods](#eip-7702-methods)
- [Standard ERC-4337 Methods](#standard-erc-4337-methods)
- [Error Responses](#error-responses)
- [Policy Enforcement](#policy-enforcement)
## Url format
- **Chain Parameter**: the chain id is always specified in the subdomain (e.g., `<chain_id>.bundler.thirdweb.com`)
- **Version Parameter**: the version is specified in the path, we recommend using `/v2`
```
https://<chain_id>.bundler.thirdweb.com/v2
```
## Authentication
All requests require authentication via:
- **Client ID**: Provided as `X-Client-Id: <client_id>` header - used for frontend authentication
- **Secret Key**: Provided as `X-Secret-Key: <secret_key>` header - used for backend authentication
## Request Format
All RPC requests follow the JSON-RPC 2.0 specification:
```json
{
"id": 1,
"jsonrpc": "2.0",
"method": "<method_name>",
"params": [...]
}
```
## Paymaster Methods
### `pm_sponsorUserOperation`
**Purpose**: Sponsors a user operation by providing paymaster data to cover gas costs.
**Parameters**:
```json
[
{
"sender": "0x...", // Address of the smart account
"nonce": "0x...", // Nonce for the operation
"initCode": "0x...", // Account initialization code (if needed)
"callData": "0x...", // The call data to execute
"callGasLimit": "0x...", // Gas limit for the call
"verificationGasLimit": "0x...", // Gas limit for verification
"preVerificationGas": "0x...", // Pre-verification gas
"maxFeePerGas": "0x...", // Maximum fee per gas
"maxPriorityFeePerGas": "0x...", // Maximum priority fee per gas
"paymasterAndData": "0x...", // Paymaster data (EntryPoint v0.6)
// OR for EntryPoint v0.7:
"paymaster": "0x...", // Paymaster address
"paymasterData": "0x...", // Paymaster data
"paymasterVerificationGasLimit": "0x...",
"paymasterPostOpGasLimit": "0x..."
},
"0x...", // Entry point address
"0x...", // Chain ID (hex)
]
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"paymaster": "0x...", // Paymaster address
"paymasterData": "0x...", // Paymaster data
"paymasterAndData": "0x..." // Combined paymaster data (v0.6)
}
}
```
### `pm_getPaymasterData`
**Purpose**: Gets paymaster data for sponsoring a user operation (functionally equivalent to `pm_sponsorUserOperation`).
**Parameters**: Same as `pm_sponsorUserOperation`
**Response**: Same as `pm_sponsorUserOperation`
### `pm_getPaymasterStubData`
**Purpose**: Gets stub paymaster data for gas estimation purposes without actual sponsorship.
**Parameters**: Same as `pm_sponsorUserOperation`
**Response**: Similar to `pm_sponsorUserOperation` but with placeholder data for estimation.
### `pm_getAcceptedPaymentTokens`
**Purpose**: Returns the list of tokens accepted for gas payments by the paymaster.
**Parameters**: `[]`
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"acceptedTokens": []
}
}
```
## User Operation Methods
### `eth_estimateUserOperationGas`
**Purpose**: Estimates gas limits required for a user operation.
**Parameters**:
```json
[
{
"sender": "0x...", // Smart account address
"nonce": "0x...", // Account nonce
"initCode": "0x...", // Initialization code (if deploying)
"callData": "0x...", // Transaction call data
"maxFeePerGas": "0x...", // Maximum fee per gas
"maxPriorityFeePerGas": "0x..." // Maximum priority fee
},
"0x...", // Entry point address
{} // State overrides (optional)
]
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"preVerificationGas": "0x...", // Pre-verification gas
"verificationGasLimit": "0x...", // Verification gas limit
"callGasLimit": "0x...", // Call gas limit
// For EntryPoint v0.7:
"paymasterVerificationGasLimit": "0x...",
"paymasterPostOpGasLimit": "0x..."
}
}
```
### `eth_sendUserOperation`
**Purpose**: Submits a user operation to the bundler for execution on-chain.
**Parameters**: Same format as the user operation object used in other methods.
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": "0x..." // User operation hash
}
```
## Gas Price Methods
### `thirdweb_getUserOperationGasPrice`
**Purpose**: Gets current gas prices optimized for user operations.
**Parameters**: `[]`
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"maxFeePerGas": "0x...", // Recommended max fee per gas
"maxPriorityFeePerGas": "0x..." // Recommended priority fee
}
}
```
## Status and Tracking Methods
### `thirdweb_getUserOperationStatus`
**Purpose**: Gets the current status of a submitted user operation.
**Parameters**:
```json
["0x..."] // User operation hash (hex string)
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"status": "not_found|not_submitted|submitted|rejected|included|failed|queued",
"transactionHash": "0x..." // Transaction hash (null if not yet included)
}
}
```
**Status Values**:
- `not_found`: User operation not found
- `not_submitted`: Not yet submitted to mempool
- `submitted`: Submitted to mempool
- `rejected`: Rejected by bundler
- `included`: Successfully included in a block
- `failed`: Transaction failed on-chain
- `queued`: Queued for processing
## zkSync-Specific Methods
### `zk_paymasterData`
**Purpose**: Gets paymaster data for zkSync chains to enable gasless transactions.
**Parameters**:
```json
[
{
"nonce": "0x...", // Transaction nonce
"from": "0x...", // Sender address
"to": "0x...", // Recipient address
"gas": "0x...", // Gas limit
"gasPrice": "0x...", // Gas price
"value": "0x...", // ETH value to send
"data": "0x...", // Transaction data
"maxFeePerGas": "0x...", // EIP-1559 max fee
"maxPriorityFeePerGas": "0x...", // EIP-1559 priority fee
"chainId": "0x..." // Chain ID
}
]
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"paymaster": "0x...", // Paymaster contract address
"paymasterInput": "0x..." // Encoded paymaster input data
}
}
```
### `zk_broadcastTransaction`
**Purpose**: Broadcasts a signed transaction on zkSync chains.
**Parameters**:
```json
[
{
"nonce": "0x...",
"from": "0x...",
"to": "0x...",
"gas": "0x...",
"gasPrice": "0x...",
"value": "0x...",
"data": "0x...",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x...",
"chainId": "0x...",
"signedTransaction": "0x..." // Raw signed transaction bytes
}
]
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": "0x..." // Transaction hash
}
```
## EIP-7702 Methods
### `tw_execute`
**Purpose**: Executes transactions using EIP-7702 (Account Abstraction via Authorization Lists). This enables EOAs to temporarily act as smart contracts.
**Parameters**:
```json
[
"0x...", // EOA address that will execute the calls
{
"calls": [
{
"target": "0x...", // Contract address to call
"value": "0x...", // ETH value to send (hex)
"data": "0x..." // Call data
}
// ... more calls
],
"uid": "0x..." // Unique identifier for the batch (bytes32)
},
"0x...", // Signature authorizing the execution
{
// Authorization list (optional)
"chainId": 1,
"address": "0x...",
"nonce": "0x...",
"yParity": 0,
"r": "0x...",
"s": "0x..."
}
]
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"queueId": "..." // Queue ID for tracking the transaction
}
}
```
### `tw_getTransactionHash`
**Purpose**: Gets the transaction hash for a queued EIP-7702 transaction.
**Parameters**:
```json
["queue_id"] // Queue ID returned from tw_execute
```
**Response**:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"transactionHash": "0x..." // Transaction hash (null if not yet mined)
}
}
```
## Standard ERC-4337 Methods
The service supports all the standard ERC-4337 bundler methods:
- `eth_chainId` - Returns the current chain ID
- `eth_getUserOperationByHash` - Retrieves user operation by hash
- `eth_getUserOperationReceipt` - Gets the receipt for a user operation
- `eth_supportedEntryPoints` - Lists supported EntryPoint contracts
- Any other standard bundler RPC methods defined in ERC-4337
## Error Responses
All methods may return error responses following the JSON-RPC 2.0 error format:
```json
{
"id": 1,
"jsonrpc": "2.0",
"error": {
"code": 400,
"message": "Detailed error description"
}
}
```
### Common Error Codes
- **400**: Invalid parameters, malformed request, or unsupported chain
- **401**: Invalid authentication credentials or insufficient permissions
- **500**: Internal server error
- **502**: Upstream bundler provider error
### Example Error Scenarios
```json
// Invalid chain
{
"error": "Invalid chain: unsupported_chain",
"chain": "unsupported_chain",
"code": 400
}
// Mainnet access denied
{
"error": "Mainnets not enabled for this account, please enable billing...",
"code": 401
}
// Invalid user operation hash
{
"error": "Invalid userOpHash parameter",
"code": 400
}
```
## Policy Enforcement
Paymaster methods support policy-based access control. When a transaction is subject to policy evaluation:
### Policy Check Process
1. The system evaluates paymaster requests against configured policies
2. Policies can restrict based on:
- Contract addresses being called
- Transaction data
- Gas limits
- Sender addresses
- Custom endpoint logic
### Policy Rejection Response
If a request is rejected by policy, the response format is:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"policyId": "policy_123", // ID of the policy that rejected the request
"reason": "Transaction rejected by policy: Unauthorized contract call"
}
}
```
### Affected Methods
Policy enforcement applies to:
- `pm_sponsorUserOperation`
- `pm_getPaymasterData`
- `zk_paymasterData`
## Rate Limits and Quotas
- Rate limits may apply based on your billing plan
- Mainnet access requires billing information
- Testnet access is available on free plans
## Supported Networks
For the most up-to-date list of supported chains, check the [thirdweb dashboard](https://thirdweb.com/dashboard).
## SDK Integration
For easier integration, consider using the thirdweb SDKs:
- [JavaScript/TypeScript SDK](/typescript)
- [React SDK](/react)
- [Unity SDK](/unity)
- [Dotnet SDK](/dotnet)
- [Unreal Engine SDK](/unreal)
@@ -0,0 +1,57 @@
# Deploy Contracts
You can deploy contracts via CLI or programatically.
## Deploying via CLI
From your forge or hardhat project, you can deploy your contract with a single command.
```bash
npx thirdweb deploy -k <project-secret-key>
```
You can also publish your contract to be deployable by anyone on any chain.
```bash
npx thirdweb publish -k <project-secret-key>
```
## Deploying via SDK
You can deploy contracts from ABI and bytecode.
```ts
import { deployContract } from "thirdweb/deploys";
const address = await deployContract({
client,
chain,
bytecode: "0x...",
abi: contractAbi,
constructorParams: {
param1: "value1",
param2: 123,
},
salt, // optional: salt enables deterministic deploys
});
```
Or alternatively, you can deploy a contract from a previously published contract.
```ts
import { deployPublishedContract } from "thirdweb/deploys";
const address = await deployPublishedContract({
client,
chain,
account,
contractId: "MyPublishedContract",
contractParams: {
param1: "value1",
param2: 123,
},
publisher: "0x...", // optional, defaults to the thirdweb deployer
});
```
@@ -0,0 +1,40 @@
# Listening to Events
The recommended way to listen to contract events is to use the [`getContractEvents`](/references/typescript/v5/getContractEvents) function and passing a prepared event with the Solidity event signature and the params. This is type-safe based on the Solidity event signature you define. You can get your desired contract event signature from the solidity code directly.
```ts
import { getContractEvents, prepareEvent } from "thirdweb";
const myEvent = prepareEvent({
signature: "event Transfer(address indexed from, address indexed to, uint256 value)",
});
const events = await getContractEvents({
contract: myContract,
events: [myEvent],
});
```
### Using standard event definitions
You can also use the standard event definitions from the SDK to define the events you want to listen to.
```ts
import { getContractEvents } from "thirdweb";
import { transferEvent } from "thirdweb/extensions/erc20";
const events = await getContractEvents({
contract: myContract,
events: [transferEvent()],
});
```
### Generating all read functions and events for a deployed contract
Using the CLI, you can generate optimized functions for all the possible calls to a contract. This saves you time and precomputes all the necessary encoding.
```shell
npx thirdweb generate <contractId>/<contractAddress>
```
Read more on how to [generate extension functions using the CLI](/contracts/generate).
@@ -0,0 +1,85 @@
import { fetchTypeScriptDoc } from "@/app/references/components/TDoc/fetchDocs/fetchTypeScriptDoc";
import { getCustomTag } from "@/app/references/components/TDoc/utils/getSidebarLinkgroups";
import { DocLink, Heading, Paragraph } from "@/components/Document";
import { Table, TBody, Td, Th, Tr } from "@/components/Document/Table";
export default async function ExtensionPage() {
const docs = await fetchTypeScriptDoc();
const extensions = [
...new Set(
docs.functions
?.filter((f) => {
const [extension] = getCustomTag(f) || [];
return extension === "@extension";
})
?.map((f) => {
const [, extensionName] = getCustomTag(f) || [];
return extensionName;
})
.filter((item) => item !== undefined) || [],
),
];
const overrides: Record<string, { name?: string; description?: string }> = {
common: {
description: "Common contract extensions",
name: "Common",
},
erc20: { description: "ERC20 token standard extensions" },
erc721: { description: "ERC721 token standard extensions" },
erc1155: { description: "ERC1155 token standard extensions" },
erc4337: { description: "ERC4337 account abstraction extensions" },
erc4626: { description: "ERC4626 Tokenized Vaults extensions" },
farcaster: { description: "Farcaster protocol extensions" },
lens: { description: "Lens protocol extensions" },
};
return (
<>
<Heading anchorId="built-in-extensions" level={1}>
Built-in extensions for common standards
</Heading>
<Paragraph>
The SDK comes packed with a set of built-in extensions for common
standards. These extensions are designed to make it easy to interact
with popular contracts and protocols. They are available as part of the
SDK and can be used in your application without any additional setup.
</Paragraph>
<Table>
<TBody>
<Tr>
<Th>Standard</Th>
<Th>Import Path</Th>
<Th>Description</Th>
</Tr>
{extensions.map((item) => {
return (
<Tr key={item}>
<Td>{overrides[item]?.name ?? item}</Td>
<Td>
<DocLink
href={`/references/typescript/v5/functions#${item.toLowerCase()}`}
>
thirdweb/extensions/{item.toLowerCase()}
</DocLink>
</Td>
<Td>{overrides[item]?.description ?? `${item} extensions`}</Td>
</Tr>
);
})}
</TBody>
</Table>
<Paragraph>
More extensions are being added regularly. Anyone can{" "}
<DocLink href="/typescript/v5/extensions/create">
create an extension
</DocLink>{" "}
and contribute it back to the repository. You can also{" "}
<DocLink href="/typescript/v5/extensions/generate">
generate extensions
</DocLink>{" "}
for any deployed contract.
</Paragraph>
</>
);
}
@@ -0,0 +1,69 @@
# Generating extensions
You can generate precompiled, optimized extensions for any deployed contract using the thirdweb CLI.
The thirdweb SDK comes with a CLI that can be run with your package manager of choice.
```bash
npx thirdweb generate <chainId>/<contract-address>
```
This will generate a new `thirdweb` directory in your own project, containing the precompiled extension for the contract at the given address.
### Example: Generating an extension for a USDC contract on Optimism
```bash
npx thirdweb generate 10/0x0b2c639c533813f4aa9d7837caf62653d097ff85
```
This will generate the following file `thirdweb/10/0x0b2c639c533813f4aa9d7837caf62653d097ff85.ts` in your project, containing:
- Precompiled, type-safe event definitions
- Precompiled, type-safe function definitions
You can inspect the generated code, modify it, and use it in your project.
### Example: Using a generated extension function
```typescript
import { permit } from "/thirdweb/10/0x0b2c639c533813f4aa9d7837caf62653d097ff85";
const contract = getContract({
client,
chain: optimism,
address: USDC_ADDRESS,
});
// Type-safe function to do a permit transaction
const transaction = permit({
owner: ...,
spender: ...,
value: ...,
deadline: ...,
signature: ...,
});
await sendTransaction({ transaction, account });
```
### Example: Using a generated event
```typescript
import { transferEvent } from "/thirdweb/10/0x0b2c639c533813f4aa9d7837caf62653d097ff85";
const contract = getContract({
client,
chain: optimism,
address: USDC_ADDRESS,
});
// Type-safe event listener
const events = await getContractEvents({
contract,
events: [
transferEvent({
from: ...,
to: ...,
})
],
});
```
+3 -3
View File
@@ -12,10 +12,10 @@ export default async function Layout(props: { children: React.ReactNode }) {
export const metadata = createMetadata({
description:
"Easily create, deploy, and manage smart contracts on any EVM compatible blockchain",
"Easily read, write, deploy, and listen to contract events on any EVM compatible blockchain",
image: {
icon: "contract",
title: "thirdweb contracts",
title: "Contracts",
},
title: "thirdweb Contracts",
title: "Contracts",
});
+701 -111
View File
@@ -1,119 +1,709 @@
import { GithubTemplateCard, ExpandableGrid, createMetadata, OpenSourceCard, DocImage, ArticleIconCard, Grid } from "@doc";
import SupportedChains from "../_images/supported-chains.png";
import { ExternalLinkIcon } from "lucide-react";
import {
Callout,
OpenSourceCard,
createMetadata,
InstallTabs,
SDKCard,
Grid,
ArticleIconCard,
Tabs,
TabsList,
TabsTrigger,
TabsContent,
} from "@doc";
import {
ReactIcon,
TypeScriptIcon,
UnityIcon,
DotNetIcon,
UnrealEngineIcon,
EngineIcon,
} from "@/icons";
import { ExternalLink } from "lucide-react";
export const metadata = createMetadata({
title: "thirdweb Contracts",
description:
"Tools to easily create, deploy, and manage smart contracts on any EVM compatible blockchain.",
image: {
title: "Contracts",
icon: "contracts",
},
title: "Contracts",
description: "Read, write, and deploy smart contracts on any EVM compatible blockchain.",
});
# What are Contracts?
# Get Started
Contracts is an end-to-end development suite which provides tools to develop, deploy, and manage smart contracts.
Read, write, and deploy smart contracts on any EVM compatible blockchain.
---
<Tabs defaultValue="http">
<TabsList>
<TabsTrigger value="http" className="flex items-center gap-2 [&>p]:mb-0">
<EngineIcon className="w-4 h-4 mr-2" />
HTTP
</TabsTrigger>
<TabsTrigger value="typescript" className="flex items-center gap-2 [&>p]:mb-0">
<TypeScriptIcon className="w-4 h-4 mr-2" />
TypeScript
</TabsTrigger>
<TabsTrigger value="react" className="flex items-center gap-2 [&>p]:mb-0">
<ReactIcon className="w-4 h-4 mr-2" />
React
</TabsTrigger>
<TabsTrigger value="reactnative" className="flex items-center gap-2 [&>p]:mb-0">
<ReactIcon className="w-4 h-4 mr-2" />
React Native
</TabsTrigger>
<TabsTrigger value="unity" className="flex items-center gap-2 [&>p]:mb-0">
<UnityIcon className="w-4 h-4 mr-2" />
Unity
</TabsTrigger>
<TabsTrigger value="dotnet" className="flex items-center gap-2 [&>p]:mb-0">
<DotNetIcon className="w-4 h-4 mr-2" />
.NET
</TabsTrigger>
<TabsTrigger value="unreal" className="flex items-center gap-2 [&>p]:mb-0">
<UnrealEngineIcon className="w-4 h-4 mr-2" />
Unreal Engine
</TabsTrigger>
</TabsList>
<TabsContent value="http">
### Read a Contract
You can read contract data efficiently using the [contract read API](https://engine.thirdweb.com/reference).
```http
GET /v1/contract/read
Content-Type: application/json
x-secret-key: <your-project-secret-key>
{
"readOptions": {
"chainId": "1" // your chain id
"from": "0x...", // optional, if you want to read from a specific address
},
"params": [{
"contractAddress": "0x...",
"method": "function allowance(address owner, address spender)",
"params": ["0x...", "0x..."],
}],
}
```
You can batch multiple contract reads in a single request, and the response will be an array of results or errors.
### Write to a Contract
You can write to a contract using the [contract write API](https://engine.thirdweb.com/reference).
```http
POST /v1/contract/write
Content-Type: application/json
x-secret-key: <your-project-secret-key>
{
"executionOptions": {
"from": "0x...", // your server wallet address
"chainId": "1" // your chain id
},
"params": [{
"contractAddress": "0x...",
"method": "function transfer(address to, uint256 amount)",
"params": ["0x...", "1000000000000000000"],
}]
}
```
You can batch multiple contract writes in a single request, and the transactions will be batched atomically onchain.
### Deploy a Contract
You can deploy a contract using the [contract deploy API](https://engine.thirdweb.com/reference).
</TabsContent>
<TabsContent value="typescript">
### Installation
Install the thirdweb SDK in your TypeScript project:
<InstallTabs
npm="npm i thirdweb"
yarn="yarn add thirdweb"
pnpm="pnpm i thirdweb"
bun="bun i thirdweb"
/>
### Set up the Client
First, create a client instance to connect with thirdweb services:
```typescript
import { createThirdwebClient } from "thirdweb";
// - clientId for client-side applications
// - secretKey for server-side applications
const client = createThirdwebClient({
clientId: "YOUR_CLIENT_ID", // Get from your thirdweb dashboard
});
```
### Defining a Contract
You can define a contract using the [`getContract`](/references/typescript/v5/getContract) function.
```tsx
import { getContract, defineChain } from "thirdweb";
const contract = await getContract({
client,
address: "0x...",
chain: defineChain(8453),
});
```
### Read a Contract
You can read contract data using the [`readContract`](/references/typescript/v5/readContract) function.
```typescript
import { readContract, getContract } from "thirdweb";
import { defineChain } from "thirdweb/chains";
const data = await readContract({
contract,
method: "function allowance(address owner, address spender)",
params: ["0x...", "0x..."],
});
```
### Write to a Contract
You can preapre a write transaction to a contract using the [`prepareContractCall`](/references/typescript/v5/prepareContractCall) function, then send it or enqueue it.
You can also use the [catalog of pre-built contract calls](/references/typescript/v5/functions#extensions) to easily prepare a transaction for standards like ERC20, ERC721, ERC1155, and more.
<Tabs defaultValue="frontend">
<TabsList>
<TabsTrigger value="frontend">Frontend</TabsTrigger>
<TabsTrigger value="backend">Backend</TabsTrigger>
</TabsList>
<TabsContent value="frontend">
On the frontend, you can use the [`sendTransaction`](/references/typescript/v5/sendTransaction) function to send a transaction from [user wallets](/wallets/users). The `account` parameter is the wallet that will be used to send the transaction. You can get an account object from a user wallet or a server wallet.
```typescript
import { sendTransaction } from "thirdweb";
// connect user wallet
const wallet = inAppWallet();
const account = await wallet.connect({ client });
// prepare the contract write call
const transaction = prepareContractCall({
contract,
method: "function transfer(address to, uint256 amount)",
params: ["0x...", "1000000000000000000"],
});
// send transaction
const { transactionHash } = await sendTransaction({
account,
transaction,
});
console.log("transaction sent", transactionHash);
```
</TabsContent>
<TabsContent value="backend">
On the backend, you can use a [server wallet](/wallets/servers) to enqueue a transaction. Enqueued transactions is recommended to not block your server. You can then monitor the transaction status using the [transaction monitor](/transactions/monitor) API.
```typescript
import { Engine } from "thirdweb";
// get a server wallet
const wallet = Engine.serverWallet({
client,
address: "0x...",
});
// prepare the contract write call
const transaction = prepareContractCall({
contract,
method: "function transfer(address to, uint256 amount)",
params: ["0x...", "1000000000000000000"],
});
// enqueue the transaction
const { transactionId } = await wallet.enqueueTransaction({
transaction,
simulate: true, // optional, if you want to simulate the transaction before enqueuing it
});
console.log("transaction enqueued", transactionId);
```
</TabsContent>
</Tabs>
</TabsContent>
<TabsContent value="react">
### Installation
Install the thirdweb SDK in your React project:
<InstallTabs
npm="npm i thirdweb"
yarn="yarn add thirdweb"
pnpm="pnpm i thirdweb"
bun="bun i thirdweb"
/>
### Create a Client
First, create a client file (e.g., `thirdwebClient.ts`) for reuse throughout your app:
```typescript
// thirdwebClient.ts
import { createThirdwebClient } from "thirdweb";
export const client = createThirdwebClient({
clientId: "YOUR_CLIENT_ID", // Get from your thirdweb dashboard
});
```
### Setup the Provider
Wrap your application with the ThirdwebProvider:
```tsx
// app.tsx / _app.tsx
import { ThirdwebProvider } from "thirdweb/react";
function App() {
return (
<ThirdwebProvider>
<YourApp />
</ThirdwebProvider>
);
}
```
### Defining a Contract
You can define a contract using the [`getContract`](/references/typescript/v5/getContract) function.
```tsx
import { getContract, defineChain } from "thirdweb";
const contract = await getContract({
client,
address: "0x...",
chain: defineChain(8453),
});
```
### Read a Contract
You can read contract data using the [`useReadContract`](/references/typescript/v5/useReadContract) hook.
```tsx
import { useReadContract } from "thirdweb/react";
import { getContract, defineChain } from "thirdweb";
function YourApp() {
const { data } = useReadContract({
contract,
method: "function allowance(address owner, address spender)",
params: ["0x...", "0x..."],
});
return (
<div>
{data?.toString()}
</div>
);
}
```
### Write to a Contract
You can write to a contract using [`prepareContractCall`](/references/typescript/v5/prepareContractCall) and the [`useSendTransaction`](/references/typescript/v5/useSendTransaction) hook.
```tsx
import { useSendTransaction, useActiveAccount } from "thirdweb/react";
function YourApp() {
const { mutate: sendTransaction, isPending, data } = useSendTransaction();
console.log("transaction hash", data?.transactionHash);
const onClick = () => {
const transaction = prepareContractCall({
contract,
method: "function transfer(address to, uint256 amount)",
params: ["0x...", "1000000000000000000"],
});
// automatically uses the connected wallet as the sender
sendTransaction(transaction);
};
return (
<button onClick={onClick}>
Send Transaction
</button>
);
}
```
You can also use the [catalog of pre-built contract calls](/references/typescript/v5/functions#extensions) to easily prepare a transaction for standards like ERC20, ERC721, ERC1155, and more.
</TabsContent>
<TabsContent value="reactnative">
### Installation
Install the thirdweb SDK in your React Native project:
<InstallTabs
npm="npm i thirdweb"
yarn="yarn add thirdweb"
pnpm="pnpm i thirdweb"
bun="bun i thirdweb"
/>
<Callout variant="info" title="Expo Go Support">
You cannot use Expo Go with thirdweb because native modules are required.
Use an Expo development build (`npx expo prebuild`) or React Native CLI app.
</Callout>
### Create a Client
Create a client once and reuse it throughout your app:
```typescript
import { createThirdwebClient } from "thirdweb";
export const client = createThirdwebClient({
clientId: "YOUR_CLIENT_ID", // Get from your thirdweb dashboard
});
```
<Callout variant="info" title="Allowlist your Bundle ID">
When creating your client ID on the thirdweb dashboard, allowlist your mobile app's bundle ID (e.g., com.yourcompany.app) for security.
</Callout>
### Setup the Provider
Wrap your application with the ThirdwebProvider:
```tsx
import { ThirdwebProvider } from "thirdweb/react";
function App() {
return (
<ThirdwebProvider>
<YourApp />
</ThirdwebProvider>
);
}
```
### Defining a Contract
You can define a contract using the [`getContract`](/references/typescript/v5/getContract) function.
```tsx
import { getContract, defineChain } from "thirdweb";
const contract = await getContract({
client,
address: "0x...",
chain: defineChain(8453),
});
```
### Read a Contract
You can read contract data using the [`useReadContract`](/references/typescript/v5/useReadContract) hook.
```tsx
import { useReadContract } from "thirdweb/react";
import { getContract, defineChain } from "thirdweb";
const contract = await getContract({
client,
address: "0x...",
chain: defineChain(8453),
});
function YourApp() {
const { data } = useReadContract({
contract,
method: "function allowance(address owner, address spender)",
params: ["0x...", "0x..."],
});
return (
<div>
{data?.toString()}
</div>
);
}
```
### Write to a Contract
You can write to a contract using [`prepareContractCall`](/references/typescript/v5/prepareContractCall) and the [`useSendTransaction`](/references/typescript/v5/useSendTransaction) hook.
```tsx
import { useSendTransaction, useActiveAccount } from "thirdweb/react";
function YourApp() {
const { mutate: sendTransaction, isPending, data } = useSendTransaction();
console.log("transaction hash", data?.transactionHash);
const onClick = () => {
const transaction = prepareContractCall({
contract,
method: "function transfer(address to, uint256 amount)",
params: ["0x...", "1000000000000000000"],
});
// automatically uses the connected wallet as the sender
sendTransaction(transaction);
};
return (
<button onClick={onClick}>
Send Transaction
</button>
);
}
```
You can also use the [catalog of pre-built contract calls](/references/typescript/v5/functions#extensions) to easily prepare a transaction for standards like ERC20, ERC721, ERC1155, and more.
</TabsContent>
<TabsContent value="unity">
### Installation
1. Download the latest [thirdweb Unity SDK](https://github.com/thirdweb-dev/unity-sdk/releases) (.unitypackage file)
2. Import the package into your Unity project via Assets > Import Package > Custom Package
### Configure Client ID
After importing the SDK:
1. Go to Project Settings > Thirdweb
2. Enter your Client ID from the thirdweb dashboard
3. Allowlist your game's Bundle ID on the thirdweb dashboard for security
### Read a Contract
You can read contract data using the [`ThirdwebContract.Read`](/dotnet/contracts/read) method.
```csharp
using Thirdweb;
using UnityEngine;
using UnityEngine.UI;
public class TransactionManager : MonoBehaviour
{
private ThirdwebSDK sdk;
public Text walletAddressText;
public Button sendButton;
void Start()
{
// Client ID is set in Project Settings > Thirdweb
sdk = new ThirdwebSDK("ethereum"); // Or any supported chain
sendButton.onClick.AddListener(ReadContract);
}
public async void ReadContract()
{
try {
var contract = await ThirdwebManager.Instance.GetContract(
address: "contract-address",
chainId: 1,
abi: "optional-abi"
);
// Send a transaction
var data = await contract.Read(wallet, contract, "allowance", ownerAddress, spenderAddress);
Debug.Log($"Contract data: {data}");
}
catch (System.Exception e) {
Debug.LogError("Error sending transaction: " + e.Message);
}
}
}
```
### Write to a Contract
You can write to a contract using the [`ThirdwebContract.Write`](/dotnet/contracts/write) method.
```csharp
using Thirdweb;
using UnityEngine;
using UnityEngine.UI;
public class TransactionManager : MonoBehaviour
{
private ThirdwebSDK sdk;
public Text walletAddressText;
public Button sendButton;
void Start()
{
// Client ID is set in Project Settings > Thirdweb
sdk = new ThirdwebSDK("ethereum"); // Or any supported chain
sendButton.onClick.AddListener(SendTransaction);
}
public async void SendTransaction()
{
try {
var contract = await ThirdwebManager.Instance.GetContract(
address: "contract-address",
chainId: 1,
abi: "optional-abi"
);
// Send a transaction
var receipt = await contract.Write(wallet, contract, "transfer", weiValue, toAddress, amount);
Debug.Log($"Transaction receipt: {receipt}");
}
catch (System.Exception e) {
Debug.LogError("Error sending transaction: " + e.Message);
}
}
}
```
</TabsContent>
<TabsContent value="dotnet">
### Installation
Install the thirdweb .NET SDK using NuGet:
```bash
dotnet add package Thirdweb
```
### Initialize the SDK
Create a client instance to connect with thirdweb services:
```csharp
using Thirdweb;
// For client-side applications:
var sdk = new ThirdwebSDK("ethereum", new ThirdwebSDK.Options
{
ClientId = "YOUR_CLIENT_ID" // From thirdweb dashboard
});
// For server-side applications:
// var sdk = new ThirdwebSDK("ethereum", new ThirdwebSDK.Options
// {
// SecretKey = Environment.GetEnvironmentVariable("THIRDWEB_SECRET_KEY")
// });
```
### Read a Contract
You can read contract data using the [`ThirdwebContract.Read`](/dotnet/contracts/read) method.
```csharp
BigInteger chainId = 1; // Ethereum mainnet
string contractAddress = "0x..."; // Your contract address
var contract = await ThirdwebContract.Create(client, contractAddress, chainId);
var data = await contract.Read(wallet, contract, "allowance", ownerAddress, spenderAddress);
Console.WriteLine($"Contract data: {data}");
```
### Write to a Contract
```csharp
BigInteger chainId = 1; // Ethereum mainnet
string contractAddress = "0x..."; // Your contract address
var contract = await ThirdwebContract.Create(client, contractAddress, chainId);
// The wallet that signs and sends the transaction
var wallet = await PrivateKeyWallet.Create(client, "yourPrivateKeyHex");
// Assuming transfer takes an address and an amount as parameters
string toAddress = "0x...";
BigInteger amount = new BigInteger(1000); // The amount to transfer
// No ether is being sent in this non-payable transaction, so weiValue is 0
BigInteger weiValue = BigInteger.Zero;
// Executing the transfer
var receipt = await contract.Write(wallet, contract, "transfer", weiValue, toAddress, amount);
Console.WriteLine($"Transaction receipt: {receipt}");
```
</TabsContent>
<TabsContent value="unreal">
### Installation
1. Download the thirdweb Unreal Engine plugin from the [Unreal Engine Marketplace](https://www.unrealengine.com/marketplace/en-US/product/thirdweb)
2. Add the plugin to your Unreal project
3. Enable the plugin in your project settings
### Configure Client ID
1. Go to Edit > Project Settings > Thirdweb
2. Enter your Client ID from the thirdweb dashboard
3. Enter your Bundle ID (must match what was allowlisted on the thirdweb dashboard)
### Read and Write to a Contract
You can read and write to a contract using the [Engine Blueprint](/unreal-engine/blueprints/engine).
</TabsContent>
</Tabs>
## Going further
- [Deploy Contracts](/contracts/deploy)
- [Contract Events](/contracts/read)
## Explore Full API References
For comprehensive guides on implementing the full thirdweb SDK, explore our language-specific documentation:
<Grid>
<ArticleIconCard
title="Deployment Tool"
icon={ExternalLinkIcon}
href="/contracts/deploy/overview"
description="Securely deploy any smart contract."
/>
<ArticleIconCard
title="Explore"
icon={ExternalLinkIcon}
href="/contracts/explore/overview"
description="Audited and expansive library of contracts."
/>
<ArticleIconCard
title="Modular Contracts"
icon={ExternalLinkIcon}
href="/contracts/explore/overview"
description="Build customizable smart contracts."
/>
<SDKCard
title="TypeScript"
href="/references/typescript/v5"
icon={TypeScriptIcon}
/>
<SDKCard title="React" href="/references/typescript/v5" icon={ReactIcon} />
<SDKCard
title="React Native"
href="/references/typescript/v5"
icon={ReactIcon}
/>
<SDKCard title="DotNet" href="/dotnet/getting-started" icon={DotNetIcon} />
<SDKCard title="Unity" href="/unity/v5/getting-started" icon={UnityIcon} />
<SDKCard
title="Unreal Engine"
href="/unreal-engine/getting-started"
icon={UnrealEngineIcon}
/>
</Grid>
<OpenSourceCard title="Contracts" href="https://github.com/thirdweb-dev/contracts" />
### With Contracts, you can:
- Easily deploy custom or pre-built contracts to [any EVM network](https://thirdweb.com/chainlist)
- Create and publish contracts for your team or community to utilize with an easy-to-deploy interface
- Create reusable contract components or modules to add to modular contracts to upgrade functionality
- Manage contract functionality, upload NFTs, set distribution mechanisms, and more directly from the dashboard
- Reduce development time by using an existing library of contracts with accompanying SDK functions and dashboard integrations to interact with contracts
### Templates
<ExpandableGrid>
<GithubTemplateCard
title="Hardhat JavaScript Starter"
href="https://github.com/thirdweb-example/hardhat-javascript-starter"
/>
<GithubTemplateCard
title="Hardhat TypeScript Starter"
href="https://github.com/thirdweb-example/hardhat-typescript-starter"
/>
<GithubTemplateCard
title="Forge Starter"
href="https://github.com/thirdweb-example/forge-starter"
/>
<GithubTemplateCard
title="Solidity Hello World"
href="https://github.com/thirdweb-example/solidity-hello-world"
/>
<GithubTemplateCard
title="Smart Account Upgrades"
href="https://github.com/thirdweb-example/smart-account-upgrades"
/>
<GithubTemplateCard
title="Tiered Loyalty Contract"
href="https://github.com/thirdweb-example/tiered-loyalty-contract"
/>
<GithubTemplateCard
title="ERC-6551"
href="https://github.com/thirdweb-example/erc-6551"
/>
<GithubTemplateCard
title="Anvil Local Node"
href="https://github.com/thirdweb-example/anvil-local-node"
/>
<GithubTemplateCard
title="Soulbound Token"
href="https://github.com/thirdweb-example/soulbound-token"
/>
<GithubTemplateCard
title="Onchain NFT Metadata"
href="https://github.com/thirdweb-example/on-chain-nft-metadata"
/>
<GithubTemplateCard
title="ERC-721 NFT Collection with Deploy & Hardhat"
href="https://github.com/thirdweb-example/erc721a-thirdweb-deploy"
/>
<GithubTemplateCard
title="Token Gated Account"
href="https://github.com/thirdweb-example/token-gated-account"
/>
</ExpandableGrid>
## Supported Chains
Contracts is supported on every EVM compatible chain. To view the full list, visit [thirdweb chainlist](https://thirdweb.com/chainlist?service=contracts).
<DocImage src={SupportedChains} />
+62 -812
View File
@@ -1,847 +1,97 @@
import { ZapIcon } from "lucide-react";
import type { SideBar } from "@/components/Layouts/DocLayout";
import { ContractModularContractIcon } from "@/icons";
import {
DotNetIcon,
ReactIcon,
TypeScriptIcon,
UnityIcon,
UnrealEngineIcon,
} from "@/icons";
const prebuiltSlug = "/contracts/explore/pre-built-contracts";
const prebuiltModular = "/contracts/explore/pre-built-modular";
const modularContractsSlug = "/contracts/modular-contracts";
const deploySlug = "/contracts/deploy";
const publishSlug = "/contracts/publish";
const designDocs = "/contracts/design-docs";
const modulesContractsSlug = "/contracts/modular-contracts/module-contracts";
const coreContractsSlug = "/contracts/modular-contracts/core-contracts";
// TODO: Deprecate links that start with the following slugs
const buildSlug = "/contracts/build";
const extensionsSlug = "/contracts/build/extensions";
const baseContractsSlug = "/contracts/build/base-contracts";
const slug = "/contracts";
export const sidebar: SideBar = {
name: "Contracts",
links: [
{
href: "/contracts",
name: "Overview",
href: slug,
name: "Get Started",
icon: <ZapIcon />,
},
{ separator: true },
{
isCollapsible: false,
links: [
{
href: `${deploySlug}/overview`,
name: "Overview",
href: `${slug}/extensions`,
name: "Use Extensions",
},
{
href: `${deploySlug}/deploy-contract`,
name: "Deploy Contract",
href: `${slug}/generate`,
name: "Generate Extensions",
},
{
href: `${publishSlug}/publish-contract`,
name: "Publish Contract",
href: `${slug}/events`,
name: "Listen to Events",
},
{
href: `${deploySlug}/reference`,
name: "CLI Reference",
href: `${slug}/deploy`,
name: "Deploy Contracts",
},
/**
* TODO
{
href: `${slug}/encode`,
name: "Encode Data",
},
{
href: `${publishSlug}/publish-options`,
name: "Publish Options",
href: `${slug}/decode`,
name: "Decode Data",
},
{
href: `${slug}/fetch-abis`,
name: "Fetch ABIs",
},
*/
],
name: "Deployment Tools",
},
// explore
{
isCollapsible: false,
links: [
{
href: "/contracts/explore/overview",
name: "Overview",
},
{
links: [
{
links: [
{
href: `${prebuiltModular}/token`,
name: "Token",
},
{
href: `${prebuiltModular}/token-drop`,
name: "Token Drop",
},
],
name: "ERC-20",
},
{
links: [
{
href: `${prebuiltModular}/nft-collection`,
name: "NFT Collection",
},
{
href: `${prebuiltModular}/nft-drop`,
name: "NFT Drop",
},
{
href: `${prebuiltModular}/open-edition`,
name: "Open Edition",
},
],
name: "ERC-721",
},
{
links: [
{
href: `${prebuiltModular}/edition`,
name: "Edition",
},
{
href: `${prebuiltModular}/edition-drop`,
name: "Edition Drop",
},
],
name: "ERC-1155",
},
],
name: "Pre-built Modular",
},
{
links: [
{
links: [
{
href: `${prebuiltSlug}/token`,
name: "Token",
},
{
href: `${prebuiltSlug}/token-drop`,
name: "Token Drop",
},
{
href: `${prebuiltSlug}/stake-erc20`,
name: "Stake ERC-20",
},
{
href: `${prebuiltSlug}/airdrop-erc20`,
name: "Airdrop ERC-20",
},
{
href: `${prebuiltSlug}/airdrop-erc20-claimable`,
name: "Airdrop ERC-20 (Claimable)",
},
],
name: "ERC-20",
},
{
links: [
{
href: `${prebuiltSlug}/nft-collection`,
name: "NFT Collection",
},
{
href: `${prebuiltSlug}/nft-drop`,
name: "NFT Drop",
},
{
href: `${prebuiltSlug}/loyalty-card`,
name: "Loyalty Card",
},
{
href: `${prebuiltSlug}/open-edition`,
name: "Open Edition",
},
{
href: `${prebuiltSlug}/stake-erc721`,
name: "Stake ERC-721",
},
{
href: `${prebuiltSlug}/airdrop-erc721`,
name: "Airdrop ERC-721",
},
{
href: `${prebuiltSlug}/airdrop-erc721-claimable`,
name: "Airdrop ERC-721 (Claimable)",
},
],
name: "ERC-721",
},
{
links: [
{
href: `${prebuiltSlug}/edition`,
name: "Edition",
},
{
href: `${prebuiltSlug}/edition-drop`,
name: "Edition Drop",
},
{
href: `${prebuiltSlug}/stake-erc1155`,
name: "Stake ERC-1155",
},
{
href: `${prebuiltSlug}/airdrop-erc1155`,
name: "Airdrop ERC-1155",
},
{
href: `${prebuiltSlug}/airdrop-erc1155-claimable`,
name: "Airdrop ERC-1155 (Claimable)",
},
],
name: "ERC-1155",
},
{
links: [
{
href: `${prebuiltSlug}/account-factory`,
name: "Account Factory",
},
{
href: `${prebuiltSlug}/managed-account-factory`,
name: "Managed Account Factory",
},
],
name: "ERC-4337",
},
{
links: [
{
href: `${prebuiltSlug}/marketplace`,
name: "Marketplace",
},
{
href: `${prebuiltSlug}/multiwrap`,
name: "Multiwrap",
},
{
href: `${prebuiltSlug}/split`,
name: "Split",
},
{
href: `${prebuiltSlug}/vote`,
name: "Vote",
},
],
name: "MISC.",
},
],
name: "Pre-built Standard",
},
],
name: "Explore (Contract Library)",
},
{ separator: true },
// modular contracts
{
isCollapsible: false,
links: [
{
href: `${modularContractsSlug}/overview`,
name: "Overview",
},
{
href: `${modularContractsSlug}/how-it-works`,
name: "How it works",
},
{
href: `${modularContractsSlug}/get-started`,
links: [
{
href: `${modularContractsSlug}/get-started/create-core-contract`,
name: "Create a Core Contract",
},
{
href: `${modularContractsSlug}/get-started/create-module-contract`,
name: "Create a Module Contract",
},
{
href: `${modularContractsSlug}/get-started/deploy-modular-contract`,
name: "Deploy a Modular Contract",
},
],
name: "Get Started",
},
{
links: [
{
href: `${modularContractsSlug}/tutorials/deploy-erc20-core`,
name: "Deploy ERC-20 Core",
},
],
name: "Tutorials",
},
// core contracts
{
links: [
{
href: `${coreContractsSlug}/erc-20`,
name: "ERC-20",
},
{
href: `${coreContractsSlug}/erc-721`,
name: "ERC-721",
},
{
href: `${coreContractsSlug}/erc-1155`,
name: "ERC-1155",
},
],
name: "Core Contracts",
},
// modules
{
links: [
{
links: [
{
links: [
{
href: `${modulesContractsSlug}/erc-20/minting/claimableERC20`,
name: "ClaimableERC20",
},
{
href: `${modulesContractsSlug}/erc-20/minting/mintableERC20`,
name: "MintableERC20",
},
],
name: "Minting",
},
{
links: [
{
href: `${modulesContractsSlug}/erc-20/misc/transferableERC20`,
name: "TransferableERC20",
},
{
href: `${modulesContractsSlug}/erc-20/misc/creatorTokenERC20`,
name: "CreatorTokenERC20",
},
],
name: "Miscellaneous",
},
],
name: "ERC-20",
},
{
links: [
{
links: [
{
href: `${modulesContractsSlug}/erc-721/metadata/batchMetadataERC721`,
name: "BatchMetadataERC721",
},
{
href: `${modulesContractsSlug}/erc-721/metadata/openEditionMetadataERC721`,
name: "OpenEditionMetadataERC721",
},
],
name: "Metadata",
},
{
links: [
{
href: `${modulesContractsSlug}/erc-721/minting/claimableERC721`,
name: "ClaimableERC721",
},
{
href: `${modulesContractsSlug}/erc-721/minting/mintableERC721`,
name: "MintableERC721",
},
],
name: "Minting",
},
{
links: [
{
href: `${modulesContractsSlug}/erc-721/misc/royaltyERC721`,
name: "RoyaltyERC721",
},
{
href: `${modulesContractsSlug}/erc-721/misc/transferableERC721`,
name: "TransferableERC721",
},
],
name: "Miscellaneous",
},
],
name: "ERC-721",
},
{
links: [
{
links: [
{
href: `${modulesContractsSlug}/erc-1155/metadata/batchMetadataERC1155`,
name: "BatchMetadataERC1155",
},
{
href: `${modulesContractsSlug}/erc-1155/metadata/openEditionMetadataERC1155`,
name: "OpenEditionMetadataERC1155",
},
],
name: "Metadata",
},
{
links: [
{
href: `${modulesContractsSlug}/erc-1155/minting/claimableERC1155`,
name: "ClaimableERC1155",
},
{
href: `${modulesContractsSlug}/erc-1155/minting/mintableERC1155`,
name: "MintableERC1155",
},
],
name: "Minting",
},
{
links: [
{
href: `${modulesContractsSlug}/erc-1155/misc/royaltyERC1155`,
name: "RoyaltyERC1155",
},
{
href: `${modulesContractsSlug}/erc-1155/misc/transferableERC1155`,
name: "TransferableERC1155",
},
{
href: `${modulesContractsSlug}/erc-1155/misc/sequentialTokenIdERC1155`,
name: "SequentialTokenIdERC1155",
},
],
name: "Miscellaneous",
},
],
name: "ERC-1155",
},
{
links: [
{
href: `${modulesContractsSlug}/cross-chain/agglayer`,
name: "Agglayer",
},
],
name: "Cross-Chain",
},
],
name: "Module Contracts",
},
],
name: "Modular Contract Framework",
},
{ separator: true },
// build
{
icon: <ContractModularContractIcon />,
isCollapsible: false,
links: [
{
href: `${buildSlug}/overview`,
name: "Overview",
},
{
href: `${buildSlug}/get-started`,
name: "Get Started",
},
// modular contracts
{
href: `${buildSlug}/modular-contracts`,
name: "Modular Contracts",
},
// base contracts
{
href: `${baseContractsSlug}`,
links: [
{
links: [
{
href: `${baseContractsSlug}/erc-20/base`,
name: "Base",
},
{
href: `${baseContractsSlug}/erc-20/drop`,
name: "Drop",
},
{
href: `${baseContractsSlug}/erc-20/drop-vote`,
name: "Drop Vote",
},
{
href: `${baseContractsSlug}/erc-20/signature-mint`,
name: "Signature Mint",
},
{
href: `${baseContractsSlug}/erc-20/signature-mint-vote`,
name: "Signature Mint Vote",
},
{
href: `${baseContractsSlug}/erc-20/vote`,
name: "Vote",
},
],
name: "ERC-20",
},
{
links: [
{
href: `${baseContractsSlug}/erc-721/base`,
name: "Base",
},
{
href: `${baseContractsSlug}/erc-721/delayed-reveal`,
name: "Delayed Reveal",
},
{
href: `${baseContractsSlug}/erc-721/drop`,
name: "Drop",
},
{
href: `${baseContractsSlug}/erc-721/lazy-mint`,
name: "Lazy Mint",
},
{
href: `${baseContractsSlug}/erc-721/signature-mint`,
name: "Signature Mint",
},
],
name: "ERC-721",
},
{
links: [
{
href: `${baseContractsSlug}/erc-1155/base`,
name: "Base",
},
{
href: `${baseContractsSlug}/erc-1155/delayed-reveal`,
name: "Delayed Reveal",
},
{
href: `${baseContractsSlug}/erc-1155/drop`,
name: "Drop",
},
{
href: `${baseContractsSlug}/erc-1155/lazy-mint`,
name: "Lazy Mint",
},
{
href: `${baseContractsSlug}/erc-1155/signature-mint`,
name: "Signature Mint",
},
],
name: "ERC-1155",
},
{
href: `${baseContractsSlug}/erc-4337`,
links: [
{
href: `${baseContractsSlug}/erc-4337/account`,
name: "Account",
},
{
href: `${baseContractsSlug}/erc-4337/account-factory`,
name: "Account Factory",
},
{
href: `${baseContractsSlug}/erc-4337/managed-account`,
name: "Managed Account",
},
{
href: `${baseContractsSlug}/erc-4337/managed-account-factory`,
name: "Managed Account Factory",
},
],
name: "ERC-4337",
},
],
name: "Base Contracts",
},
// extensions
{
href: `${extensionsSlug}`,
links: [
{
links: [
{
href: `${extensionsSlug}/general/BatchMintMetadata`,
name: "BatchMintMetadata",
},
{
href: `${extensionsSlug}/general/ContractMetadata`,
name: "ContractMetadata",
},
{
href: `${extensionsSlug}/general/DelayedReveal`,
name: "DelayedReveal",
},
{
href: `${extensionsSlug}/general/Drop`,
name: "Drop",
},
{
href: `${extensionsSlug}/general/DropSinglePhase`,
name: "DropSinglePhase",
},
{
href: `${extensionsSlug}/general/LazyMint`,
name: "LazyMint",
},
{
href: `${extensionsSlug}/general/Multicall`,
name: "Multicall",
},
{
href: `${extensionsSlug}/general/Ownable`,
name: "Ownable",
},
{
href: `${extensionsSlug}/general/Permissions`,
name: "Permissions",
},
{
href: `${extensionsSlug}/general/PermissionsEnumerable`,
name: "PermissionsEnumerable",
},
{
href: `${extensionsSlug}/general/PlatformFee`,
name: "PlatformFee",
},
{
href: `${extensionsSlug}/general/PrimarySale`,
name: "PrimarySale",
},
{
href: `${extensionsSlug}/general/Royalty`,
name: "Royalty",
},
],
name: "General",
},
{
links: [
{
href: `${extensionsSlug}/erc-20/ERC20`,
name: "ERC20",
},
{
href: `${extensionsSlug}/erc-20/ERC20BatchMintable`,
name: "ERC20BatchMintable",
},
{
href: `${extensionsSlug}/erc-20/ERC20Burnable`,
name: "ERC20Burnable",
},
{
href: `${extensionsSlug}/erc-20/ERC20ClaimConditions`,
name: "ERC20ClaimConditions",
},
{
href: `${extensionsSlug}/erc-20/ERC20Mintable`,
name: "ERC20Mintable",
},
{
href: `${extensionsSlug}/erc-20/ERC20Permit`,
name: "ERC20Permit",
},
{
href: `${extensionsSlug}/erc-20/ERC20SignatureMint`,
name: "ERC20SignatureMint",
},
{
href: `${extensionsSlug}/erc-20/ERC20Staking`,
name: "ERC20Staking",
},
],
name: "ERC-20",
},
{
links: [
{
href: `${extensionsSlug}/erc-721/ERC721`,
name: "ERC721",
},
{
href: `${extensionsSlug}/erc-721/ERC721BatchMintable`,
name: "ERC721BatchMintable",
},
{
href: `${extensionsSlug}/erc-721/ERC721Burnable`,
name: "ERC721Burnable",
},
{
href: `${extensionsSlug}/erc-721/ERC721ClaimConditions`,
name: "ERC721ClaimConditions",
},
{
href: `${extensionsSlug}/erc-721/ERC721ClaimCustom`,
name: "ERC721ClaimCustom",
},
{
href: `${extensionsSlug}/erc-721/ERC721ClaimPhases`,
name: "ERC721ClaimPhases",
},
{
href: `${extensionsSlug}/erc-721/ERC721Claimable`,
name: "ERC721Claimable",
},
{
href: `${extensionsSlug}/erc-721/ERC721Enumerable`,
name: "ERC721Enumerable",
},
{
href: `${extensionsSlug}/erc-721/ERC721Mintable`,
name: "ERC721Mintable",
},
{
href: `${extensionsSlug}/erc-721/ERC721Revealable`,
name: "ERC721Revealable",
},
{
href: `${extensionsSlug}/erc-721/ERC721SignatureMint`,
name: "ERC721SignatureMint",
},
{
href: `${extensionsSlug}/erc-721/ERC721Staking`,
name: "ERC721Staking",
},
{
href: `${extensionsSlug}/erc-721/ERC721Supply`,
name: "ERC721Supply",
},
],
name: "ERC-721",
},
{
links: [
{
href: `${extensionsSlug}/erc-1155/ERC1155`,
name: "ERC1155",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155BatchMintable`,
name: "ERC1155BatchMintable",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Burnable`,
name: "ERC1155Burnable",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155ClaimConditions`,
name: "ERC1155ClaimConditions",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155ClaimCustom`,
name: "ERC1155ClaimCustom",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155ClaimPhases`,
name: "ERC1155ClaimPhases",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Claimable`,
name: "ERC1155Claimable",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Drop`,
name: "ERC1155Drop",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155DropSinglePhase`,
name: "ERC1155DropSinglePhase",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Enumerable`,
name: "ERC1155Enumerable",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Mintable`,
name: "ERC1155Mintable",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Revealable`,
name: "ERC1155Revealable",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155SignatureMint`,
name: "ERC1155SignatureMint",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Staking`,
name: "ERC1155Staking",
},
{
href: `${extensionsSlug}/erc-1155/ERC1155Supply`,
name: "ERC1155Supply",
},
],
name: "ERC-1155",
},
{
links: [
{
href: `${extensionsSlug}/erc-4337/SmartWallet`,
name: "SmartWallet",
},
{
href: `${extensionsSlug}/erc-4337/SmartWalletFactory`,
name: "SmartWalletFactory",
},
],
name: "ERC-4337",
},
],
name: "Extensions",
},
// stylus
{
href: `${buildSlug}/stylus`,
name: "Arbitrum Stylus",
},
],
name: "Build",
name: "Guides",
},
{ separator: true },
// resources
{
isCollapsible: false,
links: [
{
href: "/contracts/faq",
name: "FAQs",
href: "/references/typescript/v5/functions#transactions",
icon: <TypeScriptIcon />,
name: "TypeScript",
},
{
links: [
{
href: `${designDocs}/modular-contracts`,
name: "Modular Contracts",
},
{
href: `${designDocs}/drop`,
name: "Drop",
},
{
href: `${designDocs}/marketplace`,
name: "Marketplace",
},
{
href: `${designDocs}/multiwrap`,
name: "Multiwrap",
},
{
href: `${designDocs}/pack`,
name: "Pack",
},
{
href: `${designDocs}/signature-mint`,
name: "Signature Mint",
},
],
name: "Design Docs",
href: "/references/typescript/v5/hooks#transactions",
icon: <ReactIcon />,
name: "React",
},
{
href: "/references/typescript/v5/hooks#transactions",
icon: <ReactIcon />,
name: "React Native",
},
{
href: "/dotnet",
icon: <DotNetIcon />,
name: "Dotnet",
},
{
href: "/unity",
icon: <UnityIcon />,
name: "Unity",
},
{
href: "/unreal-engine",
icon: <UnrealEngineIcon />,
name: "Unreal Engine",
},
],
name: "Resources",
name: "API References",
},
],
name: "Contracts",
};
@@ -57,7 +57,7 @@ The relayer will be assigned a URL in this format: `https://<engine_url>/relayer
## Submit a meta transaction from your app frontend
Use the [Connect SDK](/react) to prompt the user to sign transactions and send it this relayer.
Use the [TypeScript SDK]](/react) to prompt the user to sign transactions and send it this relayer.
First wrap your app with `<ThirdwebProvider>`:
+10
View File
@@ -108,6 +108,16 @@
}
}
@layer utilities {
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
}
code span {
color: var(--code-light-color);
}
@@ -27,8 +27,8 @@ export const sidebar: SideBar = {
{
links: [
{
href: "/connect",
name: "Connect SDK",
href: "/wallets",
name: "TypeScript SDK",
},
{
href: `${storageSlug}/how-to-use-storage/upload-files-to-ipfs`,
+1 -1
View File
@@ -53,7 +53,7 @@ export default function RootLayout({
<div className="relative flex min-h-screen flex-col">
<StickyTopContainer>
{/* <Banner
href="https://thirdweb.com/connect/universal-bridge"
href="https://thirdweb.com/payments"
text="Let users pay with whatever they have without leaving your app"
/> */}
<Header />
@@ -105,7 +105,7 @@ async function handleNebulaResponse(response) {
secretKey: process.env.THIRDWEB_SECRET_KEY,
});
// You can use any wallet- see https://portal.thirdweb.com/connect/external-wallets
// You can use any wallet- see https://portal.thirdweb.com/wallets/external-wallets
const account = await generateAccount({ client });
if (response.actions && response.actions.length > 0) {
+122 -117
View File
@@ -1,10 +1,11 @@
import { MessageCircleIcon, WebhookIcon } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { Grid, Heading, SDKCard } from "@/components/Document";
import { Heading } from "@/components/Document";
import { Button } from "@/components/ui/button";
import {
DotNetIcon,
ExternalLinkIcon,
ReactIcon,
TypeScriptIcon,
UnityIcon,
@@ -15,14 +16,13 @@ import { ConnectIcon } from "../icons/products/ConnectIcon";
import { EngineIcon } from "../icons/products/EngineIcon";
import { InsightIcon } from "../icons/products/InsightIcon";
import { PlaygroundIcon } from "../icons/products/PlaygroundIcon";
import { cn } from "../lib/utils";
import DocsHeroDark from "./_images/docs-hero-dark.png";
import DocsHeroLight from "./_images/docs-hero-light.png";
export default function Page() {
return (
<main className="container max-w-[900px] grow pb-20" data-noindex>
<main className="container max-w-5xl grow pb-20" data-noindex>
<Hero />
<div className="grid grid-cols-1 gap-8">
<div className="space-y-8">
<PlaygroundSection />
<LearningResourcesSection />
<ReferenceSection />
@@ -33,7 +33,7 @@ export default function Page() {
function Hero() {
return (
<section className="grid gap-4 py-14 lg:grid-cols-2 lg:py-0">
<section className="grid gap-4 py-14 lg:grid-cols-[1fr_420px] lg:py-0">
{/* Left */}
<div className="flex flex-col justify-center">
<div>
@@ -43,13 +43,14 @@ function Hero() {
<p className="mb-8 max-w-md text-lg text-muted-foreground leading-normal">
Development framework for building onchain apps, games, and agents.
</p>
<Link href="/chat">
<Button className="flex items-center gap-2">
<MessageCircleIcon className="size-4" />
Ask AI
<div className="flex">
<Button className="flex items-center gap-2" asChild>
<Link href="/chat">
<MessageCircleIcon className="size-4" />
Ask AI
</Link>
</Button>
</Link>
</div>
</div>
</div>
@@ -79,86 +80,67 @@ function PlaygroundSection() {
function ReferenceSection() {
return (
<section>
<SectionTitle anchorId="reference" title="API Reference" />
<SectionTitle
anchorId="client"
className="text-muted-foreground"
level={4}
title="Client libraries"
/>
<Grid>
<SDKCard
href="/references/typescript/v5"
icon={TypeScriptIcon}
title="TypeScript"
/>
<SDKCard
href="/references/typescript/v5"
icon={ReactIcon}
title="React"
/>
<SDKCard
href="/references/typescript/v5"
icon={ReactIcon}
title="React Native"
/>
<SDKCard href="/dotnet" icon={DotNetIcon} title="DotNet" />
<SDKCard href="/unity" icon={UnityIcon} title="Unity" />
<SDKCard
href="/unreal-engine"
icon={UnrealEngineIcon}
title="Unreal Engine"
/>
</Grid>
<SectionTitle
anchorId="backend"
className="text-muted-foreground"
level={4}
title="Backend APIs"
/>
<Grid>
<SDKCard
href="https://engine.thirdweb.com/reference"
icon={EngineIcon}
iconClassName="text-muted-foreground"
isExternal
title="Engine"
/>
<SDKCard
href="https://insight.thirdweb.com/reference"
icon={InsightIcon}
iconClassName="text-muted-foreground"
isExternal
title="Insight"
/>
<SDKCard
href="https://bridge.thirdweb.com/reference"
icon={BridgeIcon}
iconClassName="text-muted-foreground"
isExternal
title="Payments"
/>
<SDKCard
href="/connect/wallet/get-users"
icon={ConnectIcon} // TODO: actual openAPI docs
iconClassName="text-muted-foreground"
title="Wallets"
/>
<SDKCard
href="/connect/account-abstraction/api"
icon={ConnectIcon} // TODO: actual openAPI docs
iconClassName="text-muted-foreground"
title="Bundler"
/>
<SDKCard
href="/webhooks"
icon={WebhookIcon}
iconClassName="text-muted-foreground"
title="Webhooks"
/>
</Grid>
</section>
<>
<section>
<SectionTitle anchorId="client" title="Client libraries" />
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
<SDKCard
href="/references/typescript/v5"
icon={TypeScriptIcon}
title="TypeScript"
/>
<SDKCard
href="/references/typescript/v5"
icon={ReactIcon}
title="React"
/>
<SDKCard
href="/references/typescript/v5"
icon={ReactIcon}
title="React Native"
/>
<SDKCard href="/dotnet" icon={DotNetIcon} title="DotNet" />
<SDKCard href="/unity" icon={UnityIcon} title="Unity" />
<SDKCard
href="/unreal-engine"
icon={UnrealEngineIcon}
title="Unreal Engine"
/>
</div>
</section>
<section>
<SectionTitle anchorId="backend" title="Backend APIs" />
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
<SDKCard
href="https://engine.thirdweb.com/reference"
icon={EngineIcon}
title="Engine"
/>
<SDKCard
href="https://insight.thirdweb.com/reference"
icon={InsightIcon}
title="Insight"
/>
<SDKCard
href="https://bridge.thirdweb.com/reference"
icon={BridgeIcon}
title="Payments"
/>
<SDKCard
href="/wallets/get-users"
icon={ConnectIcon} // TODO: actual openAPI docs
title="Wallets"
/>
<SDKCard
href="/bundler"
icon={ConnectIcon} // TODO: actual openAPI docs
title="Bundler"
/>
<SDKCard href="/webhooks" icon={WebhookIcon} title="Webhooks" />
</div>
</section>
</>
);
}
@@ -166,7 +148,7 @@ function LearningResourcesSection() {
return (
<section>
<SectionTitle anchorId="learning" title="Documentation" />
<Grid className="md:grid-cols-1 lg:grid-cols-3">
<div className="grid gap-4 md:grid-cols-1 lg:grid-cols-3">
<ArticleCardIndex
description="Create and manage crypto wallets"
href="/wallets"
@@ -203,24 +185,14 @@ function LearningResourcesSection() {
icon={ConnectIcon}
title="Vault"
/>
</Grid>
</div>
</section>
);
}
function SectionTitle(props: {
title: string;
anchorId: string;
level?: number;
className?: string;
}) {
function SectionTitle(props: { title: string; anchorId: string }) {
return (
<Heading
anchorClassName="mb-4 mt-0"
anchorId={props.anchorId}
className={cn(props.className)}
level={props.level || 2}
>
<Heading anchorId={props.anchorId} anchorClassName="mb-2" level={2}>
{props.title}
</Heading>
);
@@ -233,22 +205,55 @@ function ArticleCardIndex(props: {
title: string;
description: string;
href: string;
icon?: React.FC<{ className?: string }>;
icon: React.FC<{ className?: string }>;
external?: boolean;
}) {
return (
<Link
className="flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:border-active-border"
href={props.href}
target={props.external ? "_blank" : undefined}
>
<div className="flex items-start gap-3">
{props.icon && <props.icon className="text-foreground size-6" />}
<div className="flex flex-col gap-0.5">
<h3 className="font-semibold text-foreground">{props.title}</h3>
<p className="text-sm text-muted-foreground">{props.description}</p>
<div className="rounded-lg border bg-card p-4 hover:border-active-border relative">
<div className="flex mb-3">
<div className="p-2 rounded-full border bg-background">
<props.icon className="size-5 text-muted-foreground" />
</div>
</div>
</Link>
<h3 className="mb-0.5 font-medium text-lg tracking-tight">
<Link
className="before:absolute before:inset-0"
href={props.href}
target={props.external ? "_blank" : undefined}
>
{props.title}
</Link>
</h3>
<p className="text-sm text-muted-foreground">{props.description}</p>
</div>
);
}
function SDKCard(props: {
title: string;
href: string;
icon: React.FC<{ className?: string }>;
}) {
return (
<div className="relative flex items-center gap-3 rounded-lg border bg-card p-4 transition-colors hover:border-active-border text-foreground/80 hover:text-foreground">
<div className="p-2 rounded-full border bg-background">
<props.icon className="size-4 shrink-0" />
</div>
<div className="flex flex-col">
<h3 className="font-medium text-base text-foreground mb-0.5">
<Link
href={props.href}
target={props.href.includes("http") ? "_blank" : undefined}
className="before:absolute before:inset-0"
>
{props.title}
</Link>
</h3>
<p className="inline-flex items-center gap-1 text-muted-foreground text-xs">
View docs
<ExternalLinkIcon className="size-3.5 shrink-0 text-muted-foreground/50" />
</p>
</div>
</div>
);
}
+1 -1
View File
@@ -45,7 +45,7 @@ Yes, Payments is designed to be agnostic to wallet infrastructure. You can use i
</Details>
<Details summary="Does Payments support Apple Pay or Google Pay?">
Apple Pay and Google Pay are supported through the onramp providers depending on region. Coinbase, Stripe, and Transak currently support Apple Pay. Transak supports Google Pay. [Learn more about the supported onramp providers.](/connect/pay/onramp-providers).
Apple Pay and Google Pay are supported through the onramp providers depending on region. Coinbase, Stripe, and Transak currently support Apple Pay. Transak supports Google Pay.
</Details>
<Details summary="What are the KYC requirements?">
@@ -27,7 +27,7 @@ In this guide, we'll show you how to purchase 10 USDC on Optimism in Typescript.
---
<Steps>
<Step title='Install the Connect SDK'>
<Step title='Install the TypeScript SDK'>
<InstallTabs
npm="npm i thirdweb"
yarn="yarn add thirdweb"
@@ -35,7 +35,7 @@ In this guide, we'll show you how to purchase 10 USDC on Optimism in Typescript.
/>
<Step title='Get Your Client ID'>
Log in to the [thirdweb dashboard](https://thirdweb.com/team). Click on Create New > Project to get your **Client ID**. You'll need your Client ID to interact with the Connect SDK.
Log in to the [thirdweb dashboard](https://thirdweb.com/team). Click on Create New > Project to get your **Client ID**. You'll need your Client ID to interact with the TypeScript SDK.
</Step>
</Step>
@@ -21,8 +21,8 @@ import {
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Custom Payment Data",
icon: "payments",
},
title: "Custom Payment Data",
description: "Pass custom app data to payments to be included on webhooks, payment history, and more.",
@@ -92,7 +92,7 @@ Associate user IDs, custom payment IDs, order details, and more with any payment
amount="0.1"
purchaseData={{
userId: "user-123",
orderId: "order-456",
orderId: "order-456",
productType: "wallet-funding",
metadata: {
source: "app",
@@ -195,7 +195,7 @@ To connect with other auth strategies, use external wallets, or sponsor gas for
- [Buy.prepare](/references/typescript/v5/buy/prepare)
- [Sell.prepare](/references/typescript/v5/sell/prepare)
- [BuyWidget](/references/typescript/v5/buywidget)
- [CheckoutWidget](/references/typescript/v5/checkoutwidget)
- [TransactionWidget](/references/typescript/v5/transactionwidget)
- [BuyWidget](/references/typescript/v5/widgets/BuyWidget)
- [CheckoutWidget](/references/typescript/v5/widgets/CheckoutWidget)
- [TransactionWidget](/references/typescript/v5/widgets/TransactionWidget)
+126
View File
@@ -0,0 +1,126 @@
import { createMetadata, Details } from "@doc";
export const metadata = createMetadata({
image: {
title: "thirdweb Payments - FAQs",
icon: "thirdweb",
},
title: "thirdweb Payments - FAQs - thirdweb",
description: "thirdweb Payments - Frequently Asked Questions",
});
# FAQs
<Details summary="What are the fees for Buy With Fiat?">
thirdweb does not charge any fees for buy with fiat. Any fees on onramping are based on the onramp provider.
</Details>
<Details summary="What are the fees for Buy With Crypto?">
For buying with crypto or swap fees, thirdweb charges a 0.3% protocol fee. Developers may monetize their application by charging additional fees on swap transactions. To set a fee in your project page, navigate to Payments > Settings to set this fee.
</Details>
<Details summary="What does the term “network fees” refer to?">
Network fees, also referred to as miner fees, are paid to the miner for processing crypto transactions and securing the respective network. These fees do not go to thirdweb.
</Details>
<Details summary="What does Payments use to operate under the hood?">
Payments is an asset router that combines thirdweb's own onchain infrastructure with existing bridging and swapping protocols to find the optimal route for any given transaction.
This can include intents, native bridges, third party bridges, cross-chain messaging protocols, thirdweb's custom bridges, and more. All routes are monitored and planned continuously for
health, price, and speed to guarantee the best path every time.
</Details>
<Details summary="How can I support a token on Payments?">
Payments is able to support most token that meet the following criteria:
- The token must have sufficient liquidity
- The token must be on a [supported Payments Chain](https://thirdweb.com/chainlist?service=pay).
To request support for a token, please visit the Payments tab in your project dashboard > Settings > "Don't see your token listed?" component and fill out the chain and token address information.
Payments will automatically kick off the token route discovery process. Please check back the Payments modal after 20-40 minutes for the requested token.
</Details>
<Details summary="Am I able to use Payments with other wallet infrastructure providers?">
Yes, Payments is designed to be agnostic to wallet infrastructure. You can use it with any wallet service.
</Details>
<Details summary="Does Payments support Apple Pay or Google Pay?">
Apple Pay and Google Pay are supported through the onramp providers depending on region. Coinbase, Stripe, and Transak currently support Apple Pay. Transak supports Google Pay.
</Details>
<Details summary="What are the KYC requirements?">
Onramp options all require minimal KYC. This is done to comply with local regulations and to ensure the safety of our users.
Please note: onramping with Coinbase does not require KYC for a purchase below $500 with debit card.
</Details>
<Details summary="What are your transaction limits for Buy With Fiat?">
We currently require a $1 minimum purchase for both stablecoin and non-stablecoin purchases through Buy With Fiat.
Our transaction maximum starts from $1500 per week for new users and can increase over time to $10,000 per week.
</Details>
<Details summary="What countries does Buy With Fiat support?">
**Buy With Fiat** is available 160+ countries. The following countries are _UNSUPPORTED_:
- Afghanistan
- Africa (All Countries)
- Belarus
- Bolivia
- China
- Cuba
- Colombia
- Haiti
- Honduras
- Iran
- Iraq
- Latvia
- Lebanon
- Myanmar
- Pakistan
- Qatar
- Russia
- Ukraine
- United Arab Emirates
- Venezuela
- Yemen
All United States are supported, excluding Hawaii.
</Details>
<Details summary="Does thirdweb offer direct onramping to tokens through Buy With Fiat?">
We offer direct onramping **internationally** to the following tokens:
- Mainnet (Ethereum)
- Avalanche
- Polygon
We offer direct onramping to the following tokens in the **US only**:
- ETH (Base)\*
- USDC (Ethereum)
- USDC (Polygon)\*
- USDC (Avalanche)\*
- USDC (Base)\*
All other tokens will require an additional Buy With Crypto step.
\* Not available in New York or the EU.
</Details>
<Details summary="How does KYC work with Buy With Fiat">
Users will be required to complete KYC verification for their first purchase using 'Buy with Fiat.' After that, no further KYC will be needed for future purchases on the same platform.
</Details>
<Details summary="What cryptocurrencies does Payments support?">
Payments can support any currency on our [supported chains](https://thirdweb.com/chainlist?service=pay).
</Details>
<Details summary="How are cryptocurrency prices set in thirdweb Payments?">
Prices are set depending on the liquidity provider used to route your transaction.
</Details>
<Details summary="Does thirdweb Payments offer fiat payouts?">
Fiat payouts are not currently available.
</Details>
+1 -1
View File
@@ -14,7 +14,7 @@ export const metadata = createMetadata({
description:
"Monetize your app with thirdweb Payments. Sell products, transfer funds between users, launch tokens, and more.",
image: {
icon: "payment",
icon: "payments",
title: "thirdweb Payments Docs",
},
title: "thirdweb Payments Documentation",
+4 -4
View File
@@ -23,8 +23,8 @@ import {
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay"
title: "Get started with Payments",
icon: "payments"
},
title: "Get started with Payments",
description: "Monetize your app with thirdweb Payments. Sell products, transfer funds between users, launch tokens, and more.",
@@ -46,7 +46,7 @@ thirdweb Payments allow developers to create advanced payment flows to monetize
</TabsTrigger>
<TabsTrigger value="http" className="flex items-center [&>p]:mb-0">
<EngineIcon className="size-4 mr-1.5" />
HTTP API
HTTP
</TabsTrigger>
</TabsList>
@@ -190,7 +190,7 @@ thirdweb Payments allow developers to create advanced payment flows to monetize
</TabsContent>
<TabsContent value="react">
The quickest way to setup payments in your React app is with the [`BuyWidget`](/references/typescript/v5/buywidget), [`CheckoutWidget`](/references/typescript/v5/checkoutwidget), and [`TransactionWidget`](/references/typescript/v5/transactionwidget) components.
The quickest way to setup payments in your React app is with the [`BuyWidget`](/references/typescript/v5/widgets/BuyWidget), [`CheckoutWidget`](/references/typescript/v5/widgets/CheckoutWidget), and [`TransactionWidget`](/references/typescript/v5/widgets/TransactionWidget) components.
### Installation
Install the thirdweb SDK in your React project:
@@ -12,8 +12,8 @@ import {
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Sell a Product",
icon: "payments",
},
title: "Sell a Product",
description: "Accept any token as payment for your products.",
@@ -23,7 +23,7 @@ export const metadata = createMetadata({
Accept crypto and fiat payments for any product using the `CheckoutWidget`.
<Tabs defaultValue="typescript">
<Tabs defaultValue="react">
<TabsList>
<TabsTrigger value="react" className="flex items-center gap-2 [&>p]:mb-0">
<ReactIcon className="w-4 h-4 mr-2" />
@@ -49,7 +49,7 @@ function ProductPage() {
<div>
<h1>Premium Course</h1>
<p>Complete guide to web3 development</p>
<CheckoutWidget
client={client}
chain={arbitrum}
+2 -2
View File
@@ -22,8 +22,8 @@ import { ExternalLink } from "lucide-react";
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Find Routes",
icon: "payments",
},
title: "Find Routes",
description: "Find available routes for bridging, swapping, and paying.",
+2 -2
View File
@@ -21,8 +21,8 @@ import {
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Sell Tokens",
icon: "payments",
},
title: "Sell Tokens",
description: "Learn how to sell tokens with thirdweb Payments.",
+7 -8
View File
@@ -22,8 +22,8 @@ import { ExternalLink } from "lucide-react";
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Send a payment",
icon: "payments",
},
title: "Send a payment",
description: "Learn how to send a payment between users with thirdweb Payments.",
@@ -48,7 +48,7 @@ Send a payment between users using any combination of chains or tokens. thirdweb
```typescript
import { Bridge } from "thirdweb";
const preparedQuote = await Bridge.Buy.prepare({
originChainId: 42161,
originTokenAddress: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", // USDT on Arbitrum
@@ -255,7 +255,7 @@ Send a payment between users using any combination of chains or tokens. thirdweb
await new Promise((resolve) => setTimeout(resolve, 3000)); // Wait 3 seconds
}
} while (swapStatus.status === "PENDING");
if (swapStatus.status === "FAILED") {
throw new Error("Swap transaction failed");
}
@@ -272,10 +272,9 @@ Send a payment between users using any combination of chains or tokens. thirdweb
## Going further
- [Other auth strategies](/connect/wallet/sign-in-methods/configure)
- [Sponsor Gas](/connect/account-abstraction/overview)
- [Implement Sign In with Ethereum](/connect/auth)
- [External Wallets](/connect/wallet/sign-in-methods/external-wallets) (e.g. MetaMask, WalletConnect, Coinbase Wallet, etc.)
- [Sell a Product](/payments/products)
- [Token Prices](/payments/tokens)
- [Routes](/payments/routes)
## Explore API References
+2 -2
View File
@@ -22,8 +22,8 @@ import { ExternalLink } from "lucide-react";
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Get Token Prices",
icon: "payments",
},
title: "Get Token Prices",
description: "Use thirdweb Payments to get any token's current price and metadata.",
+15 -15
View File
@@ -21,8 +21,8 @@ import {
export const metadata = createMetadata({
image: {
title: "Payments",
icon: "pay",
title: "Payments Webhooks",
icon: "payments",
},
title: "Payments Webhooks",
description: "Learn how to set up and handle webhooks for thirdweb Payments transactions.",
@@ -49,17 +49,17 @@ import { Bridge } from "thirdweb";
export async function POST(request: Request) {
const body = await request.text();
const headers = Object.fromEntries(request.headers.entries());
try {
const webhook = await Bridge.Webhook.parse(
body,
headers,
process.env.WEBHOOK_SECRET // Your webhook secret
);
// Process the webhook
console.log("Webhook received:", webhook);
return Response.json({ success: true });
} catch (error) {
console.error("Webhook verification failed:", error);
@@ -162,30 +162,30 @@ If you prefer to handle verification manually, you can verify webhooks using the
```typescript
async function verifyWebhook(
payload: string,
headers: Record<string, string>,
payload: string,
headers: Record<string, string>,
secret: string,
tolerance = 300 // 5 minutes
) {
// Get the signature and timestamp from headers
const receivedSignature = headers["x-payload-signature"] || headers["x-pay-signature"];
const receivedTimestamp = headers["x-timestamp"] || headers["x-pay-timestamp"];
if (!receivedSignature || !receivedTimestamp) {
throw new Error("Missing required webhook headers: signature or timestamp");
}
// Verify timestamp
const now = Math.floor(Date.now() / 1000);
const timestamp = parseInt(receivedTimestamp, 10);
const diff = Math.abs(now - timestamp);
if (diff > tolerance) {
throw new Error(
`Webhook timestamp is too old. Difference: ${diff}s, tolerance: ${tolerance}s`
);
}
// Generate signature using Web Crypto API
const encoder = new TextEncoder();
const key = await crypto.subtle.importKey(
@@ -195,23 +195,23 @@ async function verifyWebhook(
false,
["sign"]
);
const signature = await crypto.subtle.sign(
"HMAC",
key,
encoder.encode(`${receivedTimestamp}.${payload}`)
);
// Convert the signature to hex string
const computedSignature = Array.from(new Uint8Array(signature))
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
// Compare signatures
if (computedSignature !== receivedSignature) {
throw new Error("Invalid webhook signature");
}
// Parse and return the payload
return JSON.parse(payload);
}
@@ -72,7 +72,7 @@ function Example() {
<ArticleIconCard
title="Supported Wallets"
icon={TablePropertiesIcon}
href="/connect/external-wallets"
href="/wallets/external-wallets"
/>
</Stack>
@@ -71,7 +71,7 @@ function Example() {
<ArticleIconCard
title="Supported Wallets"
icon={TablePropertiesIcon}
href="/connect/external-wallets"
href="/wallets/external-wallets"
/>
</Stack>
@@ -14,7 +14,7 @@ export const metadata = createMetadata({
# Connection Hooks
You can build a completely custom UI for connecting the wallet using the [`useConnect`](/references/typescript/v5/useConnect) hook to connect any of [supported wallets](/connect/external-wallets).
You can build a completely custom UI for connecting the wallet using the [`useConnect`](/references/typescript/v5/useConnect) hook to connect any of [supported wallets](/wallets/external-wallets).
```tsx
import { createThirdwebClient } from "thirdweb";
@@ -106,8 +106,8 @@ The SDK supports 500+ wallets out of the box, all you need to pass is their id.
<ArticleIconCard
title="Supported Wallets"
icon={ComponentIcon}
href="/connect/external-wallets"
description="See all 500+ wallets supported by the Connect SDK"
href="/wallets/external-wallets"
description="See all 500+ wallets supported by the TypeScript SDK"
/>
</Stack>
@@ -91,14 +91,14 @@ await sendTransaction({ transaction, account });
## Full Reference
View everything you can do in the Connect SDK once you have connected your wallet:
View everything you can do in the TypeScript SDK once you have connected your wallet:
<Grid className="lg:grid-cols-2">
<ArticleIconCard
href={"/typescript/v5"}
image={WalletIcon}
title="Connect SDK reference"
title="TypeScript SDK reference"
/>
</Grid>
@@ -84,7 +84,7 @@ import { ThirdwebProvider } from "thirdweb/react"; // v5
Similar to v4's `ConnectWallet` component, the latest version has the [`ConnectButton`](/connect/sign-in/ConnectButton) component which has the same functionality.
However, unlike with v4 where the number of supported wallets is limited (about 20), and adding more wallets mean your app becomes heavier,
the SDK v5 supports [over 300 wallets](/connect/external-wallets) with virtually no impact to your application.
the SDK v5 supports [over 300 wallets](/wallets/external-wallets) with virtually no impact to your application.
Here's how you use the new `ConnectButton`:
@@ -99,7 +99,7 @@ const client = createThirdwebClient({
<ConnectButton client={client} />
```
To learn more about the new `ConnectButton`, head over to the [Playground](https://playground.thirdweb.com/connect/sign-in/button).
To learn more about the new `ConnectButton`, head over to the [Playground](/connect/sign-in/button).
Notice how you are passing the thirdweb client to the component itself and not to the `ThirdwebProvider` like in v4?
By not putting every config inside the context wrapper, we were able to make the SDK v5 much more lightweight since you only load what you need!
@@ -27,7 +27,7 @@ Learn how to migrate to thirdweb's ConnectButton component from [RainbowKit](htt
<Steps>
<Step title="Installation">
Install the connect SDK in your application
Install the TypeScript SDK in your application
<InstallTabs
npm="npm i thirdweb"
yarn="yarn add thirdweb"
+1 -1
View File
@@ -51,7 +51,7 @@ export const sidebar: SideBar = {
name: "Ecosystems Wallets",
},
{
href: "/connect/external-wallets",
href: "/wallets/external-wallets",
name: "External Wallets",
},
{
@@ -258,12 +258,10 @@ export function getSidebarLinkGroups(doc: TransformedDoc, path: string) {
const bridgeGroups = bridge.reduce(
(acc, d) => {
const [, moduleName] = getCustomTag(d) || [];
if (moduleName) {
if (!acc[moduleName]) {
acc[moduleName] = [];
}
acc[moduleName]?.push(d);
if (!acc[moduleName ?? "common"]) {
acc[moduleName ?? "common"] = [];
}
acc[moduleName ?? "common"]?.push(d);
return acc;
},
{} as Record<string, SomeDoc[]>,
@@ -5,7 +5,7 @@ import { getTDocLayout } from "@/app/references/components/TDoc/PageLayout";
export default getTDocLayout({
getDoc: fetchTypeScriptDoc,
packageSlug: "typescript",
sdkTitle: "Connect SDK",
sdkTitle: "TypeScript SDK",
});
export const metadata = createMetadata({

Before

Width:  |  Height:  |  Size: 867 KiB

After

Width:  |  Height:  |  Size: 867 KiB

Some files were not shown because too many files have changed in this diff Show More