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 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/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, }, })]; 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 b4523fe2..fe2a97bb 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 372c243b..016f8a0c 100644 --- a/src/app/typescript/v5/sidebar.tsx +++ b/src/app/typescript/v5/sidebar.tsx @@ -119,23 +119,46 @@ 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: , - })), + { + 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", + "bundleUserOp", + "waitForUserOpReceipt", + ].map((name) => ({ + name, + href: `${slug}/${name}`, + icon: , + })), + ...[ + "addAdmin", + "removeAdmin", + "addSessionKey", + "removeSessionKey", + "getAccountsOfSigner", + "getAllActiveSigners", + "getPermissionsForSigner", + "createUnsignedUserOp", + ].map((name) => ({ + name, + href: `${slug}/erc4337/${name}`, + icon: , + })), + ], }, { name: "Auth (SIWE)",