From bc3e8caf376ae3437e17c59837e57ae30a2a2ea1 Mon Sep 17 00:00:00 2001 From: ian <152932566+ianthirdweb@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:00:46 -0400 Subject: [PATCH 1/5] Tweaks to IAW and Pay FAQs (#546) Add supported tokens to direct onramp list --- src/app/connect/pay/faqs/page.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/connect/pay/faqs/page.mdx b/src/app/connect/pay/faqs/page.mdx index ac1e8b0e..ee2bbbae 100644 --- a/src/app/connect/pay/faqs/page.mdx +++ b/src/app/connect/pay/faqs/page.mdx @@ -71,13 +71,15 @@ We offer direct onramping **internationally** to the following tokens: 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. -\* USDC (Polygon) and USDC (Avalanche) are not available in New York. +\* Not available in New York or the EU. ### How does KYC work with Buy With Fiat From ce404f198c3588223b746285c2e87dd594c46697 Mon Sep 17 00:00:00 2001 From: Kien Ngo Date: Thu, 1 Aug 2024 14:59:45 -0400 Subject: [PATCH 2/5] React v4 Migration (#547) * Update * Update --- src/app/react/v5/migrate/cheatsheet/page.mdx | 32 ++++ src/app/react/v5/migrate/contracts/page.mdx | 172 ++++++++++++++++++ .../react/v5/migrate/installation/page.mdx | 112 ++++++++++++ src/app/react/v5/migrate/page.mdx | 112 ++++++++---- .../v5/migrate/use-v5-with-ethers/page.mdx | 1 + src/app/react/v5/sidebar.tsx | 18 ++ 6 files changed, 409 insertions(+), 38 deletions(-) create mode 100644 src/app/react/v5/migrate/cheatsheet/page.mdx create mode 100644 src/app/react/v5/migrate/contracts/page.mdx create mode 100644 src/app/react/v5/migrate/installation/page.mdx create mode 100644 src/app/react/v5/migrate/use-v5-with-ethers/page.mdx 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", From 397b0efdca20d227e8d3c89b740454d5830b64f7 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Fri, 2 Aug 2024 09:03:31 +1200 Subject: [PATCH 3/5] Refactor sidebar structure for better organization of Account Abstraction links (#548) --- src/app/typescript/v5/sidebar.tsx | 43 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/app/typescript/v5/sidebar.tsx b/src/app/typescript/v5/sidebar.tsx index 372c243b..18a3a687 100644 --- a/src/app/typescript/v5/sidebar.tsx +++ b/src/app/typescript/v5/sidebar.tsx @@ -119,23 +119,32 @@ export const sidebar: SideBar = { { name: "Account Abstraction", links: [ - "smartWallet", - "addAdmin", - "removeAdmin", - "addSessionKey", - "removeSessionKey", - "getAccountsOfSigner", - "getAllActiveSigners", - "getPermissionsForSigner", - "createUnsignedUserOp", - "signUserOp", - "bundleUserOp", - "waitForUserOpReceipt", - ].map((name) => ({ - name, - href: `${slug}/${name}`, - icon: , - })), + ...[ + "smartWallet", + "signUserOp", + "bundleUserOp", + "waitForUserOpReceipt", + ].map((name) => ({ + name, + href: `${slug}/${name}`, + icon: , + })), + { separator: true }, + ...[ + "addAdmin", + "removeAdmin", + "addSessionKey", + "removeSessionKey", + "getAccountsOfSigner", + "getAllActiveSigners", + "getPermissionsForSigner", + "createUnsignedUserOp", + ].map((name) => ({ + name, + href: `${slug}/erc4337/${name}`, + icon: , + })), + ], }, { name: "Auth (SIWE)", From 9a92d9f5d67085f47101ef8cb0c3a9480841d448 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Fri, 2 Aug 2024 21:42:04 +1200 Subject: [PATCH 4/5] Add Account Abstraction documentation for 'Get Started' and 'Build Your Own UI' guides (#549) --- src/app/connect/sidebar.tsx | 55 +++--- src/app/react-native/v5/sidebar.tsx | 20 +++ .../batching-transactions/page.mdx | 42 +++++ .../build-your-own-ui/page.mdx | 139 +++++++++++++++ .../account-abstraction/get-started/page.mdx | 132 ++++++++++++++ .../account-abstraction/permissions/page.mdx | 93 ++++++++++ src/app/react/v5/sidebar.tsx | 30 ++++ .../batching-transactions/page.mdx | 48 ++++++ .../account-abstraction/get-started/page.mdx | 162 ++++++++++++++++++ .../account-abstraction/permissions/page.mdx | 100 +++++++++++ src/app/typescript/v5/sidebar.tsx | 16 +- 11 files changed, 810 insertions(+), 27 deletions(-) create mode 100644 src/app/react/v5/account-abstraction/batching-transactions/page.mdx create mode 100644 src/app/react/v5/account-abstraction/build-your-own-ui/page.mdx create mode 100644 src/app/react/v5/account-abstraction/get-started/page.mdx create mode 100644 src/app/react/v5/account-abstraction/permissions/page.mdx create mode 100644 src/app/typescript/v5/account-abstraction/batching-transactions/page.mdx create mode 100644 src/app/typescript/v5/account-abstraction/get-started/page.mdx create mode 100644 src/app/typescript/v5/account-abstraction/permissions/page.mdx diff --git a/src/app/connect/sidebar.tsx b/src/app/connect/sidebar.tsx index a55cb50e..8c6655bc 100644 --- a/src/app/connect/sidebar.tsx +++ b/src/app/connect/sidebar.tsx @@ -191,7 +191,7 @@ export const sidebar: SideBar = { { name: "React Native", // TODO - add react-native dedicated page - href: "/react/v5", + href: "/react/v5/in-app-wallet/get-started", icon: , }, { @@ -293,15 +293,34 @@ export const sidebar: SideBar = { }, { name: "Get Started", - href: `${aAslug}/get-started`, - }, - { - name: "Permissions & Session Keys", - href: `${aAslug}/permissions`, - }, - { - name: "Batching Transactions", - href: `${aAslug}/batching-transactions`, + links: [ + { + name: "TypeScript", + href: "/typescript/v5/account-abstraction/get-started", + icon: , + }, + { + name: "React", + href: "/react/v5/account-abstraction/get-started", + icon: , + }, + { + name: "React Native", + // TODO - add react-native dedicated page + href: "/react/v5/account-abstraction/get-started", + icon: , + }, + { + name: "Dotnet", + href: "/dotnet/wallets/providers/account-abstraction", + icon: , + }, + { + name: "Unity", + href: "/unity/wallets/providers/account-abstraction", + icon: , + }, + ], }, { name: "Account Factories", @@ -315,25 +334,9 @@ export const sidebar: SideBar = { name: "Sponsorship rules", href: `${aAslug}/sponsorship-rules`, }, - { - name: "Guides", - isCollapsible: true, - expanded: true, - links: [ - { - name: "Usage in React", - href: `${aAslug}/guides/react`, - }, - { - name: "Usage in Typescript", - href: `${aAslug}/guides/typescript`, - }, - ], - }, { name: "Gasless", isCollapsible: true, - expanded: true, links: [ { name: "Engine", diff --git a/src/app/react-native/v5/sidebar.tsx b/src/app/react-native/v5/sidebar.tsx index ba87dca5..37a2c845 100644 --- a/src/app/react-native/v5/sidebar.tsx +++ b/src/app/react-native/v5/sidebar.tsx @@ -109,6 +109,26 @@ export const sidebar: SideBar = { icon: , })) || [], }, + { + name: "In-App Wallets", + links: [ + { + name: "React API", + href: "/react/v5/in-app-wallet/get-started", + icon: , + }, + ], + }, + { + name: "Account Abstraction", + links: [ + { + name: "React API", + href: "/react/v5/account-abstraction/get-started", + icon: , + }, + ], + }, { name: "Supported Wallets", href: "/typescript/v5/supported-wallets", diff --git a/src/app/react/v5/account-abstraction/batching-transactions/page.mdx b/src/app/react/v5/account-abstraction/batching-transactions/page.mdx new file mode 100644 index 00000000..4fd93397 --- /dev/null +++ b/src/app/react/v5/account-abstraction/batching-transactions/page.mdx @@ -0,0 +1,42 @@ +import { createMetadata } from "@doc"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; + +# Batching transactions + +export const metadata = createMetadata({ + image: { + title: "Batching transactions", + icon: "wallets", + }, + title: "Batching transactions | thirdweb", + description: "How to batch transactions with smart accounts", +}); + +Batching transactions allows sending multiple transactions in a single user operation. This can be useful to save on fees, reduce number of user confimations or to ensure that multiple transactions are executed atomically. + +A typical example is to do an approval and a transfer in a single userOperation. This way, the transfer will only happen if the approval is successful. + +```tsx +import { useActiveAccount, useSendBatchTransaction } from "thirdweb/react"; +import { approve, transferFrom } from "thirdweb/extensions/erc20"; + +const smartAccount = useActiveAccount(); +const { mutate: sendBatchTransaction } = useSendBatchTransaction(); + +const approveAndTransfer = async () => { + const transactions = [ + approve({ + contract, + spender: "0x...", + value: 100, + }), + transferFrom({ + contract, + from: "0x...", + to: "0x...", + amount: 100, + }), + ]; + await sendBatchTransaction(transactions); +}; +``` \ No newline at end of file diff --git a/src/app/react/v5/account-abstraction/build-your-own-ui/page.mdx b/src/app/react/v5/account-abstraction/build-your-own-ui/page.mdx new file mode 100644 index 00000000..4b7b33fc --- /dev/null +++ b/src/app/react/v5/account-abstraction/build-your-own-ui/page.mdx @@ -0,0 +1,139 @@ +import { + Grid, + Callout, + OpenSourceCard, + ArticleIconCard, + createMetadata, + Steps, + Step, +} from "@doc"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { WalletsSmartIcon } from "@/icons"; + +export const metadata = createMetadata({ + image: { + title: "Build a custom UI for connecting smart accounts", + icon: "wallets", + }, + title: "Build a custom UI for smart accounts | thirdweb", + description: + "You have full control with the connection hooks and functions to build your own UI", +}); + +# Build your own UI + +You can also use the connection hooks and functions to connect to your smart accounts and build your fully custom UI. + + + + +You will require an API key to use thirdweb's infrastructure services such as the bundler and paymaster. + +Obtain an API key from the [thirdweb dashboard Settings page](https://thirdweb.com/create-api-key). + +The API key lets you access thirdweb's bundler and paymaster infrastructure, which is required for smart accounts to operate and optionally enable [gasless transactions](/glossary/gasless-transactions). + +Learn more about creating an API key and restricting which contracts the smart account can interact with [here](/api-keys). + + + + +Using `useConnect`, you can pass the `accountAbstraction` prop to automatically convert any connected wallet to a smart account. + +The connected wallet will be the admin wallet of the smart account. + + + +To set up sponsored transactions, set the `sponsorGas` option to `true` in the smart account configuration. +All transactions performed with the smart account will then be sponsored by your application. Testnet transactions are free, but you need a valid credit card on file for mainnet transactions. + + + +```tsx +import { useConnect } from "thirdweb/react"; +import { inAppWallet } from "thirdweb/wallets"; +import { sepolia } from "thirdweb/chains"; + +function App() { + // 1. set the `accountAbstraction` configuration + const { connect } = useConnect({ + client, + accountAbstraction: { + chain: sepolia, // the chain where your smart accounts will be or is deployed + sponsorGas: true, // enable or disable sponsored transactions + }, + }); + + const connectToSmartAccount = async () => { + // 2. connect with the admin wallet of the smart account + connect(async () => { + const wallet = inAppWallet(); // or any other wallet + await wallet.connect({ + client, + chain: sepolia, + strategy: "google", + }); + return wallet; + }); + }; + + return ; +} +``` + + + + +Once setup, you can use the Connect [TypeScript](/typescript/v5), [React](/react/v5), or [React Native](/react-native/v5) SDKs to deploy contracts, perform transactions, and manipulate smart accounts like any other wallet. + +```tsx +import { getContract } from "thirdweb"; +import { useActiveAccount, useSendTransaction } from "thirdweb/react"; +import { claimTo, balanceOf } from "thirdweb/extensions/erc721"; + +const contract = getContract({ client, chain, address: "0x..." }); + +// The ThirdwebProvider setup above already handles the connection to the smart account +// Within the provider, you can use the SDK normally to interact with the blockchain +export default function MyComponent() { + // Get the connected smart account + const smartAccount = useActiveAccount(); + // Example read + const { data, isLoading } = useReadContract( + balanceOf, + { + contract, + owner: smartAccount.address, + }, + { + enabled: !!smartAccount, + }, + ); + // Example write + const { mutate: sendTransaction, isPending } = useSendTransaction(); + const mint = () => { + sendTransaction({ + transaction: claimTo({ + contract, + to: smartAccount.address, + quantity: 1n, + }), + }); + }; + // Mint a new NFT + return ; +} +``` + + + + +### Demos + +Learn by example with these open-source demos: + + diff --git a/src/app/react/v5/account-abstraction/get-started/page.mdx b/src/app/react/v5/account-abstraction/get-started/page.mdx new file mode 100644 index 00000000..2a1539bc --- /dev/null +++ b/src/app/react/v5/account-abstraction/get-started/page.mdx @@ -0,0 +1,132 @@ +import { + Grid, + Callout, + OpenSourceCard, + ArticleIconCard, + createMetadata, + Steps, + Step, +} from "@doc"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { WalletsSmartIcon } from "@/icons"; + +export const metadata = createMetadata({ + image: { + title: "Get started with Account Abstraction", + icon: "wallets", + }, + title: "Getting Started with Account Abstraction | thirdweb", + description: + "Getting started to add ERC-4337 Account Abstraction support to your application easily.", +}); + +# Getting Started + +Getting started to add ERC-4337 compatible smart accounts to your application easily. + +Once set, your application will: + +- Let users **connect to their smart account** using any personal wallet, including in-app wallets for easy onboarding. +- Automatically **deploy individual account contracts** for your users when they do their first onchain transaction. +- **Handle all transaction gas costs** via the thirdweb paymaster. + + + + +You will require an API key to use thirdweb's infrastructure services such as the bundler and paymaster. + +Obtain an API key from the [thirdweb dashboard Settings page](https://thirdweb.com/create-api-key). + +The API key lets you access thirdweb's bundler and paymaster infrastructure, which is required for smart accounts to operate and optionally enable [gasless transactions](/glossary/gasless-transactions). + +Learn more about creating an API key and restricting which contracts the smart account can interact with [here](/api-keys). + + + + +The easiest way to get started with account abstraction is to use the [ConnectButton](/connect/sign-in/ConnectButton) component. Simply add the `accountAbstraction` property with the desired chain and whether to sponsor gas for your users. + +With this property, all connected wallets will be automatically converted to smart accounts. The connected wallet will be the admin wallet of the smart account. + + + +To set up sponsored transactions, set the `sponsorGas` option to `true` in the smart account configuration. +All transactions performed with the smart account will then be sponsored by your application. Testnet transactions are free, but you need a valid credit card on file for mainnet transactions. + + + +```tsx +import { createThirdwebClient } from "thirdweb"; +import { ThirdwebProvider, ConnectButton } from "thirdweb/react"; + +const client = createThirdwebClient({ +clientId: "YOUR_CLIENT_ID", +}); + +export default function App() { +return ( + + + + ); +} +``` + + + +Once setup, you can use the rest of the Connect [React SDK](/react/latest) to deploy contracts, perform transactions, and manipulate smart accounts like any other wallet. + +```tsx +import { getContract } from "thirdweb"; +import { useActiveAccount, TransactionButton } from "thirdweb/react"; +import { claimTo } from "thirdweb/extensions/erc721"; + +const contract = getContract({ client, chain, address: "0x..." }); + +// The ThirdwebProvider setup above already handles the connection to the smart account +// Within the provider, you can use the SDK normally to interact with the blockchain +export default function MyComponent() { + // Get the connected smart account + const smartAccount = useActiveAccount(); + // Mint a new NFT + return ( + { + if (!account) return; + return claimTo({ + contract, + to: account.address, + quantity: 1n, + }); + }} + > + Mint NFT + + ); +} +``` + + + + +### Build your own UI + +You can also use the connection hooks and functions to connect to your smart accounts and build your fully custom UI. + +See the [Build your own UI](/react/v5/account-abstraction/build-your-own-ui) guide for more information. + +### Demos + +Learn by example with these open-source demos: + + diff --git a/src/app/react/v5/account-abstraction/permissions/page.mdx b/src/app/react/v5/account-abstraction/permissions/page.mdx new file mode 100644 index 00000000..3c8144e4 --- /dev/null +++ b/src/app/react/v5/account-abstraction/permissions/page.mdx @@ -0,0 +1,93 @@ +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { createMetadata } from "@doc"; +import { V4SDKbanner } from "@/components/others/V4SDKBanner"; + +export const metadata = createMetadata({ + image: { + title: "Account Permissions & Session Keys", + icon: "thirdweb", + }, + title: "Account Permissions & Session Keys | thirdweb", + description: + "All of the account contracts - Simple and Managed - share the same permission model. In this section, we'll describe this permission model in detail", +}); + +# Account Permissions & Session Keys + +All of the account contracts - [Simple](https://thirdweb.com/thirdweb.eth/AccountFactory) and [Managed](https://thirdweb.com/thirdweb.eth/ManagedAccountFactory) - share the same permission model. In this section, we'll describe this permission model in detail. + +An account recognizes only two types of actors: _Session Keys_ and _Admins_. + +## 1. Admins + +Admins have **unrestricted access** to the account; call any functions on the contract, use the contract without going through the ERC-4337 infrastructure (bundlers, EntryPoint, etc.), withdraw the account's native token balance, and so on. + +### Assigning Admin Permissions + +Existing admins on the account can add new admins, remove existing admins or renounce their own admin status. + +```tsx +import { addAdmin } from "thirdweb/extensions/erc4337"; +import { useSendTransaction, useActiveAccount } from "thirdweb/react"; +import { getContract } from "thirdweb"; + +const { mutate: sendTransaction } = useSendTransaction(); +const smartAccount = useActiveAccount(); + +const onClick = () => { + if (!smartAccount) return; + const transaction = addAdmin({ + contract: getContract({ + address: smartAccount.address, + chain, + client, + }), + account: smartAccount, + adminAddress: "0x...", // the address of the new admin + }); + sendTransaction(transaction); +}; +``` + +## 2. Session Keys + +Session Keys are additional authorized signers that must go through ERC-4337 infrastructure (bundlers, EntryPoint, etc.) to use an account to execute transactions. Session keys can use an account under certain restrictions. + +### Assigning Session Key Permissions + +Each individual session key has its own permissions to use the account. Only admins can set the permissions for session keys. + +Session keys can be assigned the following permissions: + +- [Required] Allow interaction with specific contracts with the account ("*" for any contracts) +- [Optional] Have a maximum amount of native tokens that can be transferred per transaction (defaults to 0 eth, transactions with value will be rejected) +- [Optional] Have access to the account only during a specific time window (defaults to 10 years from now) + +```tsx +import { addSessionKey } from "thirdweb/extensions/erc4337"; +import { useSendTransaction, useActiveAccount } from "thirdweb/react"; +import { getContract } from "thirdweb"; + +const { mutate: sendTransaction } = useSendTransaction(); +const smartAccount = useActiveAccount(); + +const onClick = () => { + if (!smartAccount) return; + const transaction = addSessionKey({ + contract: getContract({ + address: smartAccount.address, + chain, + client, + }), + account: smartAccount, + sessionKeyAddress: "0x...", // the address of the new session key + permissions: { + approvedTargets: "*", // the addresses of allowed contracts, or '*' for any contract + nativeTokenLimitPerTransaction: 0.1, // the maximum amount of native token (in ETH) that the session key can spend per transaction + permissionStartTimestamp: new Date(), // the date when the session key becomes active + permissionEndTimestamp: new Date(Date.now() + 24 * 60 * 60 * 1000), // the date when the session key expires + }, + }); + sendTransaction(transaction); +}; +``` diff --git a/src/app/react/v5/sidebar.tsx b/src/app/react/v5/sidebar.tsx index fae033f3..3028500c 100644 --- a/src/app/react/v5/sidebar.tsx +++ b/src/app/react/v5/sidebar.tsx @@ -161,6 +161,36 @@ export const sidebar: SideBar = { })), ], }, + { + name: "Account Abstraction", + links: [ + { + name: "Get Started", + href: `${slug}/account-abstraction/get-started`, + icon: , + }, + { + name: "Build your own UI", + href: `${slug}/account-abstraction/build-your-own-ui`, + icon: , + }, + { + name: "Admins & Session Keys", + href: `${slug}/account-abstraction/permissions`, + icon: , + }, + { + name: "Batching Transactions", + href: `${slug}/account-abstraction/batching-transactions`, + icon: , + }, + { + name: "Core API", + href: "/typescript/v5/smartWallet", + icon: , + }, + ], + }, { name: "All Supported Wallets", href: "/typescript/v5/supported-wallets", diff --git a/src/app/typescript/v5/account-abstraction/batching-transactions/page.mdx b/src/app/typescript/v5/account-abstraction/batching-transactions/page.mdx new file mode 100644 index 00000000..ab431947 --- /dev/null +++ b/src/app/typescript/v5/account-abstraction/batching-transactions/page.mdx @@ -0,0 +1,48 @@ +import { createMetadata } from "@doc"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; + +# Batching transactions + +export const metadata = createMetadata({ + image: { + title: "Batching transactions", + icon: "wallets", + }, + title: "Batching transactions | thirdweb", + description: "How to batch transactions with smart accounts", +}); + +Batching transactions allows sending multiple transactions in a single user operation. This can be useful to save on fees, reduce number of user confimations or to ensure that multiple transactions are executed atomically. + +A typical example is to do an approval and a transfer in a single userOperation. This way, the transfer will only happen if the approval is successful. + +```tsx +import { smartWallet } from "thirdweb/wallets"; +import { sendBatchTransaction } from "thirdweb"; +import { approve, transferFrom } from "thirdweb/extensions/erc20"; + +const smartWallet = new smartWallet(config); +const smartAccount = await smartWallet.connect({ + client, + personalAccount, +}); + +const transactions = [ + approve({ + contract, + spender: "0x...", + value: 100, + }), + transferFrom({ + contract, + from: "0x...", + to: "0x...", + amount: 100, + }), +]; + +await sendBatchTransaction({ + transactions, + account: smartAccount, +}); +``` diff --git a/src/app/typescript/v5/account-abstraction/get-started/page.mdx b/src/app/typescript/v5/account-abstraction/get-started/page.mdx new file mode 100644 index 00000000..41afb613 --- /dev/null +++ b/src/app/typescript/v5/account-abstraction/get-started/page.mdx @@ -0,0 +1,162 @@ +import { Grid, OpenSourceCard, ArticleIconCard, Steps, Step } from "@doc"; +import { WalletsSmartIcon } from "@/icons"; +import { createMetadata } from "@doc"; + +export const metadata = createMetadata({ + image: { + title: "Get Started with Account Abstraction", + icon: "typescript", + }, + title: "Using Account Abstraction in Typescript | thirdweb", + description: + "By using the wallet SDK alongside the TypeScript SDK, you can use smart accounts in your applications easily", +}); + +# Using Account abstraction in Typescript + +By using the [wallet SDK](/references/wallets/latest) alongside the [TypeScript SDK](/typescript/latest), you can use smart accounts in your applications easily. + +## Example Use Cases + +The wallet SDK with the TypeScript SDK is primarily used when creating a backend for your application or when creating a node script. +In this guide, we will be using the wallet SDK to create a Node script but the logic for creating a backend is the same. + +If you are working in a React environment, you are recommended to follow [this guide](/connect/account-abstraction/guides/react). + + + + +To use the bundler and paymaster, you must create an API key and a billing account. + +To create an API Key: + +- Head to the settings page in the dashboard and click the **API Keys** tab. +- Click on **Create API Key**. +- Follow the steps to create your API key. + +To use account abstraction infrastructure on mainnet you will also need to [create an account and add a payment method](https://thirdweb.com/dashboard/settings/billing). + + + + +To use smart accounts in a node script, simply create a new Node.js project and install the `thirdweb` package. + +```bash +npm i thirdweb +``` + +Create a `.env` file and add the following: + +```bash +THIRDWEB_SECRET_KEY= +PRIVATE_KEY= +``` + +Create an `index.ts` file where we'll write our script. + + + + +This smart account is unlocked by a 'key' - a personal wallet. +This key can be anything from a MetaMask wallet or an In-App Wallet or just a private key and is used as a way to 'sign in' to the smart account. + +To create a personal wallet key, we are going to use the [`privateKeyAccount`](/references/typescript/v5/privateKeyAccount), which we need to import from the `thirdweb/wallets` package. + +```typescript +import { createThirdwebClient } from "thirdweb"; +import { privateKeyAccount } from "thirdweb/wallets"; + +const client = createThirdwebClient({ + secretKey: process.env.THIRDWEB_SECRET_KEY as string, +}); + +const personalAccount = privateKeyAccount({ + client, + privateKey: process.env.PRIVATE_KEY as string, +}); +console.log("Personal account address:", personalAccount.address); +``` + + + + +Now, let's create a smart account using the SmartWallet class from the `@thirdweb-dev/wallets` package. +To do this, we need to pass a `SmartWalletConfig` object to the constructor. This object contains the following properties: + +- `chain`: the chain that the smart account will be deployed on. +- `sponsorGas`: whether the smart account should have sponsored transactions or not. + +Once we have created the config and instantiated the `SmartWallet` class, we can connect the personal wallet to the smart account using the `connect` method. + +```typescript +// Configure the smart wallet +const wallet = smartWallet({ + chain: sepolia, + sponsorGas: true, +}); + +// Connect the smart wallet +const smartAccount = await wallet.connect({ + client, + personalAccount, +}); +``` + + + + +Now that we have created a smart account object and connected it, we can use it to perform onchain actions gaslessly. + +In this example, we will claim a NFT using the `claimTo` method and then send the transaction using the `sendTransaction` method. + +```typescript +const balance = await getWalletBalance({ + client, + chain, + address: smartAccount.address, +}); +console.log("Smart account balance:", balance.displayValue); + +const contract = getContract({ + client, + chain: sepolia, + address: "0x...", // deploy a drop contract from thirdweb.com/explore +}); + +const transaction = await claimTo({ + contract, + to: smartAccount.address, + quantity: 1, +}); +const { transactionHash } = await sendTransaction({ + transaction, + smartAccount, +}); +console.log(`Minted NFT with transaction hash: ${transactionHash}`); +``` + +We have also passed our `secretKey` to the SDK so that we can use the bundler and paymaster. + +We have also added some helpful logs to view the smart account address and balance using the associated `balance` and `getAddress` methods. + + + + +To run the script, run the following command: + +```bash +bun index.ts +``` + +As you can see in the terminal output, upon claiming the token, the smart account is deployed. This is because smart account contracts are deployed when the first transaction is initiated. + +We have successfully deployed a smart account and claimed an ERC20 token! + + + + +In this guide, we have learned how to use the wallet SDK with the TypeScript SDK to +create a smart account and claim an NFT. + + + diff --git a/src/app/typescript/v5/account-abstraction/permissions/page.mdx b/src/app/typescript/v5/account-abstraction/permissions/page.mdx new file mode 100644 index 00000000..3e684c65 --- /dev/null +++ b/src/app/typescript/v5/account-abstraction/permissions/page.mdx @@ -0,0 +1,100 @@ +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { createMetadata } from "@doc"; +import { V4SDKbanner } from "@/components/others/V4SDKBanner"; + +export const metadata = createMetadata({ + image: { + title: "Account Permissions & Session Keys", + icon: "thirdweb", + }, + title: "Account Permissions & Session Keys | thirdweb", + description: + "All of the account contracts - Simple and Managed - share the same permission model. In this section, we'll describe this permission model in detail", +}); + +# Account Permissions & Session Keys + +All of the account contracts - [Simple](https://thirdweb.com/thirdweb.eth/AccountFactory) and [Managed](https://thirdweb.com/thirdweb.eth/ManagedAccountFactory) - share the same permission model. In this section, we'll describe this permission model in detail. + +An account recognizes only two types of actors: _Session Keys_ and _Admins_. + +## 1. Admins + +Admins have **unrestricted access** to the account; call any functions on the contract, use the contract without going through the ERC-4337 infrastructure (bundlers, EntryPoint, etc.), withdraw the account's native token balance, and so on. + +### Assigning Admin Permissions + +Existing admins on the account can add new admins, remove existing admins or renounce their own admin status. + + +```typescript +import { addAdmin } from "thirdweb/extensions/erc4337"; +import { smartWallet } from "thirdweb/wallets"; +import { sendTransaction, getContract } from "thirdweb"; + +const smartWallet = new smartWallet(config); +const smartAccount = await smartWallet.connect({ + client, + personalAccount, +}); + +const transaction = addAdmin({ + contract: getContract({ + address: smartAccount.address, + chain, + client, + }), + account: smartAccount, + adminAddress: "0x...", // the address of the new admin +}); +await sendTransaction({ + transaction, + account: smartAccount, +}); +``` + +## 2. Session Keys + +Session Keys are additional authorized signers that must go through ERC-4337 infrastructure (bundlers, EntryPoint, etc.) to use an account to execute transactions. Session keys can use an account under certain restrictions. + +### Assigning Session Key Permissions + +Each individual session key has its own permissions to use the account. Only admins can set the permissions for session keys. + +Session keys can be assigned the following permissions: + +- [Required] Allow interaction with specific contracts with the account ("*" for any contracts) +- [Optional] Have a maximum amount of native tokens that can be transferred per transaction (defaults to 0 eth, transactions with value will be rejected) +- [Optional] Have access to the account only during a specific time window (defaults to 10 years from now) + +```ts +import { addAdmin } from "thirdweb/extensions/erc4337"; +import { smartWallet } from "thirdweb/wallets"; +import { sendTransaction, getContract } from "thirdweb"; + +const smartWallet = new smartWallet(config); +const smartAccount = await smartWallet.connect({ + client, + personalAccount, +}); + +const transaction = addSessionKey({ + contract: getContract({ + address: smartAccount.address, + chain, + client, + }), + account: smartAccount, + sessionKeyAddress: "0x...", // the address of the new session key + permissions: { + approvedTargets: "*", // the addresses of allowed contracts, or '*' for any contract + nativeTokenLimitPerTransaction: 0.1, // the maximum amount of native token (in ETH) that the session key can spend per transaction + permissionStartTimestamp: new Date(), // the date when the session key becomes active + permissionEndTimestamp: new Date(Date.now() + 24 * 60 * 60 * 1000), // the date when the session key expires + }, +}); +await sendTransaction({ + transaction, + account: smartAccount, +}); +``` diff --git a/src/app/typescript/v5/sidebar.tsx b/src/app/typescript/v5/sidebar.tsx index 18a3a687..016f8a0c 100644 --- a/src/app/typescript/v5/sidebar.tsx +++ b/src/app/typescript/v5/sidebar.tsx @@ -119,6 +119,21 @@ export const sidebar: SideBar = { { name: "Account Abstraction", links: [ + { + name: "Getting Started", + href: `${slug}/account-abstraction/get-started`, + icon: , + }, + { + name: "Admins & Session Keys", + href: `${slug}/account-abstraction/permissions`, + icon: , + }, + { + name: "Batching Transactions", + href: `${slug}/account-abstraction/batching-transactions`, + icon: , + }, ...[ "smartWallet", "signUserOp", @@ -129,7 +144,6 @@ export const sidebar: SideBar = { href: `${slug}/${name}`, icon: , })), - { separator: true }, ...[ "addAdmin", "removeAdmin", From 0bb3acba31f1f8cffd41f1066517d9ae942f6c10 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Fri, 2 Aug 2024 22:28:25 +1200 Subject: [PATCH 5/5] Update page.mdx (#550) Signed-off-by: Joaquim Verges --- src/app/react/v5/in-app-wallet/enable-gasless/page.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/react/v5/in-app-wallet/enable-gasless/page.mdx b/src/app/react/v5/in-app-wallet/enable-gasless/page.mdx index ee0914bc..e7142825 100644 --- a/src/app/react/v5/in-app-wallet/enable-gasless/page.mdx +++ b/src/app/react/v5/in-app-wallet/enable-gasless/page.mdx @@ -32,10 +32,11 @@ To enable account abstraction in your app, you need to add the `smartAccount` pr ```jsx import { ConnectButton } from "thirdweb/react"; import { inAppWallet } from "thirdweb/wallets"; +import { sepolia } from "thirdweb/chains"; const wallets = [inAppWallet({ smartAccount: { - chain: "sepolia", + chain: sepolia, sponsorGas: true, }, })];