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

Hardware wallet support for Ledger #43

Merged
merged 28 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a1efb6a
Add wallet abstraction
KingGorrin Jan 10, 2024
53865bf
Fix metadata
KingGorrin Jan 10, 2024
c567e2e
Restore pubspec
KingGorrin Jan 10, 2024
26bb02a
Fix pubspec
KingGorrin Jan 10, 2024
29a53e6
Add znn_ledger_dart library
KingGorrin Jan 11, 2024
0892b32
Disable backup/dump buttons
KingGorrin Jan 11, 2024
0550898
Use password as Hive cipherkey
KingGorrin Jan 11, 2024
653a7e9
Implement ledger support
KingGorrin Jan 22, 2024
c74ce0d
Migrate p2p tests and test runs
KingGorrin Jan 22, 2024
e6af3f8
Temporarily use kinggorrin libs
KingGorrin Jan 22, 2024
b09bd48
Send review notification after plasma is generated
KingGorrin Jan 23, 2024
1cbc135
Correct error messages
KingGorrin Jan 23, 2024
d6594dc
Add discreet mode test case
KingGorrin Jan 23, 2024
37a1c8e
Add wallet type to about card
KingGorrin Jan 23, 2024
0777e6d
Reorder wallet type in about card
KingGorrin Jan 23, 2024
c8575c3
Centralize and protect wallet access with mutex
KingGorrin Jan 24, 2024
27971a5
Fix pubspec.lock
KingGorrin Jan 24, 2024
763fdc4
Add udev rules and README
KingGorrin Jan 24, 2024
7b372ca
Update README
KingGorrin Jan 24, 2024
a6258fa
Fix not closed wallet when onboarding
KingGorrin Feb 1, 2024
4d4deb2
Resolve wallet type from wallet file metadata
KingGorrin Feb 9, 2024
7f879ff
Uppdate sdk ref
KingGorrin Feb 9, 2024
9baf536
Release lock on exception
KingGorrin Feb 11, 2024
dc2f59b
Confirm address when onboarding wallet
KingGorrin Feb 16, 2024
0d5765c
Clear tx pool and dispose wallet file on reset
KingGorrin Feb 17, 2024
6ff8cd2
Update znn_sdk_dart ref
KingGorrin Feb 26, 2024
58f5731
Update znn_ledger_dart ref
KingGorrin Feb 26, 2024
3e53c67
Update znn_sdk_dart ref
KingGorrin Feb 26, 2024
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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Cross-platform non-custodial wallet designed for Alphanet - Network of Momentum Phase 0.

Developed in Flutter using the [Zenon Dart SDK](https://github.com/zenon-network/znn_sdk_dart), `s y r i u s` wallet provides a simple and intuitive interface to interact with Network of Momentum Phase 0.
Developed in Flutter using the [Zenon Dart SDK](https://github.com/zenon-network/znn_sdk_dart) and [Ledger Wallet for Zenon Dart SDK](https://github.com/hypercore-one/znn_ledger_dart), `s y r i u s` wallet provides a simple and intuitive interface to interact with Network of Momentum Phase 0.

## Architecture

Expand All @@ -18,7 +18,7 @@ The wallet has a modular design with native full node integration. There are thr

Follow the instructions to install the [Flutter SDK](https://docs.flutter.dev/get-started/install). Check the [documentation](https://docs.flutter.dev/desktop) in order to setup the Flutter desktop environment.

Learn about the foreign function interface (ffi) [here](https://docs.flutter.dev/development/platform-integration/c-interop) that enables state-of-the art KDF - [Argon2](https://github.com/zenon-network/argon2_ffi), feeless transactions - [PoW links](https://github.com/zenon-network/znn-pow-links-cpp) and native full node integration - [Embedded Node](https://github.com/zenon-network/go-zenon).
Learn about the foreign function interface (ffi) [here](https://docs.flutter.dev/development/platform-integration/c-interop) that enables state-of-the art KDF - [Argon2](https://github.com/zenon-network/argon2_ffi), feeless transactions - [PoW links](https://github.com/zenon-network/znn-pow-links-cpp), native full node integration - [Embedded Node](https://github.com/zenon-network/go-zenon) and communication library between Ledger devices - [Ledger](https://github.com/hypercore-one/ledger_ffi_rs).

Dependencies:

Expand All @@ -36,6 +36,11 @@ flutter run --dart-define=WC_PROJECT_ID=walletconnect_project_id -d <os>
flutter build --dart-define=WC_PROJECT_ID=walletconnect_project_id <os>
```

## Linux

Note that on Linux you will need to install an udev rule file with your application for unprivileged users to be able to access HID devices with hidapi.
Refer to the [README](udev/) file in the udev directory for an example.

## Contributing

Please check [CONTRIBUTING](./CONTRIBUTING.md) for more details.
Expand Down
13 changes: 4 additions & 9 deletions lib/blocs/auto_receive_tx_worker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import 'package:zenon_syrius_wallet_flutter/main.dart';
import 'package:zenon_syrius_wallet_flutter/model/model.dart';
import 'package:zenon_syrius_wallet_flutter/utils/account_block_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class AutoReceiveTxWorker extends BaseBloc<WalletNotification> {
Expand All @@ -29,25 +28,21 @@ class AutoReceiveTxWorker extends BaseBloc<WalletNotification> {
running = true;
Hash currentHash = pool.first;
try {
String toAddress =
Address toAddress =
(await zenon!.ledger.getAccountBlockByHash(currentHash))!
.toAddress
.toString();
KeyPair keyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(toAddress),
);
.toAddress;
AccountBlockTemplate transactionParams = AccountBlockTemplate.receive(
currentHash,
);
AccountBlockTemplate response =
await AccountBlockUtils.createAccountBlock(
transactionParams,
'receive transaction',
blockSigningKey: keyPair,
address: toAddress,
waitForRequiredPlasma: true,
);
pool.removeFirst();
_sendSuccessNotification(response, toAddress);
_sendSuccessNotification(response, toAddress.toString());
} on RpcException catch (e, stackTrace) {
_sendErrorNotification(e.toString());
Logger('AutoReceiveTxWorker')
Expand Down
7 changes: 2 additions & 5 deletions lib/blocs/auto_unlock_htlc_worker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AutoUnlockHtlcWorker extends BaseBloc<WalletNotification> {
}

Future<void> autoUnlock() async {
if (pool.isNotEmpty && !running && kKeyStore != null) {
if (pool.isNotEmpty && !running && kWalletFile != null) {
running = true;
Hash currentHash = pool.first;
try {
Expand All @@ -38,16 +38,13 @@ class AutoUnlockHtlcWorker extends BaseBloc<WalletNotification> {
if (!kDefaultAddressList.contains(htlc.hashLocked.toString())) {
throw 'Swap address not in default addresses. Please add the address in the addresses list.';
}
KeyPair? keyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(htlc.hashLocked.toString()),
);
AccountBlockTemplate transactionParams = zenon!.embedded.htlc
.unlock(htlc.id, FormatUtils.decodeHexString(swap.preimage!));
AccountBlockTemplate response =
await AccountBlockUtils.createAccountBlock(
transactionParams,
'complete swap',
blockSigningKey: keyPair,
address: htlc.hashLocked,
waitForRequiredPlasma: true,
);
_sendSuccessNotification(response, htlc.hashLocked.toString());
Expand Down
5 changes: 3 additions & 2 deletions lib/blocs/blocs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ export 'auto_receive_tx_worker.dart';
export 'base_bloc.dart';
export 'base_bloc_for_reloading_indicator.dart';
export 'base_bloc_with_refresh_mixin.dart';
export 'decrypt_key_store_bloc.dart';
export 'decrypt_wallet_file_bloc.dart';
export 'hide_widget_status_bloc.dart';
export 'infinite_scroll_bloc.dart';
export 'key_store_path_bloc.dart';
export 'key_store_file_bloc.dart';
export 'ledger_wallet_file_bloc.dart';
export 'lock_bloc.dart';
export 'node_sync_status_bloc.dart';
export 'notifications_bloc.dart';
Expand Down
16 changes: 0 additions & 16 deletions lib/blocs/decrypt_key_store_bloc.dart

This file was deleted.

15 changes: 15 additions & 0 deletions lib/blocs/decrypt_wallet_file_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart';

class DecryptWalletFileBloc extends BaseBloc<WalletFile?> {
Future<void> decryptWalletFile(String path, String password) async {
try {
addEvent(null);
final walletFile = await WalletUtils.decryptWalletFile(path, password);
addEvent(walletFile);
} catch (e, stackTrace) {
addError(e, stackTrace);
}
}
}
4 changes: 2 additions & 2 deletions lib/blocs/hide_widget_status_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart';
import 'package:zenon_syrius_wallet_flutter/main.dart';
import 'package:zenon_syrius_wallet_flutter/utils/constants.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:zenon_syrius_wallet_flutter/utils/keystore_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/widget_utils.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

Expand All @@ -15,7 +15,7 @@ class HideWidgetStatusBloc extends BaseBloc<bool?> {
try {
addEvent(null);
if (!isHidden) {
await KeyStoreUtils.decryptKeyStoreFile(kKeyStorePath!, password);
await WalletUtils.decryptWalletFile(kWalletPath!, password);
}
await _markWidgetAsHidden(widgetTitle, isHidden);
addEvent(isHidden);
Expand Down
25 changes: 25 additions & 0 deletions lib/blocs/key_store_file_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'dart:async';
import 'dart:convert';

import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/init_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class KeyStoreFileBloc extends BaseBloc<KeyStoreWalletFile?> {
Future<void> getKeyStorePath(
String mnemonic,
String password,
) async {
try {
await WalletUtils.createKeyStoreWalletFile(mnemonic, password);
await InitUtils.initWalletAfterDecryption(
Crypto.digest(utf8.encode(password)));
addEvent(kWalletFile as KeyStoreWalletFile);
} catch (e, stackTrace) {
addError(e, stackTrace);
}
}
}
21 changes: 0 additions & 21 deletions lib/blocs/key_store_path_bloc.dart

This file was deleted.

26 changes: 26 additions & 0 deletions lib/blocs/ledger_wallet_file_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'dart:async';
import 'dart:convert';

import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/init_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class LedgerWalletFileBloc extends BaseBloc<LedgerWalletFile?> {
Future<void> getLedgerWalletPath(
String walletId,
String password,
) async {
try {
await WalletUtils.createLedgerWalletFile(
walletId, password);
await InitUtils.initWalletAfterDecryption(
Crypto.digest(utf8.encode(password)));
addEvent(kWalletFile as LedgerWalletFile);
} catch (e, stackTrace) {
addError(e, stackTrace);
}
}
}
5 changes: 1 addition & 4 deletions lib/blocs/p2p_swap/htlc_swap/complete_htlc_swap_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,8 @@ class CompleteHtlcSwapBloc extends BaseBloc<HtlcSwap?> {

AccountBlockTemplate transactionParams = zenon!.embedded.htlc.unlock(
Hash.parse(htlcId), FormatUtils.decodeHexString(swap.preimage!));
KeyPair blockSigningKeyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(swap.selfAddress.toString()),
);
AccountBlockUtils.createAccountBlock(transactionParams, 'complete swap',
blockSigningKey: blockSigningKeyPair, waitForRequiredPlasma: true)
address: Address.parse(swap.selfAddress), waitForRequiredPlasma: true)
.then(
(response) async {
swap.state = P2pSwapState.completed;
Expand Down
8 changes: 2 additions & 6 deletions lib/blocs/p2p_swap/htlc_swap/join_htlc_swap_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/account_block_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/date_time_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/format_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class JoinHtlcSwapBloc extends BaseBloc<HtlcSwap?> {
Expand All @@ -19,7 +18,7 @@ class JoinHtlcSwapBloc extends BaseBloc<HtlcSwap?> {
required P2pSwapChain fromChain,
required P2pSwapChain toChain,
required int counterHtlcExpirationTime,
}) {
}) async {
try {
addEvent(null);
AccountBlockTemplate transactionParams = zenon!.embedded.htlc.create(
Expand All @@ -31,11 +30,8 @@ class JoinHtlcSwapBloc extends BaseBloc<HtlcSwap?> {
initialHtlc.keyMaxSize,
initialHtlc.hashLock,
);
KeyPair blockSigningKeyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(initialHtlc.hashLocked.toString()),
);
AccountBlockUtils.createAccountBlock(transactionParams, 'join swap',
blockSigningKey: blockSigningKeyPair, waitForRequiredPlasma: true)
address: initialHtlc.hashLocked, waitForRequiredPlasma: true)
.then(
(response) async {
final swap = HtlcSwap(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,20 @@ import 'package:zenon_syrius_wallet_flutter/blocs/base_bloc.dart';
import 'package:zenon_syrius_wallet_flutter/main.dart';
import 'package:zenon_syrius_wallet_flutter/utils/account_block_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class ReclaimHtlcSwapFundsBloc extends BaseBloc<AccountBlockTemplate?> {
void reclaimFunds({
required Hash htlcId,
required Address selfAddress,
}) {
}) async {
try {
addEvent(null);
AccountBlockTemplate transactionParams =
zenon!.embedded.htlc.reclaim(htlcId);
KeyPair blockSigningKeyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(selfAddress.toString()),
);
AccountBlockUtils.createAccountBlock(
transactionParams, 'reclaim swap funds',
blockSigningKey: blockSigningKeyPair, waitForRequiredPlasma: true)
address: selfAddress, waitForRequiredPlasma: true)
.then(
(response) {
ZenonAddressUtils.refreshBalance();
Expand Down
6 changes: 1 addition & 5 deletions lib/blocs/p2p_swap/htlc_swap/start_htlc_swap_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/account_block_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/date_time_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/format_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class StartHtlcSwapBloc extends BaseBloc<HtlcSwap?> {
Expand Down Expand Up @@ -37,11 +36,8 @@ class StartHtlcSwapBloc extends BaseBloc<HtlcSwap?> {
htlcPreimageMaxLength,
hashLock.getBytes(),
);
KeyPair blockSigningKeyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(selfAddress.toString()),
);
AccountBlockUtils.createAccountBlock(transactionParams, 'start swap',
blockSigningKey: blockSigningKeyPair, waitForRequiredPlasma: true)
address: selfAddress, waitForRequiredPlasma: true)
.then(
(response) async {
final swap = HtlcSwap(
Expand Down
8 changes: 2 additions & 6 deletions lib/blocs/transfer/send_payment_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart';
import 'package:zenon_syrius_wallet_flutter/utils/account_block_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart';
import 'package:zenon_syrius_wallet_flutter/utils/global.dart';
import 'package:znn_sdk_dart/znn_sdk_dart.dart';

class SendPaymentBloc extends BaseBloc<AccountBlockTemplate?> {
Expand All @@ -13,7 +12,7 @@ class SendPaymentBloc extends BaseBloc<AccountBlockTemplate?> {
List<int>? data,
Token? token,
AccountBlockTemplate? block,
}) {
}) async {
assert(
block == null &&
fromAddress != null &&
Expand All @@ -31,13 +30,10 @@ class SendPaymentBloc extends BaseBloc<AccountBlockTemplate?> {
amount!,
data,
);
KeyPair blockSigningKeyPair = kKeyStore!.getKeyPair(
kDefaultAddressList.indexOf(fromAddress),
);
AccountBlockUtils.createAccountBlock(
accountBlock,
'send transaction',
blockSigningKey: blockSigningKeyPair,
address: Address.parse(fromAddress!),
waitForRequiredPlasma: true,
).then(
(response) {
Expand Down
3 changes: 3 additions & 0 deletions lib/model/database/notification_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ enum NotificationType {

@HiveField(14)
delete,

@HiveField(15)
confirm,
}
5 changes: 5 additions & 0 deletions lib/model/database/notification_type.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/model/database/wallet_notification.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class WalletNotification extends HiveObject {
return _getCircledIcon(Icons.link);
case NotificationType.delete:
return _getCircledIcon(Icons.delete_forever);
case NotificationType.confirm:
return _getCircledIcon(Icons.remove_red_eye,
iconColor: AppColors.alertNotification);
default:
return _getCircledIcon(MaterialCommunityIcons.arrow_top_right);
}
Expand Down
Loading
Loading