Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.27.3'
flutter-version: '3.32.4'

- name: Install dependencies
run: flutter pub get
Expand Down
5 changes: 3 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
"type": "dart",
"program": "lib/main.dart",
"toolArgs": [
"run"
"run",
"--dart-define=API_KEY=your_api_key_here"
],
"args": []
}
]
}
}
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ flutter run
```
---

## 🛠 Environment Variables

This project requires the following environment variable for proper operation:

- `API_KEY`: Your API key for the Avnu provider. This is used by `AvnuRepositoryImpl` to connect to the StarkNet node. Set this value in your environment or pass it at build time.

Example (for development):
```bash
flutter run --dart-define=API_KEY=your_api_key_here
```


## Contribute to StarkWager
We welcome contributions to StarkWager! Check out our [Contributor's Guide](https://github.com/stakepoint/stark-wager-mobile/blob/dev/CONTRIBUTING.md) to get started.
Expand Down
4 changes: 3 additions & 1 deletion lib/core/network/api_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ class ApiClient {

ApiClient(this._dio) {
_dio.options = BaseOptions(
baseUrl: AppConfigs.baseUrl,
baseUrl: _dio.options.baseUrl.isNotEmpty
? _dio.options.baseUrl
: AppConfigs.baseUrl,
connectTimeout: const Duration(milliseconds: 30000),
receiveTimeout: const Duration(milliseconds: 30000),
responseType: ResponseType.json,
Expand Down
39 changes: 39 additions & 0 deletions lib/data/datasources/avnu_remote_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:starkwager/core/network/api_client.dart';

abstract class AvnuRemoteDataSource {
Future<Map<String, dynamic>> deployAccount(
{required String userAddress,
required String classHash,
required String salt,
required String unique,
required List<String> calldata,
required List<String> sigdata});
}

class AvnuRemoteDataSourceImpl implements AvnuRemoteDataSource {
final ApiClient apiClient;
AvnuRemoteDataSourceImpl(this.apiClient);
@override
Future<Map<String, dynamic>> deployAccount(
{required String userAddress,
required String classHash,
required String salt,
required String unique,
required List<String> calldata,
required List<String> sigdata}) async {
final ref = await apiClient.post(
'/paymaster/v1/deploy-account',
data: {
"userAddress": userAddress,
"deploymentData": {
"class_hash": classHash,
"salt": salt,
"unique": unique,
"calldata": calldata,
"sigdata": sigdata
}
},
);
return ref.data;
}
}
94 changes: 94 additions & 0 deletions lib/data/repositories/avnu_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'package:avnu_provider/avnu_provider.dart';
import 'package:starkwager/data/datasources/avnu_remote_datasource.dart';
import 'package:starkwager/domain/repositories/avnu_repository.dart';

class AvnuRepositoryImpl implements AvnuRepository {
late AvnuProvider _avnuProvider;
late AvnuReadProvider _avnuReadProvider;
final AvnuRemoteDataSource _avnuRemoteDataSource;

AvnuRepositoryImpl({required AvnuRemoteDataSource avnuRemoteDataSource})
: _avnuRemoteDataSource = avnuRemoteDataSource {
_initialize();
}

void _initialize() {
_avnuProvider = AvnuJsonRpcProvider(
nodeUri: Uri.parse("https://starknet-sepolia.public.blastapi.io"),
apiKey: String.fromEnvironment('API_KEY'),
);
_avnuReadProvider = AvnuJsonRpcReadProvider(
nodeUri: Uri.parse("https://starknet-sepolia.public.blastapi.io"),
apiKey: String.fromEnvironment('API_KEY'),
);
}

@override
Future<void> deployAccount({
required String userAddress,
required String classHash,
required String salt,
required String unique,
required List<String> calldata,
required List<String> sigdata,
}) async {
await _avnuRemoteDataSource.deployAccount(
userAddress: userAddress,
classHash: classHash,
salt: salt,
unique: unique,
calldata: calldata,
sigdata: sigdata,
);
}

@override
Future<AvnuAccountRewards> setUserLimit(
{required String address,
required String campaign,
required String protocol,
required int freeTx,
required DateTime expirationDate,
required List<Map<String, String>> whitelistedCalls}) async {
return await _avnuProvider.setAccountRewards(
address,
campaign,
protocol,
freeTx,
expirationDate.toIso8601String(),
whitelistedCalls,
);
}

@override
Future<AvnuBuildTypedData> registerTypedData(
{required String userAddress,
required List<Map<String, dynamic>> calls,
required String gasTokenAddress,
required String maxGasTokenAmount,
required String accountClassHash}) async {
return await _avnuProvider.buildTypedData(userAddress, calls,
gasTokenAddress, maxGasTokenAmount, accountClassHash);
}

@override
Future<AvnuExecute> executeContract(
{required String userAddress,
required String typedData,
required List<String> signature,
Map<dynamic, dynamic>? deploymentData}) async {
return await _avnuProvider.execute(
userAddress, typedData, signature, deploymentData);
}

@override
Future<AvnuGasTokenPrices> getGasTokenPrices() async {
return await _avnuReadProvider.getGasTokenPrices();
}

@override
Future<bool> checkAccountCompatibility({required String userAddress}) async {
final ref = await _avnuReadProvider.checkAccountCompatible(userAddress);
return ref is AvnuAccountCompatibleIsCompatible ? true : false;
}
}
37 changes: 37 additions & 0 deletions lib/domain/repositories/avnu_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:avnu_provider/avnu_provider.dart';

abstract class AvnuRepository {
Future<void> deployAccount({
required String userAddress,
required String classHash,
required String salt,
required String unique,
required List<String> calldata,
required List<String> sigdata,
});

Future<AvnuAccountRewards> setUserLimit(
{required String address,
required String campaign,
required String protocol,
required int freeTx,
required DateTime expirationDate,
required List<Map<String, String>> whitelistedCalls});

Future<AvnuBuildTypedData> registerTypedData(
{required String userAddress,
required List<Map<String, dynamic>> calls,
required String gasTokenAddress,
required String maxGasTokenAmount,
required String accountClassHash});

Future<AvnuExecute> executeContract(
{required String userAddress,
required String typedData,
required List<String> signature,
Map<dynamic, dynamic>? deploymentData});

Future<AvnuGasTokenPrices> getGasTokenPrices();

Future<bool> checkAccountCompatibility({required String userAddress});
}
3 changes: 2 additions & 1 deletion lib/features/connect_wallet/connect_wallet_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class _ConnectWalletScreen extends ConsumerState<ConnectWalletScreen> {
final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
chainId,
);
final address = next.service.session!.getAddress(namespace)!;
final address = next.service.session?.getAddress(namespace);
if (address == null) return;

// Call create login endpoint with this address and trigger AuthLoading state
await ref
Expand Down
16 changes: 16 additions & 0 deletions lib/features/connect_wallet/provider/avnu_repository_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:starkwager/core/network/api_client.dart';
import 'package:starkwager/data/datasources/avnu_remote_datasource.dart';
import 'package:starkwager/data/repositories/avnu_repository_impl.dart';
import 'package:starkwager/domain/repositories/avnu_repository.dart';

final avnuRemoteDataSourceProvider = Provider<AvnuRemoteDataSource>((ref) {
return AvnuRemoteDataSourceImpl(
ApiClient(Dio(BaseOptions(baseUrl: "https://sepolia.api.avnu.fi/"))));
});

final avnuRepositoryProvider = Provider<AvnuRepository>((ref) {
final remoteDataSource = ref.watch(avnuRemoteDataSourceProvider);
return AvnuRepositoryImpl(avnuRemoteDataSource: remoteDataSource);
});
Loading