diff --git a/app/lib/common/components/account_select_list.dart b/app/lib/common/components/account_select_list.dart index dfa804d5a..6f78d3312 100644 --- a/app/lib/common/components/account_select_list.dart +++ b/app/lib/common/components/account_select_list.dart @@ -2,6 +2,7 @@ import 'package:encointer_wallet/common/components/address_icon.dart'; import 'package:encointer_wallet/store/account/types/account_data.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; +import 'package:ew_keyring/ew_keyring.dart'; import 'package:flutter/material.dart'; class AccountSelectList extends StatelessWidget { @@ -14,7 +15,7 @@ class AccountSelectList extends StatelessWidget { Widget build(BuildContext context) { return ListView( children: accounts.map((account) { - final address = Fmt.ss58Encode(account.pubKey, prefix: store.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(account.pubKey, prefix: store.settings.endpoint.ss58!); return ListTile( leading: AddressIcon(address, account.pubKey), diff --git a/app/lib/common/components/address_input_field.dart b/app/lib/common/components/address_input_field.dart index 87a5eafdd..cc3ee6083 100644 --- a/app/lib/common/components/address_input_field.dart +++ b/app/lib/common/components/address_input_field.dart @@ -1,5 +1,4 @@ import 'package:dropdown_search/dropdown_search.dart'; -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/material.dart'; import 'package:encointer_wallet/common/components/address_icon.dart'; @@ -8,6 +7,8 @@ import 'package:encointer_wallet/store/account/types/account_data.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class AddressInputField extends StatefulWidget { const AddressInputField( @@ -35,7 +36,7 @@ class _AddressInputFieldState extends State { final ss58 = widget.store.settings.endpoint.ss58!; // we can't just use account.address unfortunately, see #1019. return account.name.startsWith(nameOrAddress.trim()) || - Fmt.ss58Encode(account.pubKey, prefix: ss58).startsWith(nameOrAddress.trim()); + AddressUtils.pubKeyHexToAddress(account.pubKey, prefix: ss58).startsWith(nameOrAddress.trim()); } Widget _selectedItemBuilder(BuildContext context, AccountData? account) { @@ -43,7 +44,7 @@ class _AddressInputFieldState extends State { return Container(); } - final address = Fmt.ss58Encode(account.pubKey, prefix: widget.store.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(account.pubKey, prefix: widget.store.settings.endpoint.ss58!); return Container( padding: const EdgeInsets.only(top: 8), @@ -70,7 +71,7 @@ class _AddressInputFieldState extends State { } Widget _listItemBuilder(BuildContext context, AccountData account, bool isSelected) { - final address = Fmt.ss58Encode(account.pubKey, prefix: widget.store.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(account.pubKey, prefix: widget.store.settings.endpoint.ss58!); return Container( margin: const EdgeInsets.symmetric(horizontal: 8), @@ -115,7 +116,7 @@ class _AddressInputFieldState extends State { emptyBuilder: (context, searchEntry) { if (Fmt.isAddress(searchEntry)) { final address = searchEntry.replaceAll(' ', ''); - final pubKey = Fmt.ss58Decode(address).pubKey; + final pubKey = AddressUtils.addressToPubKeyHex(address); final newAccount = AccountData() ..address = address ..pubKey = pubKey diff --git a/app/lib/models/transfer/transfer_history.dart b/app/lib/models/transfer/transfer_history.dart index b71e6f816..b5f082aec 100644 --- a/app/lib/models/transfer/transfer_history.dart +++ b/app/lib/models/transfer/transfer_history.dart @@ -1,11 +1,11 @@ -import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:flutter/material.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:encointer_wallet/l10n/l10.dart'; import 'package:encointer_wallet/utils/extensions/double/double_extension.dart'; import 'package:encointer_wallet/store/account/types/account_data.dart'; -import 'package:encointer_wallet/l10n/l10.dart'; -import 'package:encointer_wallet/utils/format.dart'; +import 'package:encointer_wallet/service/log/log_service.dart'; +import 'package:ew_keyring/ew_keyring.dart'; part 'transfer_history.g.dart'; @@ -51,7 +51,7 @@ class Transaction { try { // Contact address might be with default prefix 42, or with Kusama prefix 2. // So better to work with the universal pubKey. - if (contact.pubKey == Fmt.ss58Decode(counterParty).pubKey) { + if (contact.pubKey == AddressUtils.addressToPubKeyHex(counterParty)) { return contact.name; } } catch (e) { diff --git a/app/lib/modules/account/logic/new_account_store.dart b/app/lib/modules/account/logic/new_account_store.dart index 232f86304..f14af3be6 100644 --- a/app/lib/modules/account/logic/new_account_store.dart +++ b/app/lib/modules/account/logic/new_account_store.dart @@ -6,7 +6,7 @@ import 'package:encointer_wallet/modules/modules.dart'; import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/service/substrate_api/api.dart'; import 'package:encointer_wallet/store/app.dart'; -import 'package:encointer_wallet/utils/format.dart'; +import 'package:ew_keyring/ew_keyring.dart'; import 'package:provider/provider.dart'; part 'new_account_store.g.dart'; @@ -68,7 +68,8 @@ abstract class _NewAccountStoreBase with Store { await context.read().setPin(pin); final appStore = context.read(); - acc['address'] = Fmt.ss58Encode(acc['pubKey'] as String, prefix: appStore.settings.endpoint.ss58!); + acc['address'] = + AddressUtils.pubKeyHexToAddress(acc['pubKey'] as String, prefix: appStore.settings.endpoint.ss58!); return saveAccount(webApi, appStore, acc, pin); } catch (e, s) { _loading = false; @@ -93,7 +94,8 @@ abstract class _NewAccountStoreBase with Store { } else { await context.read().setPin(pin); final appStore = context.read(); - acc['address'] = Fmt.ss58Encode(acc['pubKey'] as String, prefix: appStore.settings.endpoint.ss58!); + acc['address'] = + AddressUtils.pubKeyHexToAddress(acc['pubKey'] as String, prefix: appStore.settings.endpoint.ss58!); final index = appStore.account.accountList.indexWhere((i) => i.pubKey == acc['pubKey']); if (index > -1) { _loading = false; diff --git a/app/lib/modules/account/view/import_account_view.dart b/app/lib/modules/account/view/import_account_view.dart index b6d654acb..e1fa6f6ca 100644 --- a/app/lib/modules/account/view/import_account_view.dart +++ b/app/lib/modules/account/view/import_account_view.dart @@ -6,7 +6,6 @@ import 'package:provider/provider.dart'; import 'package:encointer_wallet/common/components/encointer_text_form_field.dart'; import 'package:encointer_wallet/theme/theme.dart'; -import 'package:encointer_wallet/utils/validate_keys.dart'; import 'package:encointer_wallet/common/components/form/scrollable_form.dart'; import 'package:encointer_wallet/common/components/gradient_elements.dart'; import 'package:encointer_wallet/common/components/loading/centered_activity_indicator.dart'; @@ -17,6 +16,7 @@ import 'package:encointer_wallet/utils/alerts/app_alert.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/utils/input_validation.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart' show ValidateKeys; class ImportAccountView extends StatelessWidget { const ImportAccountView({super.key}); diff --git a/app/lib/modules/transfer/logic/transfer_history_view_store.dart b/app/lib/modules/transfer/logic/transfer_history_view_store.dart index fecb6e5dd..24d4552c7 100644 --- a/app/lib/modules/transfer/logic/transfer_history_view_store.dart +++ b/app/lib/modules/transfer/logic/transfer_history_view_store.dart @@ -1,13 +1,13 @@ // ignore_for_file: library_private_types_in_public_api -import 'package:encointer_wallet/service/log/log_service.dart'; -import 'package:ew_http/ew_http.dart'; import 'package:mobx/mobx.dart'; import 'package:encointer_wallet/models/index.dart'; -import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/config/consts.dart'; import 'package:encointer_wallet/utils/fetch_status.dart'; +import 'package:encointer_wallet/service/log/log_service.dart'; +import 'package:ew_http/ew_http.dart'; +import 'package:ew_keyring/ew_keyring.dart'; part 'transfer_history_view_store.g.dart'; @@ -43,7 +43,7 @@ abstract class _TransferHistoryViewStoreBase with Store { } try { - final address = Fmt.ss58Encode( + final address = AddressUtils.pubKeyHexToAddress( pubKey, prefix: appStore.settings.endpoint.ss58 ?? 42, ); diff --git a/app/lib/modules/transfer/widgets/transaction_card.dart b/app/lib/modules/transfer/widgets/transaction_card.dart index b90b9b4aa..c306d9db6 100644 --- a/app/lib/modules/transfer/widgets/transaction_card.dart +++ b/app/lib/modules/transfer/widgets/transaction_card.dart @@ -11,6 +11,7 @@ import 'package:encointer_wallet/models/index.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/ui.dart'; +import 'package:ew_keyring/ew_keyring.dart'; class TransactionCard extends StatelessWidget { const TransactionCard( @@ -137,7 +138,7 @@ String tryGetPubKey(Transaction transaction) { String counterPartyPubKey; try { - counterPartyPubKey = Fmt.ss58Decode(transaction.counterParty).pubKey; + counterPartyPubKey = AddressUtils.addressToPubKeyHex(transaction.counterParty); } catch (e) { Log.e('Could not decode address. Error: $e'); diff --git a/app/lib/page-encointer/meetup/ceremony_step2_scan2.dart b/app/lib/page-encointer/meetup/ceremony_step2_scan2.dart index df61ad9d9..6b5f35ffc 100644 --- a/app/lib/page-encointer/meetup/ceremony_step2_scan2.dart +++ b/app/lib/page-encointer/meetup/ceremony_step2_scan2.dart @@ -7,7 +7,6 @@ import 'package:provider/provider.dart'; import 'package:encointer_wallet/service/substrate_api/api.dart'; import 'package:encointer_wallet/store/app.dart'; -import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/modules/modules.dart'; import 'package:encointer_wallet/utils/snack_bar.dart'; import 'package:encointer_wallet/l10n/l10.dart'; @@ -19,6 +18,7 @@ import 'package:encointer_wallet/common/components/logo/participant_avatar.dart' import 'package:encointer_wallet/page-encointer/meetup/ceremony_progress_bar.dart'; import 'package:encointer_wallet/page-encointer/meetup/ceremony_step3_finish.dart'; import 'package:encointer_wallet/page-encointer/meetup/scan_claim_qr_code.dart'; +import 'package:ew_keyring/ew_keyring.dart'; class CeremonyStep2Scan extends StatelessWidget { const CeremonyStep2Scan( @@ -136,7 +136,7 @@ class CeremonyStep2Scan extends StatelessWidget { int meetupIndexOfAccount(String accountPubKey) { final participants = store.encointer.communityAccount!.meetup!.registry; - final address = Fmt.ss58Encode(accountPubKey); + final address = AddressUtils.pubKeyHexToAddress(accountPubKey); // the addresses of the meetup are encoded with the default prefix: 42. return participants.indexOf(address); diff --git a/app/lib/page-encointer/meetup/scan_claim_qr_code.dart b/app/lib/page-encointer/meetup/scan_claim_qr_code.dart index e93155f4b..eb68abbcf 100644 --- a/app/lib/page-encointer/meetup/scan_claim_qr_code.dart +++ b/app/lib/page-encointer/meetup/scan_claim_qr_code.dart @@ -2,7 +2,7 @@ import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:mobile_scanner/mobile_scanner.dart' show MobileScanner, MobileScannerController; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; @@ -13,6 +13,7 @@ import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/utils/snack_bar.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart' show AddressUtils, Address; class ScanClaimQrCode extends StatefulWidget { const ScanClaimQrCode(this.confirmedParticipantsCount, {super.key}); @@ -30,15 +31,14 @@ class _ScanClaimQrCodeState extends State { @override void initState() { final store = context.read(); - currentAddressPrefix42 = Fmt.ss58Encode(store.account.currentAccountPubKey!); + currentAddressPrefix42 = AddressUtils.pubKeyHexToAddress(store.account.currentAccountPubKey!); allParticipantsPrefix42 = store.encointer.communityAccount?.meetup?.registry ?? []; super.initState(); } /// Checks that the `attendeeAddress` is not equal to self and part of the meetup registry. void validateAndStoreParticipant(AppStore store, String attendeeAddress, AppLocalizations l10n) { - final attendeePubKey = Fmt.ss58Decode(attendeeAddress).pubKey; - final attendeeAddressPrefix42 = Fmt.ss58Encode(attendeePubKey); + final attendeeAddressPrefix42 = Address.decode(attendeeAddress).encode(prefix: 42); if (attendeeAddressPrefix42 == currentAddressPrefix42) { RootSnackBar.showMsg(l10n.meetupClaimantEqualToSelf); diff --git a/app/lib/page/assets/receive/receive_page.dart b/app/lib/page/assets/receive/receive_page.dart index 188f17636..79df5d5aa 100644 --- a/app/lib/page/assets/receive/receive_page.dart +++ b/app/lib/page/assets/receive/receive_page.dart @@ -1,4 +1,3 @@ -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/material.dart'; import 'package:focus_detector/focus_detector.dart'; import 'package:pausable_timer/pausable_timer.dart'; @@ -10,7 +9,6 @@ import 'package:encointer_wallet/page/assets/qr_code_printing/pages/qr_code_shar import 'package:encointer_wallet/common/components/wake_lock_and_brightness_enhancer.dart'; import 'package:encointer_wallet/theme/theme.dart'; import 'package:encointer_wallet/config/consts.dart'; -import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/page/qr_scan/qr_codes/index.dart'; import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/service/notification/lib/notification.dart'; @@ -19,6 +17,8 @@ import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/snack_bar.dart'; import 'package:encointer_wallet/l10n/l10.dart'; import 'package:encointer_wallet/utils/ui.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class ReceivePage extends StatefulWidget { const ReceivePage({super.key}); @@ -44,7 +44,8 @@ class _ReceivePageState extends State { void initState() { super.initState(); _appStore = context.read(); - final address = Fmt.ss58Encode(_appStore.account.currentAccountPubKey!, prefix: _appStore.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(_appStore.account.currentAccountPubKey!, + prefix: _appStore.settings.endpoint.ss58!); invoice = InvoiceQrCode( account: address, cid: _appStore.encointer.chosenCid, diff --git a/app/lib/page/assets/transfer/payment_confirmation_page/components/payment_overview.dart b/app/lib/page/assets/transfer/payment_confirmation_page/components/payment_overview.dart index 03aa821cf..43e437ea9 100644 --- a/app/lib/page/assets/transfer/payment_confirmation_page/components/payment_overview.dart +++ b/app/lib/page/assets/transfer/payment_confirmation_page/components/payment_overview.dart @@ -6,6 +6,7 @@ import 'package:encointer_wallet/store/account/types/account_data.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/theme/theme.dart'; import 'package:encointer_wallet/utils/format.dart'; +import 'package:ew_keyring/ew_keyring.dart'; class PaymentOverview extends StatelessWidget { const PaymentOverview(this.store, this.communitySymbol, this.recipientAccount, this.amount, {super.key}); @@ -20,7 +21,7 @@ class PaymentOverview extends StatelessWidget { Widget build(BuildContext context) { final recipientLabel = recipientAccount!.name; final recipientAddress = - Fmt.address(Fmt.ss58Encode(recipientAccount!.pubKey, prefix: store.settings.endpoint.ss58!))!; + Fmt.address(AddressUtils.pubKeyHexToAddress(recipientAccount!.pubKey, prefix: store.settings.endpoint.ss58!))!; return IntrinsicHeight( child: Row( diff --git a/app/lib/page/assets/transfer/payment_confirmation_page/index.dart b/app/lib/page/assets/transfer/payment_confirmation_page/index.dart index f08716e94..0124668d5 100644 --- a/app/lib/page/assets/transfer/payment_confirmation_page/index.dart +++ b/app/lib/page/assets/transfer/payment_confirmation_page/index.dart @@ -1,8 +1,5 @@ import 'dart:async'; -import 'package:encointer_wallet/service/tx/lib/src/send_tx_dart.dart'; -import 'package:ew_polkadart/generated/encointer_kusama/types/sp_runtime/dispatch_error.dart'; -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:iconsax/iconsax.dart'; @@ -21,10 +18,14 @@ import 'package:encointer_wallet/page/assets/transfer/payment_confirmation_page/ import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/service/substrate_api/api.dart'; import 'package:encointer_wallet/service/tx/lib/tx.dart'; +import 'package:encointer_wallet/service/tx/lib/src/send_tx_dart.dart'; import 'package:encointer_wallet/store/account/types/account_data.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_polkadart/generated/encointer_kusama/types/sp_runtime/dispatch_error.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class PaymentConfirmationParams { const PaymentConfirmationParams({ @@ -63,7 +64,8 @@ class _PaymentConfirmationPageState extends State { final cid = params.cid; final recipientAccount = params.recipientAccount; final amount = params.amount; - final recipientAddress = Fmt.ss58Encode(recipientAccount.pubKey, prefix: store.settings.endpoint.ss58!); + final recipientAddress = + AddressUtils.pubKeyHexToAddress(recipientAccount.pubKey, prefix: store.settings.endpoint.ss58!); return Scaffold( appBar: AppBar(title: Text(l10n.payment)), diff --git a/app/lib/page/assets/transfer/transfer_page.dart b/app/lib/page/assets/transfer/transfer_page.dart index 24700c6c7..442a8bf0e 100644 --- a/app/lib/page/assets/transfer/transfer_page.dart +++ b/app/lib/page/assets/transfer/transfer_page.dart @@ -1,4 +1,3 @@ -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -24,6 +23,8 @@ import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; import 'package:encointer_wallet/utils/ui.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class TransferPageParams { const TransferPageParams({ @@ -104,7 +105,7 @@ class _TransferPageState extends State { _communitySymbol = params.communitySymbol ?? store.encointer.community?.symbol; _cid = params.cid ?? store.encointer.chosenCid; - final pubKey = Fmt.ss58Decode(params.recipientAddress).pubKey; + final pubKey = AddressUtils.addressToPubKeyHex(params.recipientAddress); _accountTo = AccountData() ..pubKey = pubKey diff --git a/app/lib/page/network_select_page.dart b/app/lib/page/network_select_page.dart index c389abd3a..c95ab2aa5 100644 --- a/app/lib/page/network_select_page.dart +++ b/app/lib/page/network_select_page.dart @@ -15,6 +15,7 @@ import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/store/settings.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart'; class NetworkSelectPage extends StatefulWidget { const NetworkSelectPage({super.key}); @@ -100,7 +101,8 @@ class _NetworkSelectPageState extends State { final accounts = [appStore.account.currentAccount, ...appStore.account.optionalAccounts]; res.addAll(accounts.map((accountData) { - final address = Fmt.ss58Encode(accountData.pubKey, prefix: appStore.settings.endpoint.ss58 ?? 42); + final address = + AddressUtils.pubKeyHexToAddress(accountData.pubKey, prefix: appStore.settings.endpoint.ss58 ?? 42); return Card( shape: RoundedRectangleBorder( diff --git a/app/lib/page/profile/account/account_manage_page.dart b/app/lib/page/profile/account/account_manage_page.dart index 05064f985..f0695179a 100644 --- a/app/lib/page/profile/account/account_manage_page.dart +++ b/app/lib/page/profile/account/account_manage_page.dart @@ -25,6 +25,7 @@ import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/utils/input_validation.dart'; import 'package:encointer_wallet/l10n/l10.dart'; import 'package:encointer_wallet/utils/ui.dart'; +import 'package:ew_keyring/ew_keyring.dart'; import 'package:ew_test_keys/ew_test_keys.dart'; class AccountManagePage extends StatefulWidget { @@ -150,7 +151,8 @@ class _AccountManagePageState extends State { final accountToBeEditedPubKey = ModalRoute.of(context)!.settings.arguments as String?; final accountToBeEdited = store.account.getAccountData(accountToBeEditedPubKey); - final addressSS58 = Fmt.ss58Encode(accountToBeEditedPubKey!, prefix: store.settings.endpoint.ss58!); + final addressSS58 = + AddressUtils.pubKeyHexToAddress(accountToBeEditedPubKey!, prefix: store.settings.endpoint.ss58!); _nameCtrl = TextEditingController(text: accountToBeEdited.name); _nameCtrl!.selection = TextSelection.fromPosition(TextPosition(offset: _nameCtrl!.text.length)); diff --git a/app/lib/page/profile/contacts/account_share_page.dart b/app/lib/page/profile/contacts/account_share_page.dart index 80a7b5a72..761c8d1ec 100644 --- a/app/lib/page/profile/contacts/account_share_page.dart +++ b/app/lib/page/profile/contacts/account_share_page.dart @@ -5,12 +5,12 @@ import 'package:provider/provider.dart'; import 'package:share_plus/share_plus.dart'; import 'package:encointer_wallet/theme/theme.dart'; -import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/config/consts.dart'; import 'package:encointer_wallet/page/qr_scan/qr_codes/index.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/common/components/wake_lock_and_brightness_enhancer.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart'; class AccountSharePage extends StatefulWidget { const AccountSharePage({super.key}); @@ -29,7 +29,8 @@ class _AccountSharePageState extends State { final accountToBeSharedPubKey = ModalRoute.of(context)!.settings.arguments as String?; final accountToBeShared = store.account.getAccountData(accountToBeSharedPubKey); - final addressSS58 = Fmt.ss58Encode(accountToBeSharedPubKey!, prefix: store.settings.endpoint.ss58!); + final addressSS58 = + AddressUtils.pubKeyHexToAddress(accountToBeSharedPubKey!, prefix: store.settings.endpoint.ss58!); final contactQrCode = ContactQrCode( account: addressSS58, diff --git a/app/lib/page/profile/contacts/contact_detail_page.dart b/app/lib/page/profile/contacts/contact_detail_page.dart index 9cc962f5c..7464aa54c 100644 --- a/app/lib/page/profile/contacts/contact_detail_page.dart +++ b/app/lib/page/profile/contacts/contact_detail_page.dart @@ -1,4 +1,3 @@ -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -18,6 +17,8 @@ import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; import 'package:encointer_wallet/utils/ui.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class ContactDetailPage extends StatefulWidget { const ContactDetailPage(this.accountData, {super.key}); @@ -46,7 +47,7 @@ class _ContactDetailPageState extends State { Widget build(BuildContext context) { final l10n = context.l10n; final store = context.watch(); - final address = Fmt.ss58Encode(account.pubKey, prefix: store.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(account.pubKey, prefix: store.settings.endpoint.ss58!); return Scaffold( appBar: AppBar( title: isEditing @@ -277,7 +278,7 @@ class EndorseButton extends StatelessWidget { final community = store.encointer.community; final bootstrappers = community?.bootstrappers; final l10n = context.l10n; - final address = Fmt.ss58Encode(contact.pubKey, prefix: store.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(contact.pubKey, prefix: store.settings.endpoint.ss58!); if (bootstrappers != null && bootstrappers.contains(address)) { await _popupDialog(context, l10n.cantEndorseBootstrapper); diff --git a/app/lib/page/profile/contacts/contact_page.dart b/app/lib/page/profile/contacts/contact_page.dart index 9c3190271..a943afde4 100644 --- a/app/lib/page/profile/contacts/contact_page.dart +++ b/app/lib/page/profile/contacts/contact_page.dart @@ -1,4 +1,3 @@ -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:iconsax/iconsax.dart'; @@ -12,6 +11,8 @@ import 'package:encointer_wallet/service/substrate_api/api.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class ContactPage extends StatefulWidget { const ContactPage({super.key}); @@ -42,7 +43,7 @@ class _Contact extends State { }); final l10n = context.l10n; final addr = _addressCtrl.text.replaceAll(' ', ''); - final pubKey = Fmt.ss58Decode(addr).pubKey; + final pubKey = AddressUtils.addressToPubKeyHex(addr); final con = { 'address': addr, diff --git a/app/lib/page/profile/contacts/contacts_page.dart b/app/lib/page/profile/contacts/contacts_page.dart index 252f46204..fde4a6fae 100644 --- a/app/lib/page/profile/contacts/contacts_page.dart +++ b/app/lib/page/profile/contacts/contacts_page.dart @@ -1,4 +1,3 @@ -import 'package:ew_test_keys/ew_test_keys.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:provider/provider.dart'; @@ -9,6 +8,8 @@ import 'package:encointer_wallet/page/profile/contacts/contact_page.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/l10n/l10.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:ew_test_keys/ew_test_keys.dart'; class ContactsPage extends StatelessWidget { const ContactsPage({super.key}); @@ -38,7 +39,7 @@ class ContactsPage extends StatelessWidget { itemCount: appStore.settings.contactList.length, itemBuilder: (BuildContext context, int index) { final contact = appStore.settings.contactList[index]; - final address = Fmt.ss58Encode(contact.pubKey, prefix: appStore.settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(contact.pubKey, prefix: appStore.settings.endpoint.ss58!); return ListTile( key: Key(contact.name), leading: AddressIcon(address, contact.pubKey, size: 45), diff --git a/app/lib/page/qr_scan/qr_scan_service.dart b/app/lib/page/qr_scan/qr_scan_service.dart index 8e6fc6b1b..c2aa94acd 100644 --- a/app/lib/page/qr_scan/qr_scan_service.dart +++ b/app/lib/page/qr_scan/qr_scan_service.dart @@ -8,7 +8,7 @@ import 'package:encointer_wallet/page/qr_scan/qr_codes/index.dart'; import 'package:encointer_wallet/page/reap_voucher/reap_voucher_page.dart'; import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/store/app.dart'; -import 'package:encointer_wallet/utils/format.dart'; +import 'package:ew_keyring/ew_keyring.dart'; enum QrScannerContext { /// QrScanner was opened from the main page @@ -92,7 +92,7 @@ Future handleInvoiceQrCodeScan(BuildContext context, QrScannerContext scan 'name': qrCode.data.label, 'memo': '', 'observation': false, - 'pubKey': Fmt.ss58Decode(qrCode.data.account).pubKey + 'pubKey': AddressUtils.addressToPubKeyHex(qrCode.data.account) }; await context.read().settings.addContact(contactData); } diff --git a/app/lib/service/substrate_api/encointer/encointer_api.dart b/app/lib/service/substrate_api/encointer/encointer_api.dart index 0564cbaeb..195eb218f 100644 --- a/app/lib/service/substrate_api/encointer/encointer_api.dart +++ b/app/lib/service/substrate_api/encointer/encointer_api.dart @@ -1,11 +1,5 @@ import 'dart:convert'; -import 'package:encointer_wallet/models/bazaar/businesses.dart'; -import 'package:encointer_wallet/models/bazaar/ipfs_product.dart'; -import 'package:encointer_wallet/models/bazaar/item_offered.dart'; -import 'package:encointer_wallet/models/faucet/faucet.dart'; -import 'package:ew_http/ew_http.dart'; - import 'package:encointer_wallet/config/consts.dart'; import 'package:encointer_wallet/mocks/mock_bazaar_data.dart'; import 'package:encointer_wallet/models/bazaar/account_business_tuple.dart'; @@ -16,6 +10,10 @@ import 'package:encointer_wallet/models/communities/community_metadata.dart'; import 'package:encointer_wallet/models/encointer_balance_data/balance_entry.dart'; import 'package:encointer_wallet/models/index.dart'; import 'package:encointer_wallet/models/proof_of_attendance/proof_of_attendance.dart'; +import 'package:encointer_wallet/models/bazaar/businesses.dart'; +import 'package:encointer_wallet/models/bazaar/ipfs_product.dart'; +import 'package:encointer_wallet/models/bazaar/item_offered.dart'; +import 'package:encointer_wallet/models/faucet/faucet.dart'; import 'package:encointer_wallet/service/encointer_feed/feed.dart' as feed; import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/service/substrate_api/core/dart_api.dart'; @@ -24,7 +22,8 @@ import 'package:encointer_wallet/service/substrate_api/encointer/encointer_dart_ import 'package:encointer_wallet/service/substrate_api/encointer/no_tee_api.dart'; import 'package:encointer_wallet/service/substrate_api/encointer/tee_proxy_api.dart'; import 'package:encointer_wallet/store/app.dart'; -import 'package:encointer_wallet/utils/format.dart'; +import 'package:ew_http/ew_http.dart'; +import 'package:ew_keyring/ew_keyring.dart'; import 'package:ew_polkadart/ew_polkadart.dart'; import 'package:ew_substrate_fixed/substrate_fixed.dart'; @@ -153,7 +152,7 @@ class EncointerApi { /// Todo: Be able to handle pubKey and any address and transform it to the /// address with prefix 42. Needs #1105. Future getAggregatedAccountData(CommunityIdentifier cid, String pubKey) async { - final address = Fmt.ss58Encode(pubKey); + final address = AddressUtils.pubKeyHexToAddress(pubKey); try { final accountData = await _dartApi.getAggregatedAccountData(cid, address); diff --git a/app/lib/store/account/account.dart b/app/lib/store/account/account.dart index cccaa299c..85781b5f0 100644 --- a/app/lib/store/account/account.dart +++ b/app/lib/store/account/account.dart @@ -10,6 +10,7 @@ import 'package:encointer_wallet/store/account/types/account_data.dart'; import 'package:encointer_wallet/store/account/types/tx_status.dart'; import 'package:encointer_wallet/store/app.dart'; import 'package:encointer_wallet/utils/format.dart'; +import 'package:ew_keyring/ew_keyring.dart'; part 'account.g.dart'; @@ -95,7 +96,7 @@ abstract class _AccountStore with Store { String get currentAddress { // Todo #1110: `currentAccountPubkey` should be non-nullable. if (currentAccountPubKey == null || currentAccountPubKey!.isEmpty) return ''; - return Fmt.ss58Encode(currentAccountPubKey ?? '', prefix: rootStore.settings.endpoint.ss58!); + return AddressUtils.pubKeyHexToAddress(currentAccountPubKey ?? '', prefix: rootStore.settings.endpoint.ss58!); } @action diff --git a/app/lib/store/app.dart b/app/lib/store/app.dart index 085f83529..333b7d51f 100644 --- a/app/lib/store/app.dart +++ b/app/lib/store/app.dart @@ -4,12 +4,12 @@ import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/service/substrate_api/api.dart'; import 'package:encointer_wallet/store/account/account.dart'; import 'package:encointer_wallet/store/assets/assets.dart'; -import 'package:encointer_wallet/utils/format.dart'; import 'package:encointer_wallet/store/chain/chain.dart'; import 'package:encointer_wallet/store/data_update/data_update.dart'; import 'package:encointer_wallet/store/encointer/encointer.dart'; import 'package:encointer_wallet/store/settings.dart'; import 'package:encointer_wallet/utils/local_storage.dart'; +import 'package:ew_keyring/ew_keyring.dart'; part 'app.g.dart'; @@ -223,7 +223,7 @@ abstract class _AppStore with Store { if (pubKey != null) { // Todo: #1072 - final address = Fmt.ss58Encode(pubKey, prefix: settings.endpoint.ss58!); + final address = AddressUtils.pubKeyHexToAddress(pubKey, prefix: settings.endpoint.ss58!); Log.d('setCurrentAccount: new current account address: $address', '_AppStore'); await encointer.initializeUninitializedStores(address); } diff --git a/app/lib/utils/format.dart b/app/lib/utils/format.dart index 8d5c3c166..2cb29a985 100644 --- a/app/lib/utils/format.dart +++ b/app/lib/utils/format.dart @@ -2,17 +2,13 @@ import 'dart:convert'; import 'dart:core'; import 'dart:math'; -import 'package:base58check/base58.dart'; -import 'package:base58check/base58check.dart'; import 'package:convert/convert.dart'; import 'package:flutter/cupertino.dart'; -import 'package:flutter/foundation.dart'; import 'package:intl/intl.dart'; import 'package:encointer_wallet/service/log/log_service.dart'; import 'package:encointer_wallet/store/account/types/account_data.dart'; import 'package:encointer_wallet/l10n/l10.dart'; -import 'package:pointycastle/digests/blake2b.dart'; class Fmt { static String passwordToEncryptKey(String password) { @@ -256,84 +252,4 @@ class Fmt { static String degree(String degree, {int fixedPointFraction = 64, int fractionDisplay = 3}) { return (double.tryParse(degree) ?? 0.0).toStringAsFixed(fractionDisplay); } - - static const base58Codec = Base58Codec(Base58CheckCodec.BITCOIN_ALPHABET); - - /// Convert a pubKey into an SS58-address. - /// - /// Based on the rust version: https://github.com/paritytech/substrate/blob/48e7cb147cb9a27125fd2e82edbcf4d0ed5927c4/primitives/core/src/crypto.rs#L324 - /// - /// Note: This only supports prefixes < 64, bigger prefixes require - /// special handling. - static String ss58Encode(String pubKey, {int prefix = 42}) { - if (prefix >= 64) throw Exception('prefixes >= 64 are currently not supported'); - - final body = Uint8List.fromList([prefix, ...Fmt.hexToBytes(pubKey)]); - final hash = blake2WithSs58Pre(body); - - final complete = List.from([...body, hash[0], hash[1]]); - return base58Codec.encode(complete); - } - - /// General pubKey length used in substrate and Encointer. - static const pubKeyLen = 32; - - /// Length of the checksum in an SS58-address. - static const checkSumLen = 2; - - /// If the SS58-address has a prefix < 64 the prefix length is 1 else it is 2. - /// - /// All Encointer networks use the prefix 2 or 42, so we can only implement a subset of the - /// SS58-codec. - static const prefixLenForPrefixesSmallerThan64 = 1; - - /// Convert an SS58-address into a pubKey. - /// - /// Based on the rust version: https://github.com/paritytech/substrate/blob/48e7cb147cb9a27125fd2e82edbcf4d0ed5927c4/primitives/core/src/crypto.rs#L269 - /// - /// Note: This only supports prefixes < 64, bigger prefixes require - /// special handling. - static Ss58DecodeResult ss58Decode(String address) { - const prefixLen = prefixLenForPrefixesSmallerThan64; - - final data = base58Codec.decode(address); - final prefix = data[0]; - - if (prefix >= 64) throw Exception('prefixes >= 64 are currently not supported'); - if (data.length != prefixLen + pubKeyLen + checkSumLen) throw Exception('Bad address length ${data.length}'); - - final hash = blake2WithSs58Pre(Uint8List.fromList(data.sublist(0, pubKeyLen + prefixLen))); - final checksum = hash.sublist(0, checkSumLen); - final checksumData = data.sublist(pubKeyLen + prefixLen, pubKeyLen + prefixLen + checkSumLen); - if (!listEquals(checksumData, checksum)) throw Exception('Invalid checksum: $checksumData != $checksum'); - - return Ss58DecodeResult(bytesToHex(data.sublist(prefixLen, prefixLen + pubKeyLen)), prefix); - } - - static final ss58Prefix = 'SS58PRE'.codeUnits; - - /// Corresponds to the `ss58hash`: https://github.com/paritytech/substrate/blob/48e7cb147cb9a27125fd2e82edbcf4d0ed5927c4/primitives/core/src/crypto.rs#L374 - static Uint8List blake2WithSs58Pre(Uint8List data) { - final ss58Pre = Uint8List.fromList(ss58Prefix); - - final blake2 = Blake2bDigest() - ..init() - ..update(ss58Pre, 0, ss58Pre.length) - ..update(data, 0, data.length); - - final hash = Uint8List(blake2.digestSize); - blake2.doFinal(hash, 0); - - return hash; - } -} - -class Ss58DecodeResult { - const Ss58DecodeResult(this.pubKey, this.prefix); - - /// The pubKey corresponding to the input address. - final String pubKey; - - /// The prefix of the input address. - final int prefix; } diff --git a/app/pubspec.lock b/app/pubspec.lock index d4ab2a358..5f3b13eac 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" + url: "https://pub.dev" + source: hosted + version: "1.0.0" add_2_calendar: dependency: "direct main" description: @@ -89,6 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + base_x: + dependency: transitive + description: + name: base_x + sha256: "519abcdafd637d4b6bd7e72fabd8f9264935f804b9b9f6c5d8411c7d52cbf8fd" + url: "https://pub.dev" + source: hosted + version: "2.0.1" bidi: dependency: transitive description: @@ -97,14 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.6" - bip39: - dependency: "direct main" + bip39_mnemonic: + dependency: transitive description: - name: bip39 - sha256: de1ee27ebe7d96b84bb3a04a4132a0a3007dcdd5ad27dd14aa87a29d97c45edc + name: bip39_mnemonic + sha256: "24855a62fb9dd930f697063a274e084b0a574e1cc55ec270ca4756f579ab512c" url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "3.0.6" boolean_selector: dependency: transitive description: @@ -273,6 +289,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + cryptography: + dependency: transitive + description: + name: cryptography + sha256: "5a31bbabc6d7e15cf5d823d99ee20074bd502f2376cc49eec73bf34c9a4f7f89" + url: "https://pub.dev" + source: hosted + version: "2.6.1" csslib: dependency: transitive description: @@ -361,6 +385,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.6" + ed25519_edwards: + dependency: transitive + description: + name: ed25519_edwards + sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" + url: "https://pub.dev" + source: hosted + version: "0.3.1" equatable: dependency: transitive description: @@ -376,6 +408,13 @@ packages: relative: true source: path version: "0.1.0+1" + ew_keyring: + dependency: "direct main" + description: + path: "../packages/ew_keyring" + relative: true + source: path + version: "0.1.0+1" ew_polkadart: dependency: "direct main" description: @@ -473,6 +512,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_curve25519: + dependency: transitive + description: + name: flutter_curve25519 + sha256: d2d196e51de878f5f0289d2d7c5e93dc0c62ccda7ca98c7e47b5a58a6851b861 + url: "https://pub.dev" + source: hosted + version: "0.1.2" flutter_driver: dependency: "direct dev" description: flutter @@ -682,14 +729,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" - hex: - dependency: transitive - description: - name: hex - sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" - url: "https://pub.dev" - source: hosted - version: "0.2.0" html: dependency: transitive description: @@ -1243,7 +1282,7 @@ packages: source: hosted version: "2.1.4" pointycastle: - dependency: "direct main" + dependency: transitive description: name: pointycastle sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" @@ -1259,6 +1298,14 @@ packages: url: "https://github.com/encointer/polkadart" source: git version: "0.2.2" + polkadart_keyring: + dependency: transitive + description: + name: polkadart_keyring + sha256: ba568c22f3ff2a77c35fe0d53845212c1a433f99645e286550d1889dbb437d3c + url: "https://pub.dev" + source: hosted + version: "0.2.1" polkadart_scale_codec: dependency: transitive description: @@ -1584,6 +1631,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + ss58: + dependency: transitive + description: + name: ss58 + sha256: b24d2713597b83708ef30daea5a565dba8bc9129031b30c025069e168301ae5e + url: "https://pub.dev" + source: hosted + version: "1.1.2" stack_trace: dependency: transitive description: @@ -1616,6 +1671,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + substrate_bip39: + dependency: transitive + description: + name: substrate_bip39 + sha256: "78b45e9959c3394ecc9b56d9bfb07e11f93db70d273eccd93e3e4d84b28f11c0" + url: "https://pub.dev" + source: hosted + version: "0.2.0" substrate_metadata: dependency: transitive description: @@ -1704,6 +1767,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.1" + unorm_dart: + dependency: transitive + description: + name: unorm_dart + sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b" + url: "https://pub.dev" + source: hosted + version: "0.2.0" upgrader: dependency: "direct main" description: @@ -1977,5 +2048,5 @@ packages: source: hosted version: "1.1.2+6" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.1.0 <4.0.0" flutter: ">=3.13.8" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index abc2890ab..ed216e66b 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -26,8 +26,6 @@ dependencies: # intl - format numbers intl: ^0.18.1 json_annotation: ^4.8.1 - bip39: ^1.0.6 # Todo: #1268: replace with alternative package - pointycastle: ^3.7.3 # state management with mobx mobx: ^2.2.1 flutter_mobx: ^2.1.0+1 @@ -82,6 +80,8 @@ dependencies: path: ../packages/ew_storage/ ew_http: path: ../packages/ew_http/ + ew_keyring: + path: ../packages/ew_keyring/ ew_polkadart: path: ../packages/ew_polkadart/ ew_substrate_fixed: diff --git a/app/pubspec_overrides.yaml b/app/pubspec_overrides.yaml index 3b9390a57..a05738e8b 100644 --- a/app/pubspec_overrides.yaml +++ b/app/pubspec_overrides.yaml @@ -1,7 +1,9 @@ -# melos_managed_dependency_overrides: ew_http,ew_storage,ew_polkadart,ew_substrate_fixed +# melos_managed_dependency_overrides: ew_http,ew_storage,ew_polkadart,ew_substrate_fixed,ew_keyring dependency_overrides: ew_http: path: ../packages/ew_http + ew_keyring: + path: ../packages/ew_keyring ew_polkadart: path: ../packages/ew_polkadart ew_storage: diff --git a/app/test/utils/format_test.dart b/app/test/utils/format_test.dart deleted file mode 100644 index 344d8c916..000000000 --- a/app/test/utils/format_test.dart +++ /dev/null @@ -1,164 +0,0 @@ -import 'dart:typed_data'; - -import 'package:encointer_wallet/utils/format.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('SS58', () { - // Alice pubKey, double check with `subkey inspect //Alice` - const alice = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; - - group('Encode', () { - test('ss58Encode works for prefix 2', () { - // Prefix of the encointer kusama-parachain (production) and rococo-parachain (testnet). - // Reproduce with `subkey inspect //Alice -n kusama` - expect(Fmt.ss58Encode(alice, prefix: 2), 'HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); - }); - - test('ss58Encode works for prefix 42', () { - // Prefix of the other encointer testnets. - // Reproduce with `subkey inspect //Alice` - expect(Fmt.ss58Encode(alice), '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); - }); - - test('ss58Encode fails for prefix >= 64', () { - try { - Fmt.ss58Encode(alice, prefix: 64); - } catch (e) { - expect(e.toString(), 'Exception: prefixes >= 64 are currently not supported'); - } - }); - }); - - group('Decode', () { - test('ss58Decode works for prefix 2', () { - final result = Fmt.ss58Decode('HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); - expect(result.prefix, 2); - expect(result.pubKey, alice); - }); - - test('ss58Decode works for prefix 42', () { - final result = Fmt.ss58Decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); - expect(result.prefix, 42); - expect(result.pubKey, alice); - }); - - test('ss58Decode fails for wrong checksum', () { - try { - // Replaced last letter: Y -> Q - Fmt.ss58Decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQQ'); - } catch (e) { - expect(e.toString(), 'Exception: Invalid checksum: [29, 25] != [29, 33]'); - } - }); - - test('ss58Decode fails for prefix too big', () { - try { - // Removed last letter. I don't really know how to trigger specific prefixes. - Fmt.ss58Decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQ'); - } catch (e) { - expect(e.toString(), 'Exception: prefixes >= 64 are currently not supported'); - } - }); - - // I could not find out how to trigger wrong length yet... - }); - - test('blake2bWithSs58Pre works', () { - final hello = Uint8List.fromList('hello'.codeUnits); - final hash = Fmt.blake2WithSs58Pre(hello); - expect(hash, rustHelloHashWithPrefix); - }); - - test('SS58PRE matches rust value', () { - expect( - Fmt.ss58Prefix, - // Corresponds to rust's: `const PREFIX: &[u8] = b"SS58PRE";` - List.from([83, 83, 53, 56, 80, 82, 69]), - ); - }); - }); -} - -/// This is the value obtained by the following rust function: -/// -/// ```rust -/// const PREFIX: &[u8] = b"SS58PRE"; -/// -/// fn blake2b(data: &[u8]) -> Vec { -/// use blake2::{Blake2b512, Digest}; -/// -/// let mut ctx = Blake2b512::new(); -/// ctx.update(PREFIX); -/// ctx.update(data); -/// ctx.finalize().to_vec() -/// } -/// -/// blake2b(b"hello") -/// ``` -final rustHelloHashWithPrefix = List.from([ - 88, - 202, - 6, - 102, - 51, - 141, - 3, - 199, - 32, - 83, - 28, - 81, - 100, - 25, - 199, - 244, - 15, - 229, - 18, - 218, - 73, - 28, - 53, - 88, - 44, - 37, - 167, - 97, - 168, - 74, - 163, - 176, - 12, - 174, - 194, - 191, - 48, - 186, - 230, - 104, - 194, - 149, - 101, - 217, - 8, - 150, - 232, - 70, - 164, - 72, - 101, - 229, - 6, - 87, - 151, - 185, - 173, - 118, - 38, - 146, - 30, - 102, - 65, - 187 -]); diff --git a/packages/ew_keyring/README.md b/packages/ew_keyring/README.md new file mode 100644 index 000000000..d010a56dc --- /dev/null +++ b/packages/ew_keyring/README.md @@ -0,0 +1,3 @@ +# EW Encointer Keyring + +Encointer Keyring Package diff --git a/packages/ew_keyring/analysis_options.yaml b/packages/ew_keyring/analysis_options.yaml new file mode 100644 index 000000000..3ff4f2b81 --- /dev/null +++ b/packages/ew_keyring/analysis_options.yaml @@ -0,0 +1,7 @@ +include: package:very_good_analysis/analysis_options.3.1.0.yaml + +linter: + rules: + public_member_api_docs: false + lines_longer_than_80_chars: false + sort_pub_dependencies: false \ No newline at end of file diff --git a/packages/ew_keyring/lib/ew_keyring.dart b/packages/ew_keyring/lib/ew_keyring.dart new file mode 100644 index 000000000..502a4d186 --- /dev/null +++ b/packages/ew_keyring/lib/ew_keyring.dart @@ -0,0 +1,7 @@ +/// Manages the cryptographic keys on the end device +library ew_keyring; + +// Don't export keyring as it doesn't support sr25519 yet. +// export 'src/keyring.dart'; +export 'src/address_utils.dart' show Address, AddressUtils, AddressExtension; +export 'src/validate_keys.dart' show ValidateKeys; diff --git a/packages/ew_keyring/lib/src/address_utils.dart b/packages/ew_keyring/lib/src/address_utils.dart new file mode 100644 index 000000000..300fd734c --- /dev/null +++ b/packages/ew_keyring/lib/src/address_utils.dart @@ -0,0 +1,38 @@ +import 'dart:typed_data'; + +import 'package:convert/convert.dart' show hex; +import 'package:ss58/ss58.dart' show Address; + +export 'package:ss58/ss58.dart' show Address; + +extension AddressExtension on Address { + String toPubHex() { + return '0x${hex.encode(pubkey)}'; + } +} + +abstract class AddressUtils { + /// Encode a public key to an SS58 address. + /// + /// The default SS58 address prefix is 42. + static String pubKeyToAddress(List pubKey, {int prefix = 42}) { + return Address(prefix: prefix, pubkey: Uint8List.fromList(pubKey)).encode(); + } + + /// Encode a public key to an SS58 address. + /// + /// The default SS58 address prefix is 42. + static String pubKeyHexToAddress(String pubKey, {int prefix = 42}) { + final pub = hex.decode(pubKey.replaceFirst('0x', '')); + return Address(prefix: prefix, pubkey: Uint8List.fromList(pub)).encode(); + } + + /// Decode an SS58 address to its public key. + static Uint8List addressToPubKey(String address) { + return Address.decode(address).pubkey; + } + + static String addressToPubKeyHex(String address) { + return Address.decode(address).toPubHex(); + } +} diff --git a/packages/ew_keyring/lib/src/keyring.dart b/packages/ew_keyring/lib/src/keyring.dart new file mode 100644 index 000000000..8ae028e81 --- /dev/null +++ b/packages/ew_keyring/lib/src/keyring.dart @@ -0,0 +1,64 @@ +import 'package:ew_keyring/src/keyring_data.dart'; +import 'package:polkadart_keyring/polkadart_keyring.dart'; + +/// The public key (as a list of integers). +typedef Pubkey = String; + +/// Keyring that is stored on the devices encrypted storage. +/// +/// Note: This can't yet be used by encointer. It uses ed25519, +/// which is unfortunately not compatible with encointer. We have +/// to wait for sr25519 support from polkadart. +class EncointerKeyring { + EncointerKeyring() + : keyring = Keyring(), + accounts = {}; + + static Future fromAccounts(List accounts) async { + final k = EncointerKeyring(); + await k.addAccounts(accounts); + return k; + } + + final Keyring keyring; + final Map accounts; + + Future addAccounts(List keyringAccounts) async { + await Future.wait(keyringAccounts.map(addAccount)); + } + + Future addAccount(KeyringAccount keyringAccount) async { + final pair = await KeyPair.fromMnemonic(keyringAccount.seed); + keyring.add(pair); + // same as what keyring does internally. + accounts[_publicKey(pair).toString()] = keyringAccount; + } + + KeyPair getPairByPublicKey(List publicKey) { + return keyring.getByPublicKey(publicKey); + } + + KeyringAccount getAccountByPublicKey(List publicKey) { + if (accounts[publicKey.toString()] == null) { + throw ArgumentError('KeyPair with provided key, not found.'); + } + return accounts[publicKey.toString()]!; + } + + void remove(List publicKey) { + keyring.pairs.removeByPublicKey(publicKey); + accounts.remove(publicKey.toString()); + } + + /// Remove all key pairs from the keyring. + void clear() { + keyring.clear(); + accounts.clear(); + } + + /// Get a List as string, this is the same as the keyring internally uses + /// to add a pair. + List _publicKey(KeyPair pair) { + return keyring.decodeAddress(pair.address); + } +} diff --git a/packages/ew_keyring/lib/src/keyring_data.dart b/packages/ew_keyring/lib/src/keyring_data.dart new file mode 100644 index 000000000..b654d0913 --- /dev/null +++ b/packages/ew_keyring/lib/src/keyring_data.dart @@ -0,0 +1,34 @@ +import 'package:ew_keyring/src/validate_keys.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'keyring_data.g.dart'; + +@JsonSerializable() +class KeyringAccount { + KeyringAccount(this.name, this.seed) : type = getSeedTypeFromString(seed); + + final String name; + final SeedType type; + final String seed; + + static KeyringAccount fromJson(Map json) => _$KeyringAccountFromJson(json); + static Map toJson(KeyringAccount acc) => _$KeyringAccountToJson(acc); +} + +SeedType getSeedTypeFromString(String seed) { + if (ValidateKeys.isRawSeed(seed)) { + return SeedType.raw; + } else if (ValidateKeys.isPrivateKey(seed)) { + return SeedType.privateKey; + } else if (ValidateKeys.validateMnemonic(seed)) { + return SeedType.mnemonic; + } else { + throw Exception('invalid seed: $seed'); + } +} + +enum SeedType { + raw, + privateKey, + mnemonic, +} diff --git a/packages/ew_keyring/lib/src/keyring_data.g.dart b/packages/ew_keyring/lib/src/keyring_data.g.dart new file mode 100644 index 000000000..4a0542e84 --- /dev/null +++ b/packages/ew_keyring/lib/src/keyring_data.g.dart @@ -0,0 +1,17 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'keyring_data.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +KeyringAccount _$KeyringAccountFromJson(Map json) => KeyringAccount( + json['name'] as String, + json['seed'] as String, + ); + +Map _$KeyringAccountToJson(KeyringAccount instance) => { + 'name': instance.name, + 'seed': instance.seed, + }; diff --git a/app/lib/utils/validate_keys.dart b/packages/ew_keyring/lib/src/validate_keys.dart similarity index 81% rename from app/lib/utils/validate_keys.dart rename to packages/ew_keyring/lib/src/validate_keys.dart index ff25e588c..f7187095b 100644 --- a/app/lib/utils/validate_keys.dart +++ b/packages/ew_keyring/lib/src/validate_keys.dart @@ -1,4 +1,4 @@ -import 'package:bip39/bip39.dart' as bip39; +import 'package:substrate_bip39/substrate_bip39.dart'; class ValidateKeys { static bool isPrivateKey(String privateKey) { @@ -34,6 +34,16 @@ class ValidateKeys { static bool validateMnemonic(String mnemonic) { final input = mnemonic.trim(); final len = input.split(' ').length; - return (len == 12 || len == 24) && bip39.validateMnemonic(input); + + if (!(len == 12 || len == 24)) { + return false; + } + + try { + Mnemonic.fromSentence(input, Language.english); + return true; + } catch (_) { + return false; + } } } diff --git a/packages/ew_keyring/pubspec.lock b/packages/ew_keyring/pubspec.lock new file mode 100644 index 000000000..e64796378 --- /dev/null +++ b/packages/ew_keyring/pubspec.lock @@ -0,0 +1,645 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" + source: hosted + version: "61.0.0" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" + source: hosted + version: "5.13.0" + args: + dependency: transitive + description: + name: args + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + async: + dependency: transitive + description: + name: async + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" + source: hosted + version: "2.10.0" + base_x: + dependency: transitive + description: + name: base_x + sha256: "519abcdafd637d4b6bd7e72fabd8f9264935f804b9b9f6c5d8411c7d52cbf8fd" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + bip39_mnemonic: + dependency: transitive + description: + name: bip39_mnemonic + sha256: "24855a62fb9dd930f697063a274e084b0a574e1cc55ec270ca4756f579ab512c" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" + url: "https://pub.dev" + source: hosted + version: "2.4.6" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "30859c90e9ddaccc484f56303931f477b1f1ba2bab74aa32ed5d6ce15870f8cf" + url: "https://pub.dev" + source: hosted + version: "7.2.8" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e" + url: "https://pub.dev" + source: hosted + version: "8.7.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" + url: "https://pub.dev" + source: hosted + version: "4.7.0" + collection: + dependency: transitive + description: + name: collection + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + convert: + dependency: "direct main" + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + url: "https://pub.dev" + source: hosted + version: "1.6.3" + crypto: + dependency: transitive + description: + name: crypto + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + cryptography: + dependency: transitive + description: + name: cryptography + sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35 + url: "https://pub.dev" + source: hosted + version: "2.5.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + ed25519_edwards: + dependency: transitive + description: + name: ed25519_edwards + sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter_curve25519: + dependency: transitive + description: + name: flutter_curve25519 + sha256: d2d196e51de878f5f0289d2d7c5e93dc0c62ccda7ca98c7e47b5a58a6851b861 + url: "https://pub.dev" + source: hosted + version: "0.1.2" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" + logging: + dependency: transitive + description: + name: logging + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + polkadart_keyring: + dependency: "direct main" + description: + name: polkadart_keyring + sha256: ba568c22f3ff2a77c35fe0d53845212c1a433f99645e286550d1889dbb437d3c + url: "https://pub.dev" + source: hosted + version: "0.2.1" + polkadart_scale_codec: + dependency: transitive + description: + name: polkadart_scale_codec + sha256: "75289b2f53c6cf997dd68945d959fee596c1e47bba3dedba22a6e95646df893c" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" + source: hosted + version: "1.4.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c + url: "https://pub.dev" + source: hosted + version: "1.1.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "490098075234dcedb83c5d949b4c93dad5e6b7702748de000be2b57b8e6b2427" + url: "https://pub.dev" + source: hosted + version: "0.10.11" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + ss58: + dependency: "direct main" + description: + name: ss58 + sha256: b24d2713597b83708ef30daea5a565dba8bc9129031b30c025069e168301ae5e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + substrate_bip39: + dependency: "direct main" + description: + name: substrate_bip39 + sha256: "78b45e9959c3394ecc9b56d9bfb07e11f93db70d273eccd93e3e4d84b28f11c0" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + url: "https://pub.dev" + source: hosted + version: "1.24.3" + test_api: + dependency: transitive + description: + name: test_api + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + test_core: + dependency: transitive + description: + name: test_core + sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + url: "https://pub.dev" + source: hosted + version: "0.5.3" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + unorm_dart: + dependency: transitive + description: + name: unorm_dart + sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + very_good_analysis: + dependency: "direct dev" + description: + name: very_good_analysis + sha256: "5e4ea72d2a9188630f0dd8f120a541de730090ef8863243fedca8267a84508b8" + url: "https://pub.dev" + source: hosted + version: "5.0.0+1" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7 + url: "https://pub.dev" + source: hosted + version: "9.4.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" + source: hosted + version: "2.3.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" + source: hosted + version: "3.1.1" +sdks: + dart: ">=3.0.1 <4.0.0" diff --git a/packages/ew_keyring/pubspec.yaml b/packages/ew_keyring/pubspec.yaml new file mode 100644 index 000000000..b64c894ea --- /dev/null +++ b/packages/ew_keyring/pubspec.yaml @@ -0,0 +1,21 @@ +name: ew_keyring +description: Encointer Utils Package +version: 0.1.0+1 +publish_to: none + +environment: + sdk: ">=3.0.1 <4.0.0" + +dependencies: + convert: ^3.1.1 + json_annotation: ^4.8.1 + polkadart_keyring: 0.2.1 + ss58: ^1.1.2 + substrate_bip39: ^0.2.0 + +dev_dependencies: + test: 1.24.3 + very_good_analysis: ^5.0.0+1 + build_runner: ^2.4.6 + json_serializable: ^6.7.1 + diff --git a/packages/ew_keyring/test/address_utils_test.dart b/packages/ew_keyring/test/address_utils_test.dart new file mode 100644 index 000000000..856af493f --- /dev/null +++ b/packages/ew_keyring/test/address_utils_test.dart @@ -0,0 +1,66 @@ +import 'package:ew_keyring/ew_keyring.dart' show Address, AddressUtils, AddressExtension; +import 'package:test/test.dart'; + +void main() { + group('AddressExtension', () { + test('toPubHex works', () { + final alice = Address.decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + expect(alice.toPubHex(), '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'); + }); + }); + + group('AddressUtils', () { + test('addressToPubKey with default prefix works works', () { + final alice = Address.decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + final pubAlice = AddressUtils.addressToPubKey('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + + expect(alice.pubkey, pubAlice); + expect(alice.toPubHex(), '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'); + }); + + test('addressToPubKey with prefix 2 works works', () { + final alice = Address.decode('HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); + final pubAlice = AddressUtils.addressToPubKey('HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); + + expect(alice.pubkey, pubAlice); + expect(alice.toPubHex(), '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'); + }); + + test('addressToPubKeyHex with default prefix works works', () { + final pubAlice = AddressUtils.addressToPubKeyHex('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + expect(pubAlice, '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'); + }); + + test('addressToPubKeyHex with prefix 2 works works', () { + final pubAlice = AddressUtils.addressToPubKeyHex('HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); + expect(pubAlice, '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'); + }); + + test('pubKeyToAddress with default prefix works', () { + final alice = Address.decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + + final aliceAddress = AddressUtils.pubKeyToAddress(alice.pubkey); + expect(aliceAddress, '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + }); + + test('pubKeyToAddress with prefix 2 works', () { + final alice = Address.decode('HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); + + final aliceAddress = AddressUtils.pubKeyToAddress(alice.pubkey, prefix: 2); + expect(aliceAddress, 'HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); + }); + + test('pubKeyHexToAddress with default prefix works', () { + final aliceAddress = + AddressUtils.pubKeyHexToAddress('0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'); + expect(aliceAddress, '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + }); + + test('pubKeyHexToAddress with prefix 2 works', () { + final aliceAddress = AddressUtils.pubKeyHexToAddress( + '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', + prefix: 2); + expect(aliceAddress, 'HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F'); + }); + }); +} diff --git a/packages/ew_keyring/test/keyring_data_test.dart b/packages/ew_keyring/test/keyring_data_test.dart new file mode 100644 index 000000000..602f42ad0 --- /dev/null +++ b/packages/ew_keyring/test/keyring_data_test.dart @@ -0,0 +1,15 @@ +import 'package:ew_keyring/src/keyring_data.dart'; +import 'package:test/test.dart'; + +void main() { + group('getSeedTypeFromString', () { + test('inferring key type works', () { + expect(getSeedTypeFromString('0xabe03'), SeedType.privateKey); + expect(getSeedTypeFromString('//Alice'), SeedType.raw); + expect( + getSeedTypeFromString('spray trust gown toast route merge awful sight ghost all degree exit'), + SeedType.mnemonic, + ); + }); + }); +} diff --git a/packages/ew_keyring/test/keyring_test.dart b/packages/ew_keyring/test/keyring_test.dart new file mode 100644 index 000000000..1b486fb15 --- /dev/null +++ b/packages/ew_keyring/test/keyring_test.dart @@ -0,0 +1,37 @@ +@Skip('These tests fail until we have sr25519 support') + +import 'package:ew_keyring/src/keyring.dart'; +import 'package:ew_keyring/src/keyring_data.dart'; +import 'package:polkadart_keyring/polkadart_keyring.dart'; +import 'package:test/test.dart'; + +void main() { + group('Well known accounts', () { + test('inferring key type works', () async { + final alice = KeyringAccount('Alice', '//Alice'); + final bob = KeyringAccount('Bob', '//Bob'); + final charlie = KeyringAccount('Charlie', '//Charlie'); + final accounts = [alice, bob, charlie]; + final keyring = await EncointerKeyring.fromAccounts(accounts); + + // print("keyring: ${keyring.accounts.toString()}"); + // print("keyring: ${keyring.keyring.toString()}"); + + final alicePair = keyring.keyring.getByAddress('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + // final alicePair = keyring.getPairByPublicKey('d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'.codeUnits); + final aliceAccount = + keyring.getAccountByPublicKey('d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'.codeUnits); + + expect(aliceAccount.name, 'Alice'); + expect(alicePair.address, '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'); + }); + + test('test alice works', () async { + final pair = await KeyPair.fromMnemonic('//Alice'); + expect( + pair.address, + '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', + ); + }); + }); +} diff --git a/app/test/utils/key_validation_test.dart b/packages/ew_keyring/test/validate_keys_test.dart similarity index 95% rename from app/test/utils/key_validation_test.dart rename to packages/ew_keyring/test/validate_keys_test.dart index ec6e25890..89af28355 100644 --- a/app/test/utils/key_validation_test.dart +++ b/packages/ew_keyring/test/validate_keys_test.dart @@ -1,6 +1,5 @@ -import 'package:flutter_test/flutter_test.dart'; - -import 'package:encointer_wallet/utils/validate_keys.dart'; +import 'package:ew_keyring/ew_keyring.dart'; +import 'package:test/test.dart'; void main() { group('PrivateKey', () {