Skip to content

Commit 313073e

Browse files
committed
Updates wrt comments in PR
1 parent 9f32e7d commit 313073e

File tree

6 files changed

+552
-35
lines changed

6 files changed

+552
-35
lines changed

embedded-wallets/sdk/android/advanced/custom-authentication.mdx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ Additional to the `LoginConfig` you can pass extra options to the `login` functi
302302
| `ui_locales?` | The space separated list of language tags, ordered by preference. For instance `fr-CA fr en`. |
303303
| `id_token_hint?` | It denotes the previously issued ID token. It takes `String` as a value. |
304304
| `id_token?` | JWT (ID Token) to be passed for login. |
305-
| `login_hint?` | Used to specify the user's email address or phone number for Email/SMS Passwordless login flows. Takes a `String` value. For the SMS, the format should be: `+{country_code}-{phone_number}` (e.g. `+1-1234567890`) |
305+
| `access_token?` | Access token for OAuth flows. It takes `String` as a value. |
306+
| `flow_type?` | Specifies the email passwordless flow type. It takes `EmailFlowType` as a value (`CODE` or `LINK`). |
306307
| `acr_values?` | acc_values |
307308
| `scope?` | The default scope to be used on authentication requests. The defaultScope defined in the Auth0Client is included along with this scope. It takes `String` as a value. |
308309
| `audience?` | The audience, presented as the aud claim in the access token, defines the intended consumer of the token. It takes `String` as a value. |
@@ -330,7 +331,8 @@ data class ExtraLoginOptions(
330331
private var ui_locales : String? = null,
331332
private var id_token : String? = null,
332333
private var id_token_hint : String? = null,
333-
private var login_hint : String? = null,
334+
private var access_token : String? = null,
335+
private var flow_type : EmailFlowType? = null,
334336
private var acr_values : String? = null,
335337
private var scope : String? = null,
336338
private var audience : String? = null,
@@ -340,6 +342,13 @@ data class ExtraLoginOptions(
340342
private var nonce : String? = null,
341343
private var redirect_uri : String? = null
342344
)
345+
346+
enum class EmailFlowType {
347+
@SerializedName("code")
348+
CODE,
349+
@SerializedName("link")
350+
LINK
351+
}
343352
```
344353

345354
</TabItem>
@@ -434,6 +443,7 @@ val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.conne
434443
</TabItem>
435444

436445
<TabItem value="email-passwordless">
446+
437447
To use the Email Passwordless login, you need to put the email into the `loginHint` parameter of
438448
the `LoginParams`. By default, the login flow will be `code` flow, if you want to use the
439449
`link` flow, you need to put `flow_type` into the `extraLoginOptions` parameter.
@@ -455,15 +465,20 @@ val web3Auth = Web3Auth(
455465
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
456466
LoginParams(
457467
AuthConnection.EMAIL_PASSWORDLESS,
458-
// focus-next-line
459-
loginHint = "[email protected]"
468+
// focus-start
469+
loginHint = "[email protected]",
470+
extraLoginOptions = ExtraLoginOptions(
471+
flow_type = EmailFlowType.CODE // Use CODE for OTP flow or LINK for magic link flow
472+
)
473+
// focus-end
460474
)
461475
)
462476
```
463477

464478
</TabItem>
465479

466480
<TabItem value="sms-passwordless">
481+
467482
To use the SMS Passwordless login, send the phone number as the `loginHint` parameter of the
468483
`LoginParams`. Please make sure the phone number is in the format of
469484
+\{country_code}-\{phone_number}, i.e. (+91-09xx901xx1).
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
---
2+
title: Smart Accounts (Account Abstraction)
3+
sidebar_label: Smart Accounts
4+
description: 'Web3Auth Android SDK - Smart Accounts | Embedded Wallets'
5+
---
6+
7+
import TabItem from '@theme/TabItem'
8+
import Tabs from '@theme/Tabs'
9+
import GrowthPlanNote from '../../_common/_growth_plan_note.mdx'
10+
11+
Effortlessly create and manage smart accounts for your users with Web3Auth's native Account Abstraction support. Smart accounts offer enhanced control and programmability, enabling powerful features that traditional wallets can't provide.
12+
13+
<GrowthPlanNote />
14+
15+
## Overview
16+
17+
Web3Auth Android SDK v10.x includes built-in support for ERC-4337 smart accounts. When enabled, your users automatically get smart contract wallets with advanced features like:
18+
19+
- **Gas Sponsorship**: Cover transaction fees for your users
20+
- **Batch Transactions**: Execute multiple operations in a single transaction
21+
- **ERC-20 Token Gas Payments**: Let users pay gas fees with any ERC-20 token
22+
- **Transaction Policies**: Set spending limits and automated rules
23+
- **Account Recovery**: Enhanced security with social recovery options
24+
25+
## Dashboard Configuration
26+
27+
To enable smart accounts for your Android application:
28+
29+
1. Navigate to your project in the [Web3Auth Dashboard](https://dashboard.web3auth.io)
30+
2. Go to **Project Settings****Smart Accounts**
31+
3. Enable smart accounts by toggling the switch
32+
4. Configure your preferred providers:
33+
- **Bundler**: Automatically configured (powered by Pimlico)
34+
- **Paymaster**: Choose between sponsored transactions or ERC-20 payments
35+
- **Smart Account Type**: Select your preferred implementation
36+
37+
## Implementation
38+
39+
### Checking Smart Account Status
40+
41+
Once configured in the dashboard, smart accounts are automatically used when users authenticate:
42+
43+
```kotlin
44+
// After successful authentication
45+
val userInfo = web3Auth.getUserInfo()
46+
val isSmartAccount = userInfo?.isSmartAccountEnabled ?: false
47+
48+
if (isSmartAccount) {
49+
// User has a smart account
50+
val smartAccountAddress = userInfo?.smartAccountAddress
51+
Log.d("Smart Account", "Address: $smartAccountAddress")
52+
}
53+
```
54+
55+
### Getting Smart Account Address
56+
57+
The smart account address is different from the EOA address:
58+
59+
```kotlin
60+
// Get EOA address (traditional wallet)
61+
val eoaAddress = web3Auth.getAddress()
62+
63+
// Get smart account address (from user info)
64+
val userInfo = web3Auth.getUserInfo()
65+
val smartAccountAddress = userInfo?.smartAccountAddress
66+
67+
Log.d("Addresses", "EOA: $eoaAddress, Smart Account: $smartAccountAddress")
68+
```
69+
70+
### Sending User Operations
71+
72+
With smart accounts enabled, you can send user operations through the `request` method:
73+
74+
```kotlin
75+
// Prepare user operation
76+
val userOp = JsonObject().apply {
77+
addProperty("sender", smartAccountAddress)
78+
addProperty("nonce", "0x0")
79+
addProperty("initCode", "0x")
80+
addProperty("callData", encodedCallData)
81+
addProperty("callGasLimit", "0x5208")
82+
addProperty("verificationGasLimit", "0x5208")
83+
addProperty("preVerificationGas", "0x5208")
84+
addProperty("maxFeePerGas", "0x3b9aca00")
85+
addProperty("maxPriorityFeePerGas", "0x3b9aca00")
86+
addProperty("paymasterAndData", "0x") // Auto-filled by dashboard config
87+
addProperty("signature", "0x")
88+
}
89+
90+
val params = JsonArray().apply {
91+
add(userOp)
92+
}
93+
94+
// Send user operation
95+
val userOpResult = web3Auth.request(
96+
"eth_sendUserOperation",
97+
requestParams = params
98+
)
99+
100+
userOpResult.whenComplete { result, error ->
101+
if (error == null) {
102+
val userOpHash = result?.get("result")?.asString
103+
Log.d("UserOp", "Hash: $userOpHash")
104+
} else {
105+
Log.e("UserOp", "Error: ${error.message}")
106+
}
107+
}
108+
```
109+
110+
### Batch Transactions
111+
112+
Execute multiple transactions in a single user operation:
113+
114+
```kotlin
115+
// Prepare multiple calls
116+
val calls = JsonArray().apply {
117+
// First call: Transfer ETH
118+
add(JsonObject().apply {
119+
addProperty("to", "0x...")
120+
addProperty("value", "0x1")
121+
addProperty("data", "0x")
122+
})
123+
124+
// Second call: ERC20 transfer
125+
add(JsonObject().apply {
126+
addProperty("to", erc20Address)
127+
addProperty("value", "0x0")
128+
addProperty("data", encodedTransferData)
129+
})
130+
}
131+
132+
// Encode batch call
133+
val batchCallData = encodeBatchCall(calls)
134+
135+
// Send as user operation
136+
val userOp = JsonObject().apply {
137+
addProperty("sender", smartAccountAddress)
138+
addProperty("callData", batchCallData)
139+
// ... other fields
140+
}
141+
```
142+
143+
### Gas Sponsorship
144+
145+
When configured in the dashboard, gas sponsorship is automatically handled:
146+
147+
```kotlin
148+
// Transaction with sponsored gas
149+
val sponsoredTx = JsonObject().apply {
150+
addProperty("to", recipientAddress)
151+
addProperty("value", "0x1000")
152+
addProperty("data", "0x")
153+
}
154+
155+
// The paymasterAndData field is automatically populated
156+
val result = web3Auth.request(
157+
"eth_sendTransaction",
158+
requestParams = JsonArray().apply { add(sponsoredTx) }
159+
)
160+
161+
// User pays nothing for gas!
162+
```
163+
164+
### ERC-20 Gas Payments
165+
166+
Allow users to pay gas fees with ERC-20 tokens:
167+
168+
```kotlin
169+
// Configure ERC-20 paymaster in dashboard first
170+
// Then transactions automatically use ERC-20 for gas
171+
172+
val transaction = JsonObject().apply {
173+
addProperty("to", recipientAddress)
174+
addProperty("value", amount)
175+
addProperty("data", "0x")
176+
// Specify the token for gas payment (optional)
177+
addProperty("paymasterData", JsonObject().apply {
178+
addProperty("token", "USDC")
179+
})
180+
}
181+
182+
val result = web3Auth.request(
183+
"eth_sendTransaction",
184+
requestParams = JsonArray().apply { add(transaction) }
185+
)
186+
```
187+
188+
## Wallet UI Integration
189+
190+
The `showWalletUI()` method automatically supports smart account features:
191+
192+
```kotlin
193+
// Launch wallet UI with smart account support
194+
val walletResult = web3Auth.showWalletUI()
195+
196+
walletResult.whenComplete { _, error ->
197+
if (error == null) {
198+
// Wallet UI will show:
199+
// - Smart account address
200+
// - Batch transaction options
201+
// - Gas sponsorship status
202+
// - ERC-20 gas payment options
203+
}
204+
}
205+
```
206+
207+
## Best Practices
208+
209+
### 1. Address Management
210+
211+
Always distinguish between EOA and smart account addresses:
212+
213+
```kotlin
214+
class WalletManager(private val web3Auth: Web3Auth) {
215+
216+
fun getActiveAddress(): String {
217+
val userInfo = web3Auth.getUserInfo()
218+
return if (userInfo?.isSmartAccountEnabled == true) {
219+
userInfo.smartAccountAddress ?: getEOAAddress()
220+
} else {
221+
getEOAAddress()
222+
}
223+
}
224+
225+
private fun getEOAAddress(): String {
226+
return web3Auth.getAddress()
227+
}
228+
}
229+
```
230+
231+
### 2. Error Handling
232+
233+
Handle smart account-specific errors:
234+
235+
```kotlin
236+
web3Auth.request(method, params).whenComplete { result, error ->
237+
when {
238+
error?.message?.contains("insufficient paymaster funds") == true -> {
239+
// Handle paymaster balance issues
240+
showError("Transaction sponsorship unavailable")
241+
}
242+
error?.message?.contains("user operation") == true -> {
243+
// Handle user operation errors
244+
showError("Smart account operation failed")
245+
}
246+
error != null -> {
247+
// Generic error handling
248+
showError(error.message ?: "Transaction failed")
249+
}
250+
else -> {
251+
// Success
252+
handleSuccess(result)
253+
}
254+
}
255+
}
256+
```
257+
258+
### 3. Feature Detection
259+
260+
Check for smart account features before using them:
261+
262+
```kotlin
263+
class SmartAccountFeatures(private val web3Auth: Web3Auth) {
264+
265+
fun isAvailable(): Boolean {
266+
val projectConfig = web3Auth.getProjectConfiguration()
267+
return projectConfig?.smartAccounts?.enabled == true
268+
}
269+
270+
fun isGasSponsorshipEnabled(): Boolean {
271+
val projectConfig = web3Auth.getProjectConfiguration()
272+
return projectConfig?.smartAccounts?.sponsorshipEnabled == true
273+
}
274+
275+
fun supportsBatchTransactions(): Boolean {
276+
return isAvailable() // All smart accounts support batching
277+
}
278+
}
279+
```
280+
281+
## Migration from EOA
282+
283+
If you're migrating from EOA to smart accounts:
284+
285+
```kotlin
286+
// Before (EOA)
287+
val address = web3Auth.getAddress()
288+
val privateKey = web3Auth.getPrivateKey()
289+
290+
// After (Smart Account)
291+
val userInfo = web3Auth.getUserInfo()
292+
val address = userInfo?.smartAccountAddress ?: web3Auth.getAddress()
293+
// Private key is managed by the smart account contract
294+
```
295+
296+
## Troubleshooting
297+
298+
### Common Issues
299+
300+
1. **Smart account not created**: Ensure smart accounts are enabled in dashboard
301+
2. **User operation failing**: Check bundler and paymaster configuration
302+
3. **Gas sponsorship not working**: Verify paymaster balance and limits
303+
4. **Wrong address used**: Always use `smartAccountAddress` for transactions
304+
305+
### Debug Mode
306+
307+
Enable verbose logging for smart account operations:
308+
309+
```kotlin
310+
val web3AuthOptions = Web3AuthOptions(
311+
// ... other options
312+
enableLogging = true
313+
)
314+
```
315+
316+
## Learn More
317+
318+
- [Account Abstraction Overview](/embedded-wallets/features/smart-accounts)
319+
- [ERC-4337 Specification](https://eips.ethereum.org/EIPS/eip-4337)
320+
- [Web3Auth Dashboard Guide](https://dashboard.web3auth.io)

0 commit comments

Comments
 (0)