> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Account Abstraction

> Gasless and batched EVM transactions on Flutter using Alchemy smart accounts backed by Para

The Flutter SDK can spin up an Alchemy smart account for any EVM wallet your user holds. The Para wallet signs; the smart account is what shows up on-chain. You get gas sponsorship through Alchemy's Gas Manager and atomic batched calls through the Account Kit.

<Note>
  Only Alchemy (EIP-4337) is wired through the native bridge today. ZeroDev, Pimlico, and the other providers already available on web and React Native are on the roadmap for Flutter.
</Note>

## Setup

1. Create an [Alchemy account](https://dashboard.alchemy.com/signup), grab your **API key**, and create a Gas Manager **policy** for the chain you're targeting. The policy ID is what tells the paymaster to sponsor gas.

2. Drop the values into your `.env` file. `flutter_dotenv` is already wired into the Flutter example:

```bash .env theme={null}
ALCHEMY_API_KEY=your_alchemy_api_key
ALCHEMY_GAS_POLICY_ID=your_gas_policy_id
```

You don't need to add a pub.dev dependency. The Flutter SDK reaches `@getpara/aa-alchemy` through the bridge on the web side.

## Usage

Create the smart account, then send a gasless transaction with it:

```dart theme={null}
import 'package:para/para.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

// `para` is your authenticated Para instance
final info = await para.createSmartAccount(
  apiKey: dotenv.env['ALCHEMY_API_KEY']!,
  chainId: 11155111, // Sepolia
  gasPolicyId: dotenv.env['ALCHEMY_GAS_POLICY_ID'],
);
print('Smart account: ${info.smartAccountAddress}');

// Zero-value tx to the burn address, paid for by the paymaster.
final receipt = await para.sendSmartAccountTransaction(
  smartAccountAddress: info.smartAccountAddress,
  chainId: 11155111,
  to: '0x000000000000000000000000000000000000dEaD',
);
print('tx: ${receipt.transactionHash}, status: ${receipt.status}');
```

Heads up on timing: UserOp inclusion on a public chain usually lands in 30 to 90 seconds, and the call blocks until it does. `ParaConfig.requestTimeout` defaults to 120s for this reason. Override it when you build your `ParaConfig` if you'd rather bail earlier.

### Batched transactions

One UserOp, multiple calls, one receipt. Use it for approve + swap, approve + transfer, or anything that should succeed or fail together:

```dart theme={null}
final batchReceipt = await para.sendSmartAccountBatchTransaction(
  smartAccountAddress: info.smartAccountAddress,
  chainId: 11155111,
  calls: [
    SmartAccountCall(to: '0xRecipientA', value: '10000000000000000'), // 0.01 ETH
    SmartAccountCall(to: '0xRecipientB', data: '0xEncodedCallData'),
  ],
);
```

### Error handling

Provider failures come back with a `SmartAccountErrorCode` from `@getpara/core-sdk`. The ones you're most likely to see:

* `PROVIDER_RATE_LIMITED`: back off and retry.
* `SPONSORSHIP_DENIED`: the gas policy rejected this UserOp. Check the Alchemy dashboard.
* `TRANSACTION_REVERTED`: the target contract reverted at execution time.
* `MISSING_ACCOUNT_ADDRESS`: you called `sendSmartAccountTransaction` before `createSmartAccount` for this chain + address.

Errors surface as `ParaBridgeException` and keep the provider's original message.

## What gets returned

`createSmartAccount` returns a `SmartAccountInfo`:

```dart theme={null}
class SmartAccountInfo {
  final String smartAccountAddress;
  final String mode;        // "4337"
  final String provider;    // "ALCHEMY"
  final int chainId;
}
```

`sendSmartAccountTransaction` and `sendSmartAccountBatchTransaction` return an `AATransactionReceipt`:

```dart theme={null}
class AATransactionReceipt {
  final String transactionHash;
  final String blockHash;
  final String blockNumber;       // uint256, decimal string
  final String from;
  final String? to;
  final String status;            // "success" or "reverted"
  final String gasUsed;
  final String effectiveGasPrice;
}
```

BigInt fields arrive as decimal strings so you don't lose `uint256` precision across the bridge.

## Reference

Full working implementation: [`examples-hub/mobile/with-flutter/lib/features/smart_account/smart_account_screen.dart`](https://github.com/getpara/examples-hub/tree/3.0.0/mobile/with-flutter/lib/features/smart_account).
