diff --git a/src/app/react/v5/migrate/cheatsheet/page.mdx b/src/app/react/v5/migrate/cheatsheet/page.mdx new file mode 100644 index 00000000..c2fa8b3e --- /dev/null +++ b/src/app/react/v5/migrate/cheatsheet/page.mdx @@ -0,0 +1,32 @@ +### React Cheatsheet + +| Task | `@thirdweb-dev/react` | `thirdweb` | +| ---------------------| ----------------------------------------------------- | --------------------------------------------------- | +| Provider | `import { ThirdwebProvider} from @thirdweb-dev/react` | [`import { ThirdwebProvider } from "thirdweb/react"`](/react/v5/ThirdwebProvider) | +| Contract | `useContract(...)` | [`getContract(...) // not a hook`](/references/typescript/v5/getContract) | +| Address | `useAddress(...)` | [`useActiveAccount(...) // account?.address`](/references/typescript/v5/useActiveAccount) | +| Read | `useContractRead(...)` | [`useReadContract(...)`](/references/typescript/v5/useReadContract) | +| Write | `useContractWrite(...)` | [`useSendTransaction()`](/references/typescript/v5/useSendTransaction) | +| Extensions | `useNFTs(...)` | [`useReadContract(getNFTs, { ... })`](/references/typescript/v5/useReadContract) | +| Get Signer | `useSigner()` | [`useActiveAccount()`](/references/typescript/v5/useActiveAccount) | +| Get Wallet | `useWallet()` | [`useActiveWallet()`](/references/typescript/v5/useActiveWallet) | +| Button | `Web3Button` | [`TransactionButton`](/react/v5/TransactionButton) | +| Connect | `ConnectWallet` | [`ConnectButton`](/react/v5/ConnectButton) | +| Connection Status | `useConnectionStatus()` | [`useActiveWalletConnectionStatus()`](/references/typescript/v5/useActiveWalletConnectionStatus) | +| Switch Chain | `useSwitchChain()` | [`useSwitchActiveWalletChain()`](/references/typescript/v5/useSwitchActiveWalletChain) | +| Get Connected Chain | `useChain()` | [`useSwitchActiveWalletChain()`](/references/typescript/v5/useSwitchActiveWalletChain) | + + +### TypeScript Cheatsheet + +| Task | `@thirdweb-dev/sdk` | `thirdweb` | +| ---------- | -------------------------------------------------------- | ------------------------------------------------- | +| Chains | `import { Sepolia } from "@thirdweb-dev/chains"` | [`import { sepolia } from "thirdweb/chains"`](/typescript/v5/chain) | +| Wallets | `import { MetaMaskWallet } from "@thirdweb-dev/wallets"` | [`import { createWallet } from "thirdweb/wallets"`](/references/typescript/v5/createWallet) | +| Initialize | `new ThirdwebSDK(...)` | [`createThirdwebClient({ ... })`](/references/typescript/v5/createThirdwebClient) | +| Contract | `await sdk.getContract(...)` | [`getContract(...) // no await`](/references/typescript/v5/getContract) | +| Read | `await contract.call(...)` | [`await readContract(...)`](/references/typescript/v5/readContract) | +| Prepare | `await contract.prepare(...)` | [`prepareContractCall(...) // no await`](/references/typescript/v5/prepareContractCall) | +| Send | `await contract.call(...)` | [`await sendTransaction(...)`](/references/typescript/v5/sendTransaction) | +| Extensions | `await contract.erc721.getAll()` | [`await getNFTs(...)`](/references/typescript/v5/erc721/getNFTs) | +| Deploy | `sdk.deployer.deployBuiltInContract(...)` | [`await deployPublishedContract(...)`](/references/typescript/v5/deploy/deployPublishedContract) | \ No newline at end of file diff --git a/src/app/react/v5/migrate/contracts/page.mdx b/src/app/react/v5/migrate/contracts/page.mdx new file mode 100644 index 00000000..aa2f6d9c --- /dev/null +++ b/src/app/react/v5/migrate/contracts/page.mdx @@ -0,0 +1,172 @@ +[Migrate from React v4](/react/v5/migrate) + +# Interacting with contracts + +With SDK v4, you always have to "load" a contract with `useContract`. This process adds complexity to your app and inpacts its performance. +In the latest version, a smart contract (type: [`ThirdwebContract`](/references/typescript/v5/ThirdwebContract)) represents a simple object containing info about the contract address, the chain it was deployed on, and the thirdweb client object. + +Example for declaring a smart contract on Ethereum mainnet +```tsx +import { getContract, createThirdwebClient } from "thirdweb"; +import { ethereum } from "thirdweb/chains"; + +const client = createThirdwebClient({ + clientId: process.env.NEXT_PUBLIC_TW_CLIENT_ID, +}); + +const contract = getContract({ + address: "0x....", + chain: ethereum, + client, +}); +``` + +## Contract extensions + +This is a new terminology that we introduced in the new SDK. Basically, each extension represents a method of a contract, be it a "write" or a "read" method. + +An extension is a function that returns a [`PreparedTransaction`](/references/typescript/v5/PreparedTransaction) which in turn can be executed in a React hook for interacting with the contract. We will talk more about it in the section below. + +One of the amazing updates that v5 brings is the rich set of prebuilt extensions. They are the contract methods that have been precompile to ensure a typesafe & performant developer experience. + +Check out the list of over 100 prebuilt extensions [here](/typescript/v5/extensions/built-in), ranging from ERC20, ERC721, ERC1155 to top popular DeFi protocols like Uniswap, Farcaster & Lens. + +Example: Import an ERC1155 "read" extension, for checking the balance of a wallet +```tsx +import { balanceOf } from "thirdweb/extension/erc1155"; + +const transaction = balanceOf({ + contract, + owner: "0x...", + tokenId: 0n, +}); +``` + +## Reading states of a contract +Given the task of calling `balanceOf` from an ERC1155 contract, we'll be comparing the code between v4 and v5 + +#### SDK v4 +```tsx +import { useNFTBalance, useContract } from "@thirdweb-dev/react"; + +function App() { + const { contract } = useContract(contractAddress); + const { isLoading, data, error } = useNFTBalance( + contract, + "{{wallet_address}}", + "{{token_id}}", + ); +} + +``` + +#### SDK v5 +```tsx +import { getContract, createThirdwebClient } from "thirdweb"; +import { balanceOf } from "thirdweb/extensions/erc1155"; +import { ethereum } from "thirdweb/chains"; +import { client } from "@lib/client"; + +const contract = getContract({ + address: "0x....", + chain: ethereum, + client, +}); + +function App() { + const { data } = useReadContract(balanceOf, { contract, owner: "0x...", tokenId: 0n }); +} +``` + +As you can see from the example above, we introduced the hook [`useReadContract`](/references/typescript/v5/useReadContract) in v5. +You should use it to perform any contract "read" in your React app. +It is the perfect replacement for the old chunky React hooks from v4. + +The formula for reading a contract state is: +``` +useReadContract + +``` + +#### If the extension you are looking for is not included in the SDK +You can always use the function signature with `useReadContract` (It's also typesafe) +```tsx +useReadContract({ + contract, + method: "function balanceOf(address _owner, uint256 tokenId) view returns (uint256)", + ... +}) +``` + +#### Tips for getting a function's signature +Go to the thirdweb Dashboard's explorer page and select the function that you want to interact with. +You should see the "Use this function in your app" section with the code snippet for the signature of the function. + +[An example](https://thirdweb.com/avalanche-fuji/0xd5e815241882676F772A624E3892b27Ff3a449c4/explorer?name=balanceOf) + + +## Writing to a contract +In v5, you can utilize the following hooks for writing to contracts: [`useSendTransaction`](/references/typescript/v5/useSendTransaction) and [`useSendAndConfirmTransaction`](/references/typescript/v5/useSendAndConfirmTransaction). +The main difference between the 2 hooks is that `useSendTransaction` will mark the request as "complete" once the transaction is sent, +while `useSendAndConfirmTransaction` will wait until the transaction is included in the blockchain. + +Given the task of claiming an NFT from an NFT Drop collection, let's compare the code between the SDK v4 and v5 + + +#### SDK V4 +```tsx +import { useContract, useClaimNFT } from "@thirdweb-dev/react"; + +function App() { + const { contract } = useContract(contractAddress); + const { + mutateAsync: claimNft, + isLoading, + error, + } = useClaimNFT(contract); + + return ( + + claimNft({ + to: "{{wallet_address}}", // Use useAddress hook to get current wallet address + quantity: 1, + }) + } + > + Claim NFT + + ); +} +``` + +#### SDK v5 +```tsx +import { useSendTransaction } from "thirdweb/react"; +import { claimTo } from "thirdweb/extension/erc721"; + +function App() { + const transaction = claimTo({ contract, quantity: 1n, to: "0x..." }); + const { mutateAsync: claimNft } = useSendTransaction(); + + return +} +``` + +Another beautiful thing about the SDK v5 is that it comes with the [`TransactionButton`](/references/typescript/v5/TransactionButton) +which allows you to make a contract call _without_ having to use the above React hooks. As you can see, the code is much cleaner this way! + +```tsx +import { TransactionButton } from "thirdweb/react"; +import { claimTo } from "thirdweb/extension/erc721"; + +function App() { + return claimTo({ contract, quantity: 1n, to: "0x..." }) + }> + Claim + +} +``` \ No newline at end of file diff --git a/src/app/react/v5/migrate/installation/page.mdx b/src/app/react/v5/migrate/installation/page.mdx new file mode 100644 index 00000000..9930a20a --- /dev/null +++ b/src/app/react/v5/migrate/installation/page.mdx @@ -0,0 +1,112 @@ +import { + ArticleCard, + GithubTemplateCard, + Grid, + ExpandableGrid, + createMetadata, + OpenSourceCard, + Stack, + Steps, + Step, + InstallTabs, + Callout +} from "@doc"; + +[Migrate from React v4](/react/v5/migrate) + +# Installation & Setups + +Welcome to the migration guide for updating your React SDK from version 4 to version 5. This guide will walk you through the necessary steps to ensure a smooth transition. In this section, we'll cover the installation process for the new version of the SDK. + +## Installation + +#### Below is how you install thirdweb v4 SDKs + + +#### With the latest version, everything comes in one single package + + + +## Setups + +Once you have installed the latest package (alongside the older version that you want to replace), you can start the migration process. + +### ThirdwebProvider + +In the latest SDK, the [`ThirdwebProvider`](/references/typescript/v5/ThirdwebProvider) no longer accepts any prop such as `activeChain`, `clientId` or any extra SDK options. +Instead, you only need to pass the clientId when necessary (we'll talk more about this in a few sections below). + +```tsx +import { ThirdwebProvider } from "thirdweb/react"; + + + ... + +``` + +###### Progressive migration + + +If you're currently using the `@thirdweb-dev/sdk`, you can progressively migrate to the new `thirdweb` SDK. Both SDKs can be used side by side and are interoperable with each other. + +In React, you can mix and match the v4 and v5 `ThirdwebProvider`, that gives you access to the hooks and functionality of both SDKs. +This way, once you have moved away from all the v4 functionalities, you can finally remove the `ThirdwebProviderV4` from your app. + +```tsx +import { ThirdwebProvider as ThirdwebProviderV4 } from "@thirdweb-dev/react"; +import { ThirdwebProvider } from "thirdweb/react"; // v5 + + + + ... + + +``` + +### Connecting wallets + +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](/typescript/v5/supported-wallets) with virtually no impact to your application. + +Here's how you use the new `ConnectButton`: + +```tsx +import { createThirdwebClient } from "thirdweb"; +import { ConnectButton } from "thirdweb/react"; + +const client = createThirdwebClient({ + clientId: process.env.NEXT_PUBLIC_TW_CLIENT_ID, +}); + + +``` + +To learn more about the new `ConnectButton`, head over to the [Playground](https://thirdweb.com/dashboard/connect/playground). + +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! + + +Tip: You can reuse the thirdweb client object by putting it in a file and export it. +```ts +// @lib/client.ts + +import { createThirdwebClient } from "thirdweb"; + +export const client = createThirdwebClient({ + clientId: process.env.NEXT_PUBLIC_TW_CLIENT_ID, +}); + +``` \ No newline at end of file diff --git a/src/app/react/v5/migrate/page.mdx b/src/app/react/v5/migrate/page.mdx index ee3047e1..5e15b128 100644 --- a/src/app/react/v5/migrate/page.mdx +++ b/src/app/react/v5/migrate/page.mdx @@ -1,4 +1,73 @@ -# Migration from SDK v4 +# Migration from React SDK v4 + +## Why you should migrate + +#### 1. Better performance, happier clients +The new SDK is built with performance in mind and proper tree-shaking. Therefore, the minimum bundle size of your application is greatly reduced. + +Below is the comparison of 2 similar applications, using `ConnectWallet` (v4) & `ConnectButton` (v5), which are identical in term of functionality. + +| | SDK v4 | SDK v5 +| ------------------- | ------ | ------- +| Minimum bundle size | 766kb | 104kb +| Dependencies | `"@thirdweb-dev/react": "^4.9.4"`
`"@thirdweb-dev/sdk": "^4.0.99"`
`"ethers": "^5.7.2"`| `"thirdweb": "^5.42.0"` + +_(Built with Next.js 14.2.5)_ + +#### 2. More wallets supported +The SDK v4 only supports a handful of web3 wallets and the more wallets you want to include in your app, the heavier it becomes. + +SDK v5 supports over 300 wallets and this number is increasing! You can [interact with wallets based on their unique IDs](/typescript/v5/wallets#example-connect-a-wallet-and-access-an-account-to-send-a-transaction). +Hence, adding more wallets to your app has little to no effect to the final bundle. + +#### 3. Flexibility with React hooks +When building a React web3 application with thirdweb SDK v4, you have access to a set of prebuilt React hooks which let you conveniently interact with your smart contracts. + +The issue with this approach is that, the number of smart-contract methods is ever-increasing, and for each hook that does not exist, we have to dedicate time & energy +to write, test & maintain. This process is time-consuming & frankly, the more React hooks you add to your app, the slower and more unmaintainable your projects become. + +In SDK v5, we introduce a novel concept called "prebuilt extensions" - a set of read & write methods for popular contracts which you can _plug & play_. For example: +###### Read contract states with v5 +```ts +// Get a list of owned ERC721 tokens in a wallet +import { useReadContract } from "thirdweb/react"; +import { getOwnedNFTs } from "thirdweb/extensions/erc721"; + +const { data } = useReadContract(getOwned, { contract, owner }); +``` + +###### Write to contract with v5 +```ts +// Claim an NFT from thirdweb Drop contract +import { useSendTransaction } from "thirdweb/react"; +import { claimTo } from "thirdweb/extensions/erc721"; + +const { mutate: sendTx } = useSendTransaction(); +const transaction = claimTo({ + contract, + to: "0x...", + quantity: 1n, +}); +sendTx(transaction); +``` + +As you can see, by pairing the contract extensions with `useReadContract` (for read) and `useSendTransaction` (for write), +we are able to greatly reduce the amount of code that is packaged & shipped to the end users. Plus, with this approach we can dedicate more time +to building contract extensions. The SDK v5 currenty supports over hundreds of extensions, with some popular protocols like Uniswap, Farcaster, Lens & more to come. + +View a list of [supported extensions](/typescript/v5/extensions/built-in) here, or [build your own](/typescript/v5/extensions/create)! + + + +#### 4. Access to latest software +Currently the SDK v4 is using `ethers@5.7.2` and `@tanstack/react-query@^4` which can be considered "outdated". +We unfortunately do not have a plan to upgrade v4's dependencies to the latest versions. +We highly recommend you to migrate to the SDK v5 to receive the latest software with better security and performance. +Want to keep using ethers.js 5? Worry not! The SDK v5 comes with powerful adapters which let you use thirdweb with popular web3 frameworks like viem or ethers 5 & 6. +[Learn more](/typescript/v5/adapters#ethers-v5) + + +
### High-level changes @@ -14,14 +83,14 @@ If you're currently using the `@thirdweb-dev/sdk`, you can progressively migrate In React, you can mix and match the v4 and v5 `ThirdwebProvider`, that gives you access to the hooks and functionality of both SDKs. ```tsx -import { ThirdwebProvider} from "@thirdweb-dev/react" } -import { ThirdwebProvider as ThirdwebProviderV5 } from "thirdweb/react" +import { ThirdwebProvider as ThirdwebProviderV4 } from "@thirdweb-dev/react"; +import { ThirdwebProvider } from "thirdweb/react" - + ... - + ``` From there, you can obtain the current signer using the `useSigner` hook, and convert it when needed using the `ethers5Adapter`: @@ -43,36 +112,3 @@ const onClick = async () => { }); }; ``` - -### React Cheatsheet - -| Task | `@thirdweb-dev/react` | `thirdweb` | -| ---------------------| ----------------------------------------------------- | --------------------------------------------------- | -| Provider | `import { ThirdwebProvider} from @thirdweb-dev/react` | [`import { ThirdwebProvider } from "thirdweb/react"`](/react/v5/ThirdwebProvider) | -| Contract | `useContract(...)` | [`getContract(...) // not a hook`](/references/typescript/v5/getContract) | -| Address | `useAddress(...)` | [`useActiveAccount(...) // account?.address`](/references/typescript/v5/useActiveAccount) | -| Read | `useContractRead(...)` | [`useReadContract(...)`](/references/typescript/v5/useReadContract) | -| Write | `useContractWrite(...)` | [`useSendTransaction()`](/references/typescript/v5/useSendTransaction) | -| Extensions | `useNFTs(...)` | [`useReadContract(getNFTs, { ... })`](/references/typescript/v5/useReadContract) | -| Get Signer | `useSigner()` | [`useActiveAccount()`](/references/typescript/v5/useActiveAccount) | -| Get Wallet | `useWallet()` | [`useActiveWallet()`](/references/typescript/v5/useActiveWallet) | -| Button | `Web3Button` | [`TransactionButton`](/react/v5/TransactionButton) | -| Connect | `ConnectWallet` | [`ConnectButton`](/react/v5/ConnectButton) | -| Connection Status | `useConnectionStatus()` | [`useActiveWalletConnectionStatus()`](/references/typescript/v5/useActiveWalletConnectionStatus) | -| Switch Chain | `useSwitchChain()` | [`useSwitchActiveWalletChain()`](/references/typescript/v5/useSwitchActiveWalletChain) | -| Get Connected Chain | `useChain()` | [`useSwitchActiveWalletChain()`](/references/typescript/v5/useSwitchActiveWalletChain) | - - -### TypeScript Cheatsheet - -| Task | `@thirdweb-dev/sdk` | `thirdweb` | -| ---------- | -------------------------------------------------------- | ------------------------------------------------- | -| Chains | `import { Sepolia } from "@thirdweb-dev/chains"` | [`import { sepolia } from "thirdweb/chains"`](/typescript/v5/chain) | -| Wallets | `import { MetaMaskWallet } from "@thirdweb-dev/wallets"` | [`import { createWallet } from "thirdweb/wallets"`](/references/typescript/v5/createWallet) | -| Initialize | `new ThirdwebSDK(...)` | [`createThirdwebClient({ ... })`](/references/typescript/v5/createThirdwebClient) | -| Contract | `await sdk.getContract(...)` | [`getContract(...) // no await`](/references/typescript/v5/getContract) | -| Read | `await contract.call(...)` | [`await readContract(...)`](/references/typescript/v5/readContract) | -| Prepare | `await contract.prepare(...)` | [`prepareContractCall(...) // no await`](/references/typescript/v5/prepareContractCall) | -| Send | `await contract.call(...)` | [`await sendTransaction(...)`](/references/typescript/v5/sendTransaction) | -| Extensions | `await contract.erc721.getAll()` | [`await getNFTs(...)`](/references/typescript/v5/erc721/getNFTs) | -| Deploy | `sdk.deployer.deployBuiltInContract(...)` | [`await deployPublishedContract(...)`](/references/typescript/v5/deploy/deployPublishedContract) | diff --git a/src/app/react/v5/migrate/use-v5-with-ethers/page.mdx b/src/app/react/v5/migrate/use-v5-with-ethers/page.mdx new file mode 100644 index 00000000..1a1aebed --- /dev/null +++ b/src/app/react/v5/migrate/use-v5-with-ethers/page.mdx @@ -0,0 +1 @@ +# WIP \ No newline at end of file diff --git a/src/app/react/v5/sidebar.tsx b/src/app/react/v5/sidebar.tsx index e66a77ed..fae033f3 100644 --- a/src/app/react/v5/sidebar.tsx +++ b/src/app/react/v5/sidebar.tsx @@ -296,6 +296,24 @@ export const sidebar: SideBar = { { name: "Migrate from v4", href: `${slug}/migrate`, + links: [ + { + name: "Installation", + href: `${slug}/migrate/installation`, + }, + { + name: "Interacting with contracts", + href: `${slug}/migrate/contracts`, + }, + // { + // name: "Using v5 with ethers", + // href: `${slug}/migrate/use-v5-with-ethers`, + // }, + { + name: "Cheatsheet", + href: `${slug}/migrate/cheatsheet`, + }, + ], }, { name: "Migrate from RainbowKit",