Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persistence - Wallet Addresses Storage #41

Draft
wants to merge 24 commits into
base: add_arrr
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c89d825
create WalletAddress
naezith Jun 27, 2023
b7d13c1
create AccountAddressesApiInterface
naezith Jun 27, 2023
4ee8952
create AccountAddressesApiHive
naezith Jun 27, 2023
0b25c30
validation and cleanup for AccountAddressesApiHive
naezith Jun 27, 2023
3cf3d9e
error handling for AccountAddressesApiHive
naezith Jun 27, 2023
01f5cab
field params instead of WalletAddress obj
naezith Jun 27, 2023
90b1541
updateOrCreate for AccountAddressesApiHive
naezith Jun 27, 2023
14748a4
factory for AccountAddressesApiHive
naezith Jun 27, 2023
cb92f78
HiveException for AccountAddressesApiHive
naezith Jun 27, 2023
562b899
FutureOr for AccountAddressesApiHive init
naezith Jun 27, 2023
dc8fa90
store original exception in HiveException
naezith Jun 27, 2023
448162a
remove comment
naezith Jun 27, 2023
16bb0ca
call Hive.registerAdapter only once
naezith Jun 28, 2023
8d7d6ee
add trailing commas
naezith Jun 28, 2023
b0b6fa7
added @required and named params
naezith Jun 28, 2023
f5809ab
implement AccountAddressesRepository
naezith Jun 28, 2023
1b3066b
atomic AccountAddressesRepository
naezith Jun 29, 2023
010fcc5
cancel AddressRepository subscription earlier
naezith Jun 29, 2023
3ea1e55
remove custom HiveException
naezith Jul 3, 2023
fac2231
Add a real-time stream for active wallet changes
CharlVS Jul 3, 2023
e1e8ba2
Add stream for wallet snapshot changes
CharlVS Jul 3, 2023
7197b76
Add wallet address serialisation metods
CharlVS Jul 4, 2023
8631c9b
Save wallet changes in DB class methods
CharlVS Jul 4, 2023
9d3548e
Add realtime address list helper method for bloc
CharlVS Jul 4, 2023
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
164 changes: 164 additions & 0 deletions lib/packages/account_addresses/api/account_addresses_api_hive.dart
naezith marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import 'dart:async';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:komodo_dex/packages/account_addresses/api/account_addresses_api_interface.dart';
import 'package:komodo_dex/packages/account_addresses/models/wallet_address.dart';

class HiveException implements Exception {
naezith marked this conversation as resolved.
Show resolved Hide resolved
final String message;
final Exception originalException;

HiveException(this.message, [this.originalException]);

@override
String toString() => 'HiveException: $message';
}

class AccountAddressesApiHive implements AccountAddressesApiInterface {
final Box<WalletAddress> _box;

AccountAddressesApiHive._(this._box);

static FutureOr<AccountAddressesApiHive> initialize() async {
naezith marked this conversation as resolved.
Show resolved Hide resolved
Hive.registerAdapter(WalletAddressAdapter());
Box<WalletAddress> box;
try {
box = await Hive.openBox<WalletAddress>('account_addresses');
} catch (e) {
throw HiveException('Failed to open Hive box: $e', e);
}
return AccountAddressesApiHive._(box);
}

String _getKey(String walletId, String address) {
return '${walletId}_$address';
}

@override
Future<void> create(String walletId, String address, String ticker,
double availableBalance, String accountId) async {
_validateFields(walletId, address, availableBalance);
try {
await _box.put(
_getKey(walletId, address),
WalletAddress(
walletId: walletId,
address: address,
ticker: ticker,
availableBalance: availableBalance,
accountId: accountId));
} catch (e) {
throw HiveException('Failed to create WalletAddress: $e', e);
}
}

@override
Future<void> updateOrCreate(String walletId, String address, String ticker,
double availableBalance, String accountId) async {
final key = _getKey(walletId, address);
if (_box.containsKey(key)) {
await update(walletId, address,
ticker: ticker,
availableBalance: availableBalance,
accountId: accountId);
} else {
await create(walletId, address, ticker, availableBalance, accountId);
}
}

@override
Future<void> update(String walletId, String address,
{String ticker, double availableBalance, String accountId}) async {
_validateFields(walletId, address, availableBalance);
final key = _getKey(walletId, address);
final existingWalletAddress = _box.get(key);

if (existingWalletAddress == null) {
throw Exception('WalletAddress not found');
}

final updatedWalletAddress = WalletAddress(
walletId: walletId,
address: address,
ticker: ticker ?? existingWalletAddress.ticker,
availableBalance:
availableBalance ?? existingWalletAddress.availableBalance,
accountId: accountId ?? existingWalletAddress.accountId,
);

try {
await _box.put(key, updatedWalletAddress);
} catch (e) {
throw HiveException('Failed to update WalletAddress: $e', e);
}
}

@override
Future<void> deleteOne(String walletId, String address) async {
try {
await _box.delete(_getKey(walletId, address));
} catch (e) {
throw HiveException('Failed to delete WalletAddress: $e', e);
}
}

@override
Future<void> deleteAll(String walletId) async {
final keys = _box.keys.where((key) => key.startsWith(walletId));
try {
await _box.deleteAll(keys);
} catch (e) {
throw HiveException('Failed to delete WalletAddresses: $e', e);
}
}

@override
Future<WalletAddress> readOne(String walletId, String address) async {
try {
return _box.get(_getKey(walletId, address));
} catch (e) {
throw HiveException('Failed to read WalletAddress: $e', e);
}
}

@override
Future<List<WalletAddress>> readAll(String walletId) async {
try {
return _box.values
.where((walletAddress) => walletAddress.walletId == walletId)
.toList();
} catch (e) {
throw HiveException('Failed to read WalletAddresses: $e', e);
}
}

@override
Stream<WalletAddress> watchAll(String walletId) {
return _box
.watch()
.where((event) =>
event.key.startsWith(walletId) && event.value is WalletAddress)
.map((event) => event.value as WalletAddress);
}

Future<void> close() async {
try {
await _box.close();
} catch (e) {
throw HiveException('Failed to close Hive box: $e', e);
}
}

void _validateFields(
String walletId, String address, double availableBalance) {
if (walletId == null || walletId.isEmpty) {
throw ArgumentError('Wallet ID must not be empty');
}
if (address == null || address.isEmpty) {
throw ArgumentError('Address must not be empty');
}
if (availableBalance == null || availableBalance < 0) {
throw ArgumentError('Available balance must be non-negative');
}
}
}
naezith marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:komodo_dex/packages/account_addresses/models/wallet_address.dart';

abstract class AccountAddressesApiInterface {
Future<void> create(String walletId, String address, String ticker,
double availableBalance, String accountId);
Future<void> update(String walletId, String address,
{String ticker, double availableBalance, String accountId});
Future<void> updateOrCreate(String walletId, String address, String ticker,
double availableBalance, String accountId);
Future<void> deleteOne(String walletId, String address);
Future<void> deleteAll(String walletId);
Future<WalletAddress> readOne(String walletId, String address);
Future<List<WalletAddress>> readAll(String walletId);
Stream<WalletAddress> watchAll(String walletId);
}
29 changes: 29 additions & 0 deletions lib/packages/account_addresses/models/wallet_address.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:hive/hive.dart';

part 'wallet_address.g.dart';

@HiveType(typeId: 0)
class WalletAddress {
@HiveField(0)
String walletId;

@HiveField(1)
String address;

@HiveField(2)
String ticker;

@HiveField(3)
double availableBalance;

@HiveField(4)
String accountId;

WalletAddress({
this.walletId,
this.address,
this.ticker,
this.availableBalance,
this.accountId,
});
}
26 changes: 26 additions & 0 deletions lib/packages/account_addresses/models/wallet_address.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
part of 'wallet_address.dart';

class WalletAddressAdapter extends TypeAdapter<WalletAddress> {
@override
final typeId = 0;

@override
WalletAddress read(BinaryReader reader) {
return WalletAddress(
walletId: reader.read(),
address: reader.read(),
ticker: reader.read(),
availableBalance: reader.read(),
accountId: reader.read(),
);
}

@override
void write(BinaryWriter writer, WalletAddress obj) {
writer.write(obj.walletId);
writer.write(obj.address);
writer.write(obj.ticker);
writer.write(obj.availableBalance);
writer.write(obj.accountId);
}
}
14 changes: 14 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
hive:
dependency: "direct main"
description:
name: hive
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
hive_flutter:
dependency: "direct main"
description:
name: hive_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
http:
dependency: "direct main"
description:
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ dependencies:

# "Flutter Favorite" plugin (https://docs.flutter.dev/packages-and-plugins/favorites)
flutter_local_notifications: ^12.0.4 # TODO: Secure code review of this plugin.
hive: ^2.2.3
hive_flutter: ^1.1.0



Expand Down