Skip to content

Commit

Permalink
docs: Add wallet app tutorial (#421)
Browse files Browse the repository at this point in the history
  • Loading branch information
lesnitsky authored Dec 1, 2024
1 parent 9ad0b07 commit 32c611c
Show file tree
Hide file tree
Showing 14 changed files with 239 additions and 2,431 deletions.
210 changes: 192 additions & 18 deletions docs/examples/mobile-wallet.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 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

```
Expand All @@ -8,30 +12,200 @@ flutter create wallet_app

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

2. Create a `contracts` folder and setup a scarb project.
2. Install and run [`starknet-devnet`](https://0xspaceshard.github.io/starknet-devnet-rs/docs/running/install)

3. Add necessary dependnecies

```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="0x05400e90f7e0ae78bd02c77cd75527280470e2fe19c54970dd79dc37a9d3645c"
RPC="http://127.0.0.1:5050/rpc"
```

> If you are building for Android, use `RPC="http://10.0.2.2:5050/rpc"` instead.
## Let's write some code

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

```dart
import 'package:flutter/material.dart';
- Install Rust
```
rustup override set stable && rustup update
```
- [Install scarb](https://docs.swmansion.com/scarb/docs/install) and run `scarb --version` to make sure it is working properly
- Run `scarb new contracts` in `wallet_app/`
- Run `scarb build` in `contracts/`
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();
}
```

3. Run starknet locally with devnet
Now let's intialize `wallet_kit` and `hive` in our `main` function

- `poetry new devnet`
- `cd devnet`
- `poetry add starknet-devnet`
- `poetry run starknet-devnet`
```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';
4. Add `deps`
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
- `flutter pub add starknet_flutter`
- ```
flutter pub add hooks_riverpod dev:custom_lint dev:riverpod_lint riverpod_annotation dev:build_runner dev:riverpod_generator
```
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 Layout2(
children: [
SizedBox(height: 32),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
WalletSelector(),
AccountAddress(),
],
),
SizedBox(height: 32),
WalletBody(),
SendEthButton(),
],
);
}
}
```

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! 💸
2 changes: 2 additions & 0 deletions examples/wallet_app/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ACCOUNT_CLASS_HASH="0x05400e90f7e0ae78bd02c77cd75527280470e2fe19c54970dd79dc37a9d3645c"
RPC="http://10.0.2.2:5050/rpc"
1 change: 1 addition & 0 deletions examples/wallet_app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
!.env
2 changes: 1 addition & 1 deletion examples/wallet_app/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '2.0.21'
repositories {
google()
mavenCentral()
Expand Down
1 change: 0 additions & 1 deletion examples/wallet_app/contracts
Submodule contracts deleted from 6ca81b
Empty file.
Empty file.
Loading

0 comments on commit 32c611c

Please sign in to comment.