Skip to content

Commit 187846a

Browse files
committed
chore: update sub accounts docs
1 parent 7fa283b commit 187846a

2 files changed

Lines changed: 102 additions & 77 deletions

File tree

docs/base-account/improve-ux/sub-accounts.mdx

Lines changed: 102 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,26 @@ import { GithubRepoCard } from "/snippets/GithubRepoCard.mdx"
77

88
## What are Sub Accounts?
99

10-
Base Account's self-custodial design requires a user passkey prompt for each wallet interaction, such as transactions or message signing. While this ensures user awareness and approval of every wallet interaction, it can impact user experience in applications requiring frequent wallet interactions.
11-
12-
To support Base Account with user experiences that need more developer control over wallet interactions, we've built Sub Accounts in conjunction with [ERC-7895](https://eip.tools/eip/7895), a new wallet RPC for creating hierarchical relationships between wallet accounts.
13-
14-
Sub Accounts allow you to provision wallet accounts that are directly embedded in your application for your users. You can control when a Sub Account is created and interact with them just as you would with another wallet via the wallet provider or popular web3 libraries like OnchainKit, wagmi, and viem.
10+
Sub Accounts allow you to provision app-specific wallet accounts for your users that are embedded directly in your application. Once created, you can interact with them just as you would with any other wallet via the wallet provider or popular onchain libraries like OnchainKit, wagmi, and viem.
1511

16-
These Sub Accounts are linked to the end user's Base Account through an onchain relationship. When combined with our [Spend Permission feature](/base-account/improve-ux/spend-permissions), this creates a powerful foundation for provisioning and funding app accounts securely, while giving you ample control over building the user experience that makes the most sense for your application.
12+
<Note>
13+
Looking for a full implementation? Jump to the [Complete Integration Example](/base-account/improve-ux/sub-accounts#complete-integration-example).
14+
</Note>
1715

1816
## Key Benefits
1917

20-
- **Seamless UX**: Reduce user friction by eliminating repeated signing prompts
21-
- **Developer Control**: Manage when and how Sub Accounts are created
22-
- **Secure Relationships**: Onchain linking between main account and sub accounts
23-
- **Spend Permissions**: Control what Sub Accounts can spend and when
24-
- **Easy Integration**: Works with existing web3 libraries and tools
18+
- **Frictionless transactions**: Eliminate repeated signing prompts for high frequency and agentic use cases or take full control of the transaction flow.
19+
- **No funding flows required**: Spend Permissions allow Sub Accounts to spend directly from the universal Base Account's balance.
20+
- **User control**: Users can manage all their sub accounts at [account.base.app](https://account.base.app).
2521

2622
<Note>
27-
If you would like to see a live demo of Sub Accounts in action, check out our [Sub Accounts Demo](https://sub-account-demo.com).
23+
If you would like to see a live demo of Sub Accounts in action, check out our [Sub Accounts Demo](https://sub-accounts-fc.vercel.app).
2824
</Note>
2925

3026
<Tip>
31-
**Pair with Spend Permissions**
27+
**Spend Permissions**
3228

33-
In order to make your UX more seamless, you can pair Sub Accounts with the
34-
[Spend Permissions](/base-account/improve-ux/spend-permissions)
35-
to make transactions on behalf of the user.
29+
Sub Accounts are optimized for use with Spend Permissions to allow your app to take advantage of the user's existing Base Account balances. See the [Spend Permissions](/base-account/improve-ux/spend-permissions) guide for more information about how they work.
3630
</Tip>
3731

3832
## Installation
@@ -57,11 +51,32 @@ bun add @base-org/account
5751
```
5852
</CodeGroup>
5953

60-
## Basic Setup
54+
## Quickstart
55+
56+
The fastest way to adopt Sub Accounts is to enable automatic Sub Accounts by setting `subAccounts.mode` to `auto` in the SDK configuration.
57+
58+
```tsx
59+
const sdk = createBaseAccountSDK({
60+
// ...
61+
subAccounts: {
62+
mode: 'auto',
63+
}
64+
});
65+
```
66+
67+
This will automatically create a Sub Account for the user when they connect their Base Account and transactions will automatically be sent from the Sub Account unless you specify the `from` parameter in your transaction request to be the universal account address. Spend Permissions will also be automatically requested for the Sub Account as your app needs them.
68+
69+
<Tip>
70+
We recommend using a [Paymaster](/base-account/improve-ux/sponsor-gas/paymasters) to sponsor gas to ensure the best user experience when integrating Sub Accounts. You can set a paymaster to be used for all transactions by configuring the `paymasterUrls` parameter in the SDK configuration. See the [createBaseAccount](/base-account/reference/core/createBaseAccount#param-paymaster-urls) reference for more information.
71+
</Tip>
72+
73+
## Using Sub Accounts
74+
75+
If you don't want to use automatic Sub Accounts, you can create and manage them manually.
6176

6277
### Initialize the SDK
6378

64-
First, set up the Base Account SDK with Sub Account support:
79+
First, set up the Base Account SDK. Be sure to customize the `appName` and `appLogoUrl` to match your app as this will be displayed in the wallet connection popup and in the account.base.app dashboard. You can also customize the `appChainIds` to be the chains that your app supports.
6580

6681
```tsx
6782
import { createBaseAccountSDK, getCryptoKeyAccount } from '@base-org/account';
@@ -78,11 +93,16 @@ const sdk = createBaseAccountSDK({
7893
const provider = sdk.getProvider()
7994
```
8095

81-
## Using Sub Accounts
96+
### Create a Sub Account
8297

83-
### Create a New Sub Account
98+
<Tip>
99+
Make sure to authenticate the user with their Base Account before creating a Sub Account.
100+
For that, you can choose one of the following options:
101+
- Follow the [Authenticate users](/base-account/guides/authenticate-users) guide
102+
- Simply use `provider.request({ method: 'eth_requestAccounts' });` for a simple wallet connection
103+
</Tip>
84104

85-
Create a Sub Account for your application using the provider RPC method:
105+
Create a Sub Account for your application using the provider's [wallet_addSubAccount](/base-account/reference/core/provider-rpc-methods/wallet_addSubAccount) RPC method. When no `publicKey` parameter is provided, a non-extractable browser CryptoKey is generated and used to sign on behalf of the Sub Account.
86106

87107
```tsx
88108
// Create sub account
@@ -100,20 +120,9 @@ const subAccount = await provider.request({
100120
console.log('Sub Account created:', subAccount.address);
101121
```
102122

103-
<Tip>
104-
**Tip:**
105-
106-
Make sure to authenticate the user with their universal account before creating a Sub Account.
107-
For that, you can choose one of the following options:
108-
- Follow the [Authenticate users](/base-account/guides/authenticate-users) guide
109-
- Simply use `provider.request({ method: 'eth_requestAccounts' });` for a simple wallet connection
110-
111-
</Tip>
112-
113-
Create a Sub Account using the SDK convenience method:
123+
Alternatively, you can use the SDK convenience method:
114124

115125
```tsx
116-
// Create new sub account
117126
const subAccount = await sdk.subAccount.create();
118127

119128
console.log('Sub Account created:', subAccount.address);
@@ -125,38 +134,9 @@ This is what the user will see when prompted to create a Sub Account:
125134
<img src="/images/base-account/SubAccountCreation.png" alt="Sub Account Creation Flow" style={{ width: '300px', height: 'auto' }} />
126135
</div>
127136

128-
### Import an existing Sub Account
129-
130-
If you already have a deployed Smart Contract Account, you can import it as a Sub Account using the provider RPC method:
131-
132-
```tsx
133-
const subAccount = await provider.request({
134-
method: 'wallet_addSubAccount',
135-
params: [
136-
{
137-
account: {
138-
type: 'deployed',
139-
address: '0xYourSmartContractAccountAddress',
140-
chainId: 8453 // the chain the account is deployed on
141-
},
142-
}
143-
],
144-
});
145-
146-
console.log('Sub Account added:', subAccount.address);
147-
```
148-
149-
<Note>
150-
151-
Before the Sub Account is imported, you will need to add the Base Account address as an owner of the Sub Account. This currently needs to be done manually
152-
by calling the [`addOwnerAddress`](https://github.com/coinbase/smart-wallet/blob/a8c6456f3a6d5d2dea08d6336b3be13395cacd42/src/MultiOwnable.sol#L101) or [`addOwnerPublicKey`](https://github.com/coinbase/smart-wallet/blob/a8c6456f3a6d5d2dea08d6336b3be13395cacd42/src/MultiOwnable.sol#L109) functions on the Smart Contract of the Sub Account that was imported and setting the Base Account address as the owner.
153-
154-
Additionally, only Coinbase Smart Wallet contracts are currently supported for importing as a Sub Account into your Base Account.
155-
</Note>
156-
157137
### Get Existing Sub Account
158138

159-
Retrieve an existing Sub Account using the provider RPC method:
139+
Retrieve an existing Sub Account using the provider's [wallet_getSubAccounts](/base-account/reference/core/provider-rpc-methods/wallet_getSubAccounts) RPC method. This will return the Sub Account associated with the app's domain and is useful to check if a Sub Account already exists for the user to determine if one needs to be created.
160140

161141
```tsx
162142
// Get the universal account
@@ -181,10 +161,9 @@ if (subAccount) {
181161
}
182162
```
183163

184-
Get the Sub Account associated with the current app using the SDK convenience method:
164+
Alternatively, you can use the SDK convenience method:
185165

186166
```tsx
187-
// Get sub account
188167
const subAccount = await sdk.subAccount.get();
189168

190169
console.log('Sub Account:', subAccount);
@@ -193,29 +172,32 @@ console.log('Sub Account:', subAccount);
193172

194173
To send transactions from the connected sub account you can use EIP-5792 `wallet_sendCalls` or `eth_sendTransaction`. You need to specify the `from` parameter to be the sub account address.
195174

196-
197-
198175
<Tip>
199-
**Tip:**
176+
When the Sub Account is connected, it is the second account in the array returned by `eth_requestAccounts` or `eth_accounts`. `wallet_addSubAccount` needs to be called in each session before the Sub Account can be used. It will not trigger a new Sub Account creation if one already exists.
200177

201-
When the sub account is connected, it is the second account in the array returned by `eth_requestAccounts` or `eth_accounts`.
178+
If you are using `mode: 'auto'`, the Sub Account will be the first account in the array.
202179
</Tip>
203180

181+
First, get all the accounts that are available, of which the sub account will be the second account:
204182

205183
```tsx
206-
// Get the sub account address
207184
const [universalAddress, subAccountAddress] = await provider.request({
208185
method: "eth_requestAccounts", // or "eth_accounts" if already connected
209186
params: []
210187
})
188+
```
189+
190+
Then, send the transaction from the sub account:
191+
192+
**`wallet_sendCalls`**
211193

212-
// wallet_sendCalls
194+
```tsx
213195
const callsId = await provider.request({
214196
method: 'wallet_sendCalls',
215197
params: [{
216198
version: "2.0",
217199
atomicRequired: true,
218-
from: subAccountAddress,
200+
from: subAccountAddress, // Specify the sub account address
219201
calls: [{
220202
to: '0x...',
221203
data: '0x...',
@@ -229,13 +211,15 @@ const callsId = await provider.request({
229211
})
230212

231213
console.log('Calls sent:', callsId);
214+
```
232215

216+
**`eth_sendTransaction`**
233217

234-
// eth_sendTransaction
218+
```tsx
235219
const tx = await provider.request({
236220
method: 'eth_sendTransaction',
237221
params: [{
238-
from: subAccountAddress,
222+
from: subAccountAddress, // Specify the sub account address
239223
to: '0x...',
240224
data: '0x...',
241225
value: '0x...',
@@ -245,12 +229,45 @@ const tx = await provider.request({
245229
console.log('Transaction sent:', tx);
246230
```
247231

232+
We recommend using `wallet_sendCalls` in conjunction with a paymaster to ensure the best user experience. See the [Paymasters](/base-account/improve-ux/sponsor-gas/paymasters) guide for more information.
233+
234+
## Advanced Usage
235+
236+
### Import an existing account
237+
238+
If you already have a deployed Smart Contract Account, you can import it as a Sub Account using the provider RPC method:
239+
240+
```tsx
241+
const subAccount = await provider.request({
242+
method: 'wallet_addSubAccount',
243+
params: [
244+
{
245+
account: {
246+
type: 'deployed',
247+
address: '0xYourSmartContractAccountAddress',
248+
chainId: 8453 // the chain the account is deployed on
249+
},
250+
}
251+
],
252+
});
253+
254+
console.log('Sub Account added:', subAccount.address);
255+
```
256+
257+
<Note>
258+
259+
Before the Sub Account is imported, you will need to add the Base Account address as an owner of the Sub Account. This currently needs to be done manually
260+
by calling the [`addOwnerAddress`](https://github.com/coinbase/smart-wallet/blob/a8c6456f3a6d5d2dea08d6336b3be13395cacd42/src/MultiOwnable.sol#L101) or [`addOwnerPublicKey`](https://github.com/coinbase/smart-wallet/blob/a8c6456f3a6d5d2dea08d6336b3be13395cacd42/src/MultiOwnable.sol#L109) functions on the Smart Contract of the Sub Account that was imported and setting the Base Account address as the owner.
261+
262+
Additionally, only Coinbase Smart Wallet contracts are currently supported for importing as a Sub Account into your Base Account.
263+
</Note>
264+
265+
248266
### Add Owner Account
249267

250-
Add an owner to a Sub Account:
268+
Sub Accounts automatically detect when an ownership update is needed when a signature is required and will prompt the user to approve the update before signing. However, you can also add an owner to a Sub Account manually using the SDK convenience method:
251269

252270
```tsx
253-
// Add owner account
254271
const ownerAccount = await sdk.subAccount.addOwner({
255272
address: subAccount?.address,
256273
publicKey: cryptoAccount?.account?.publicKey,
@@ -260,6 +277,8 @@ const ownerAccount = await sdk.subAccount.addOwner({
260277
console.log('Owner added to Sub Account');
261278
```
262279

280+
This generates a transaction to call the `addOwnerAddress` or `addOwnerPublicKey` functions on the Sub Account's smart contract to add the owner.
281+
263282
## Auto Spend Permissions
264283

265284
Auto Spend Permissions allows Sub Accounts to access funds from their parent Base Account when transaction balances are insufficient. This feature can also establish ongoing spend permissions, enabling future transactions to execute without user approval prompts, reducing friction in your app's transaction flow.
@@ -301,6 +320,13 @@ Spend permission requests are limited to the first token when multiple transfers
301320
</Warning>
302321

303322

323+
## Technical Details
324+
325+
Base Account's self-custodial design requires a user passkey prompt for each wallet interaction, such as transactions or message signing. While this ensures user awareness and approval of every wallet interaction, it can impact user experience in applications requiring frequent wallet interactions.
326+
327+
To support Base Account with user experiences that need more developer control over wallet interactions, we've built Sub Accounts in conjunction with [ERC-7895](https://eip.tools/eip/7895), a new wallet RPC for creating hierarchical relationships between wallet accounts.
328+
329+
These Sub Accounts are linked to the end user's Base Account through an onchain relationship. When combined with our [Spend Permission feature](/base-account/improve-ux/spend-permissions), this creates a powerful foundation for provisioning and funding app accounts securely, while giving you ample control over building the user experience that makes the most sense for your application.
304330

305331

306332
## Complete Integration Example
@@ -345,7 +371,6 @@ export default function SubAccountDemo() {
345371
try {
346372
const sdkInstance = createBaseAccountSDK({
347373
appName: "Sub Account Demo",
348-
appLogoUrl: "https://base.org/logo.png",
349374
appChainIds: [baseSepolia.id],
350375
});
351376

-830 Bytes
Loading

0 commit comments

Comments
 (0)