# How to build a mobile wallet for Starknet

In this tutorial we will build a mobile wallet app.

## Pre-requisites

1. Create a new flutter project

```bash
flutter create wallet_app
```

Run it locally with `flutter run` to make sure it is properly configured.

2. Install and run [`starknet-devnet`](https://0xspaceshard.github.io/starknet-devnet-rs/docs/running/install)

3. Add necessary dependencies

```bash
flutter pub add wallet_kit hive_flutter hooks_riverpod flutter_dotenv
```

4. Create a `.env` file in the root of your wallet_app project

```bash
ACCOUNT_CLASS_HASH="0x05b4b537eaa2399e3aa99c4e2e0208ebd6c71bc1467938cd52c798c601e43564"
RPC="http://127.0.0.1:5050/rpc"
```

> Please note that `ACCOUNT_CLASS_HASH` must match the one used by your version of `starknet-devnet`, it's displayed at startup.
Here is the value for `starknet-devnet 0.4.2`
> ```
> Predeployed accounts using class with hash: 0x05b4b537eaa2399e3aa99c4e2e0208ebd6c71bc1467938cd52c798c601e43564
> ```

> If you are running on another device than the host running `starknet-devnet`, you should use the external IP of your host running and start `starknet-devnet` with `--host 0.0.0.0` argument


5. Add `.env` file in your `pubspec.yaml`
```yaml
  assets:
    - .env
```

6. Update Android minimun SDK version

`secure_store` package used by `wallet_kit` require Android minimum SDK version set to at least 23, you need to modify `android/app/build.gradle`:
```
    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId = "com.example.wallet_app"
        // You can update the following values to match your application needs.
        // For more information, see: https://flutter.dev/to/review-gradle-config.
        minSdk = 23
        targetSdk = flutter.targetSdkVersion
        versionCode = flutter.versionCode
        versionName = flutter.versionName
    }
```

7. Biometric support (optional)

In order to use `Biometric` on Android, your `MainActivity` must inherit from `FlutterFragmentActivity` instead of `FlutterActity`.
You need to modify your `MainActivity.kt` with:
```kotlin
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity()
```

## Let's write some code

Let's start with a simple `main` function in your 'main.dart' file.

```dart
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
}
```

We will need to load our environment variables using `flutter_dotenv` package

```dart
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await dotenv.load();
}
```

Now let's intialize `wallet_kit` and `hive` in our `main` function

```dart
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:wallet_kit/wallet_kit.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await dotenv.load();

  await WalletKit().init(
    accountClassHash: dotenv.env['ACCOUNT_CLASS_HASH'] as String,
    rpc: dotenv.env['RPC'] as String,
  );

  await Hive.initFlutter();
}
```

Let's also setup device orientation and system ui overlay

```dart
SystemChrome.setEnabledSystemUIMode(
    SystemUiMode.edgeToEdge,
  );

  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);

  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarIconBrightness: Brightness.dark,
    systemNavigationBarColor: Colors.transparent,
    systemNavigationBarDividerColor: Colors.transparent,
    systemNavigationBarIconBrightness: Brightness.dark,
  ));
```

Finally we can create an App widget and run our app:

```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:wallet_kit/wallet_kit.dart';

import './screens/home_screen.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await dotenv.load();

  WalletKit().init(
    accountClassHash: dotenv.env['ACCOUNT_CLASS_HASH'] as String,
    rpc: dotenv.env['RPC'] as String,
  );

  await Hive.initFlutter();

  SystemChrome.setEnabledSystemUIMode(
    SystemUiMode.edgeToEdge,
  );

  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);

  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarIconBrightness: Brightness.dark,
    systemNavigationBarColor: Colors.transparent,
    systemNavigationBarDividerColor: Colors.transparent,
    systemNavigationBarIconBrightness: Brightness.dark,
  ));

  runApp(const ProviderScope(child: WalletApp()));
}

class WalletApp extends HookConsumerWidget {
  const WalletApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return MaterialApp(
      title: 'Starknet Wallet',
      home: const Placeholder(),
      theme: walletThemeData,
      debugShowCheckedModeBanner: false,
    );
  }
}
```

Create a `screens/` folder and add `home_screen.dart` file with a pre-built layout from `wallet_kit`, as well as `WalletSelector`, `AccountAddress`, `WalletBody` and `SendEthButton`:

```dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:wallet_kit/wallet_kit.dart';

class HomeScreen extends HookConsumerWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return const Scaffold(
      body: Layout2(
        children: [
          SizedBox(height: 32),
          Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              WalletSelector(),
              AccountAddress(),
              DeployAccountButton(),
            ],
          ),
          SizedBox(height: 32),
          WalletBody(),
          SendEthButton(),
          WalletErrorHandler(),
        ],
      ),
    );
  }
}
```

Now replace `home: const Placeholder()` with `home: const HomeScreen()` in `main.dart`. Your WalletApp should now look like this:

```dart
import './screens/home_screen.dart';

class WalletApp extends HookConsumerWidget {
  const WalletApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return MaterialApp(
      title: 'Starknet Wallet',
      home: const HomeScreen(),
      theme: walletThemeData,
      debugShowCheckedModeBanner: false,
    );
  }
}
```

Now you can run your app with `flutter run` and see your wallet in action! 💸

---

Deploying an account requires some ETH to pay transaction fees.
With `starknet-devnet`, you can mint some ETH to your account address with the following command:
```shell
curl --silent -H 'Content-type: application/json' \
  -X POST http://localhost:5050/mint \
  -d '{"address": ""<YOUR_ACCOUNT_ADDRESS>"", "amount": 20000000000000000000, "unit": "WEI"}'
```
```console
{"new_balance":"20000000000000000000","unit":"WEI","tx_hash":"0x9d2d26cef777c50b64475592e0df6e6c6012014e660f97bb37aaf5138aff54"}
```
