mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-22 19:39:22 +00:00
WIP basic PoC showing firo spark address in stack wallet
This commit is contained in:
parent
6ddef9f077
commit
734e9d90b1
14 changed files with 160 additions and 43 deletions
|
@ -15,6 +15,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
|
@ -30,6 +31,7 @@ import 'package:stackwallet/utilities/text_styles.dart';
|
|||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
|
@ -57,6 +59,7 @@ class _DesktopReceiveState extends ConsumerState<DesktopReceive> {
|
|||
late final Coin coin;
|
||||
late final String walletId;
|
||||
late final ClipboardInterface clipboard;
|
||||
late final bool supportsSpark;
|
||||
|
||||
Future<void> generateNewAddress() async {
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
|
@ -98,6 +101,7 @@ class _DesktopReceiveState extends ConsumerState<DesktopReceive> {
|
|||
walletId = widget.walletId;
|
||||
coin = ref.read(pWalletInfo(walletId)).coin;
|
||||
clipboard = widget.clipboard;
|
||||
supportsSpark = ref.read(pWallets).getWallet(walletId) is SparkInterface;
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
@ -111,6 +115,106 @@ class _DesktopReceiveState extends ConsumerState<DesktopReceive> {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (supportsSpark)
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
clipboard.setData(
|
||||
ClipboardData(text: receivingAddress),
|
||||
);
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.info,
|
||||
message: "Copied to clipboard",
|
||||
iconAsset: Assets.svg.copy,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.backgroundAppBar,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
),
|
||||
child: RoundedWhiteContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your ${widget.contractAddress == null ? coin.ticker : ref.watch(
|
||||
tokenServiceProvider.select(
|
||||
(value) => value!.tokenContract.symbol,
|
||||
),
|
||||
)} SPARK address",
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.copy,
|
||||
width: 15,
|
||||
height: 15,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.infoItemIcons,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
Text(
|
||||
"Copy",
|
||||
style: STextStyles.link2(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FutureBuilder<Address?>(
|
||||
future: (ref.watch(pWallets).getWallet(walletId)
|
||||
as SparkInterface)
|
||||
.getCurrentReceivingSparkAddress(),
|
||||
builder: (context, snapshot) {
|
||||
String addressString = "Error";
|
||||
if (snapshot.hasData) {
|
||||
addressString = snapshot.data!.value;
|
||||
}
|
||||
|
||||
return Text(
|
||||
addressString,
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
|
|
|
@ -28,7 +28,7 @@ class BitcoinWallet extends Bip39HDWallet
|
|||
// ===========================================================================
|
||||
|
||||
@override
|
||||
Future<List<Address>> fetchAllOwnAddresses() async {
|
||||
Future<List<Address>> fetchAddressesForElectrumXScan() async {
|
||||
final allAddresses = await mainDB
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
|
@ -51,7 +51,7 @@ class BitcoinWallet extends Bip39HDWallet
|
|||
|
||||
// TODO: [prio=med] switch to V2 transactions
|
||||
final data = await fetchTransactionsV1(
|
||||
addresses: await fetchAllOwnAddresses(),
|
||||
addresses: await fetchAddressesForElectrumXScan(),
|
||||
currentChainHeight: currentChainHeight,
|
||||
);
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class BitcoincashWallet extends Bip39HDWallet
|
|||
// ===========================================================================
|
||||
|
||||
@override
|
||||
Future<List<Address>> fetchAllOwnAddresses() async {
|
||||
Future<List<Address>> fetchAddressesForElectrumXScan() async {
|
||||
final allAddresses = await mainDB
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
|
@ -94,7 +94,7 @@ class BitcoincashWallet extends Bip39HDWallet
|
|||
|
||||
@override
|
||||
Future<void> updateTransactions() async {
|
||||
List<Address> allAddressesOld = await fetchAllOwnAddresses();
|
||||
List<Address> allAddressesOld = await fetchAddressesForElectrumXScan();
|
||||
|
||||
Set<String> receivingAddresses = allAddressesOld
|
||||
.where((e) => e.subType == AddressSubType.receiving)
|
||||
|
|
|
@ -24,7 +24,7 @@ class DogecoinWallet extends Bip39HDWallet
|
|||
// ===========================================================================
|
||||
|
||||
@override
|
||||
Future<List<Address>> fetchAllOwnAddresses() async {
|
||||
Future<List<Address>> fetchAddressesForElectrumXScan() async {
|
||||
final allAddresses = await mainDB
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
|
@ -47,7 +47,7 @@ class DogecoinWallet extends Bip39HDWallet
|
|||
|
||||
// TODO: [prio=med] switch to V2 transactions
|
||||
final data = await fetchTransactionsV1(
|
||||
addresses: await fetchAllOwnAddresses(),
|
||||
addresses: await fetchAddressesForElectrumXScan(),
|
||||
currentChainHeight: currentChainHeight,
|
||||
);
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class EcashWallet extends Bip39HDWallet
|
|||
// ===========================================================================
|
||||
|
||||
@override
|
||||
Future<List<Address>> fetchAllOwnAddresses() async {
|
||||
Future<List<Address>> fetchAddressesForElectrumXScan() async {
|
||||
final allAddresses = await mainDB
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
|
@ -87,7 +87,7 @@ class EcashWallet extends Bip39HDWallet
|
|||
|
||||
@override
|
||||
Future<void> updateTransactions() async {
|
||||
List<Address> allAddressesOld = await fetchAllOwnAddresses();
|
||||
List<Address> allAddressesOld = await fetchAddressesForElectrumXScan();
|
||||
|
||||
Set<String> receivingAddresses = allAddressesOld
|
||||
.where((e) => e.subType == AddressSubType.receiving)
|
||||
|
|
|
@ -37,24 +37,6 @@ class FiroWallet extends Bip39HDWallet
|
|||
|
||||
// ===========================================================================
|
||||
|
||||
@override
|
||||
Future<List<Address>> fetchAllOwnAddresses() async {
|
||||
final allAddresses = await mainDB
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
.not()
|
||||
.group(
|
||||
(q) => q
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.nonWallet),
|
||||
)
|
||||
.findAll();
|
||||
return allAddresses;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
bool _duplicateTxCheck(
|
||||
List<Map<String, dynamic>> allTransactions, String txid) {
|
||||
for (int i = 0; i < allTransactions.length; i++) {
|
||||
|
@ -67,7 +49,7 @@ class FiroWallet extends Bip39HDWallet
|
|||
|
||||
@override
|
||||
Future<void> updateTransactions() async {
|
||||
final allAddresses = await fetchAllOwnAddresses();
|
||||
final allAddresses = await fetchAddressesForElectrumXScan();
|
||||
|
||||
Set<String> receivingAddresses = allAddresses
|
||||
.where((e) => e.subType == AddressSubType.receiving)
|
||||
|
|
|
@ -289,7 +289,10 @@ abstract class Wallet<T extends CryptoCurrency> {
|
|||
|
||||
// listen to changes in db and updated wallet info property as required
|
||||
void _watchWalletInfo() {
|
||||
_walletInfoStream = mainDB.isar.walletInfo.watchObject(_walletInfo.id);
|
||||
_walletInfoStream = mainDB.isar.walletInfo.watchObject(
|
||||
_walletInfo.id,
|
||||
fireImmediately: true,
|
||||
);
|
||||
_walletInfoStream.forEach((element) {
|
||||
if (element != null) {
|
||||
_walletInfo = element;
|
||||
|
|
|
@ -1641,7 +1641,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
|||
|
||||
@override
|
||||
Future<void> updateUTXOs() async {
|
||||
final allAddresses = await fetchAllOwnAddresses();
|
||||
final allAddresses = await fetchAddressesForElectrumXScan();
|
||||
|
||||
try {
|
||||
final fetchedUtxoList = <List<Map<String, dynamic>>>[];
|
||||
|
@ -1856,7 +1856,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
|||
int estimateTxFee({required int vSize, required int feeRatePerKB});
|
||||
Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB);
|
||||
|
||||
Future<List<Address>> fetchAllOwnAddresses();
|
||||
Future<List<Address>> fetchAddressesForElectrumXScan();
|
||||
|
||||
/// Certain coins need to check if the utxo should be marked
|
||||
/// as blocked as well as give a reason.
|
||||
|
|
|
@ -10,6 +10,40 @@ import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
|
|||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
|
||||
|
||||
mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||
@override
|
||||
Future<void> init() async {
|
||||
Address? address = await getCurrentReceivingSparkAddress();
|
||||
if (address == null) {
|
||||
address = await generateNextSparkAddress();
|
||||
await mainDB.putAddress(address);
|
||||
} // TODO add other address types to wallet info?
|
||||
|
||||
// await info.updateReceivingAddress(
|
||||
// newAddress: address.value,
|
||||
// isar: mainDB.isar,
|
||||
// );
|
||||
|
||||
await super.init();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Address>> fetchAddressesForElectrumXScan() async {
|
||||
final allAddresses = await mainDB
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
.not()
|
||||
.group(
|
||||
(q) => q
|
||||
.typeEqualTo(AddressType.spark)
|
||||
.or()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.nonWallet),
|
||||
)
|
||||
.findAll();
|
||||
return allAddresses;
|
||||
}
|
||||
|
||||
Future<Address?> getCurrentReceivingSparkAddress() async {
|
||||
return await mainDB.isar.addresses
|
||||
.where()
|
||||
|
@ -29,15 +63,18 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future<Address> generateNextSparkAddress({int index = 1}) async {
|
||||
Future<Address> generateNextSparkAddress() async {
|
||||
final highestStoredDiversifier =
|
||||
(await getCurrentReceivingSparkAddress())?.derivationIndex;
|
||||
|
||||
// default to starting at 1 if none found
|
||||
final int diversifier = (highestStoredDiversifier ?? 0) + 1;
|
||||
|
||||
// TODO: check that this stays constant and only the diversifier changes?
|
||||
const index = 1;
|
||||
|
||||
final root = await getRootHDNode();
|
||||
final derivationPath = "$kSparkBaseDerivationPath$index";
|
||||
const derivationPath = "$kSparkBaseDerivationPath$index";
|
||||
final keys = root.derivePath(derivationPath);
|
||||
|
||||
final String addressString = await LibSpark.getAddress(
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <devicelocale/devicelocale_plugin.h>
|
||||
#include <flutter_libepiccash/flutter_libepiccash_plugin.h>
|
||||
#include <flutter_libmonero/flutter_libmonero_plugin.h>
|
||||
#include <flutter_libsparkmobile/flutter_libsparkmobile_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
||||
#include <stack_wallet_backup/stack_wallet_backup_plugin.h>
|
||||
|
@ -30,9 +29,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) flutter_libmonero_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibmoneroPlugin");
|
||||
flutter_libmonero_plugin_register_with_registrar(flutter_libmonero_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_libsparkmobile_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibsparkmobilePlugin");
|
||||
flutter_libsparkmobile_plugin_register_with_registrar(flutter_libsparkmobile_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
|
||||
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
|
||||
|
|
|
@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
devicelocale
|
||||
flutter_libepiccash
|
||||
flutter_libmonero
|
||||
flutter_libsparkmobile
|
||||
flutter_secure_storage_linux
|
||||
isar_flutter_libs
|
||||
stack_wallet_backup
|
||||
|
@ -17,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
coinlib_flutter
|
||||
flutter_libsparkmobile
|
||||
tor_ffi_plugin
|
||||
)
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ import desktop_drop
|
|||
import device_info_plus
|
||||
import devicelocale
|
||||
import flutter_libepiccash
|
||||
import flutter_libsparkmobile
|
||||
import flutter_local_notifications
|
||||
import flutter_secure_storage_macos
|
||||
import isar_flutter_libs
|
||||
|
@ -35,7 +34,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
|
||||
FlutterLibepiccashPlugin.register(with: registry.registrar(forPlugin: "FlutterLibepiccashPlugin"))
|
||||
FlutterLibsparkmobilePlugin.register(with: registry.registrar(forPlugin: "FlutterLibsparkmobilePlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <flutter_libepiccash/flutter_libepiccash_plugin_c_api.h>
|
||||
#include <flutter_libsparkmobile/flutter_libsparkmobile_plugin_c_api.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
|
@ -25,8 +24,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
||||
FlutterLibepiccashPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterLibepiccashPluginCApi"));
|
||||
FlutterLibsparkmobilePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterLibsparkmobilePluginCApi"));
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
IsarFlutterLibsPluginRegisterWithRegistrar(
|
||||
|
|
|
@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
connectivity_plus
|
||||
desktop_drop
|
||||
flutter_libepiccash
|
||||
flutter_libsparkmobile
|
||||
flutter_secure_storage_windows
|
||||
isar_flutter_libs
|
||||
permission_handler_windows
|
||||
|
@ -17,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
flutter_libsparkmobile
|
||||
tor_ffi_plugin
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue