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

# Architecture

> How the package is structured and how it interacts with your app.

## Package structure

```
bmoni_embedded_wallets_cards/
├── constants/       EmbeddedWalletCacheKeys
├── contracts/       EmbeddedWalletReadDataSource
│                    EmbeddedWalletStorage
│                    EmbeddedWalletBalanceCache
├── failures/        EmbeddedFailure and subtypes
├── models/          EmbeddedWallet and all response/transaction types
├── notifiers/       EmbeddedWalletListNotifier
│                    EmbeddedWalletBalanceNotifier
│                    EmbeddedWalletTransactionsNotifier
└── widgets/         EmbeddedWalletCard
                     EmbeddedWalletTransactionsSection
```

***

## Dependency direction

```
Your app (Riverpod providers, navigation, auth)
    │
    ▼  instantiates notifiers and provides contracts
Notifiers (EmbeddedWalletListNotifier, ...)
    │
    ▼  depend on contracts you implement
Contracts (EmbeddedWalletReadDataSource, EmbeddedWalletStorage, ...)
    │
    ▼  you implement these against your API / DB
Your data layer (HTTP client, local DB, in-memory cache, ...)
```

Widgets consume notifier state but never call contracts directly.

***

## Data flow

1. Your Riverpod provider instantiates a notifier, injecting your contract implementations.
2. Your screen calls a notifier method (e.g. `fetchWallets()`).
3. The notifier calls the contract, maps the result to an `Either<EmbeddedFailure, T>`, and emits new state.
4. Widgets observe state and rebuild.

```dart theme={null}
// 1. Provider — inject your contracts
final walletListProvider =
    StateNotifierProvider<EmbeddedWalletListNotifier, EmbeddedWalletListState>(
  (ref) => EmbeddedWalletListNotifier(
    walletDataSource: ref.watch(walletDataSourceProvider),
    storage: ref.watch(walletStorageProvider),
  ),
);

// 2. Screen — trigger a fetch
await ref.read(walletListProvider.notifier).fetchWallets();

// 3. Widget — observe state
final EmbeddedWalletListState state = ref.watch(walletListProvider);
```

***

## Error model

All notifier methods return `void` / `Future<void>`. Failures are surfaced through the `hasError` / `failure` fields of each state class:

```dart theme={null}
final state = ref.watch(walletListProvider);

if (state.hasError) {
  final EmbeddedFailure failure = state.failure!;
  // failure is one of the EmbeddedFailure subtypes
}
```

See [Failures](/wallets/data-contracts#failures) for all subtypes.

***

## Offline & caching strategy

Each notifier accepts optional `EmbeddedWalletStorage` and `EmbeddedWalletBalanceCache` contracts. When a fetch fails (network error), the notifier transparently falls back to cached data:

```dart theme={null}
// On first load, pass isCache: true to prefer cached data
await ref.read(walletBalancesProvider.notifier)
    .fetchWalletBalances(ids, isCache: true);

// On pull-to-refresh, bypass the cache
await ref.read(walletBalancesProvider.notifier)
    .fetchWalletBalances(ids, isCache: false);
```
