From ed269e0ae7b616068054900c75f5b8a008d1dcce Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Fri, 20 Sep 2024 15:19:08 +0200 Subject: [PATCH] spending, urqr, wallet save() --- android/app/src/main/jniLibs/.gitignore | 1 + lib/coins/monero.dart | 42 ++++++++++++++++--- .../barcode_scanner_view_model.dart | 10 ++--- .../unconfirmed_transaction_view_model.dart | 10 ++++- lib/views/unconfirmed_transaction.dart | 10 +++-- lib/views/urqr.dart | 10 +++++ 6 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 android/app/src/main/jniLibs/.gitignore diff --git a/android/app/src/main/jniLibs/.gitignore b/android/app/src/main/jniLibs/.gitignore new file mode 100644 index 0000000..28bbbde --- /dev/null +++ b/android/app/src/main/jniLibs/.gitignore @@ -0,0 +1 @@ +libmonero_libwallet2_api_c.so diff --git a/lib/coins/monero.dart b/lib/coins/monero.dart index 009aac3..20884ea 100644 --- a/lib/coins/monero.dart +++ b/lib/coins/monero.dart @@ -4,8 +4,10 @@ import 'package:cup_cake/coins/abstract.dart'; import 'package:cup_cake/utils/filesystem.dart'; import 'package:cup_cake/view_model/barcode_scanner_view_model.dart'; import 'package:cup_cake/view_model/unconfirmed_transaction_view_model.dart'; +import 'package:cup_cake/view_model/urqr_view_model.dart'; import 'package:cup_cake/views/open_wallet.dart'; import 'package:cup_cake/views/unconfirmed_transaction.dart'; +import 'package:cup_cake/views/urqr.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/src/widgets/framework.dart'; import 'package:monero/monero.dart' as monero; @@ -224,7 +226,7 @@ class Monero implements Coin { walletPath: walletPath, walletPassword: walletPassword, seed: seed!, - seedOffsetOrEncryption: seedOffsetOrEncryption!); + seedOffsetOrEncryption: seedOffsetOrEncryption ?? ""); // polyseed // polyseed encrypted // polyseed offset @@ -235,7 +237,7 @@ class Monero implements Coin { walletPath: walletPath, walletPassword: walletPassword, seed: seed!, - seedOffsetOrEncryption: seedOffsetOrEncryption!); + seedOffsetOrEncryption: seedOffsetOrEncryption ?? ""); // legacy seed // legacy seed offset } else if (createWallet == false && spendKey != "") { @@ -325,6 +327,10 @@ class MoneroWallet implements CoinWallet { MoneroWallet(this.wptr); monero.wallet wptr; + void save() { + monero.Wallet_store(wptr); + } + @override Coin coin = Monero(); @@ -342,6 +348,7 @@ class MoneroWallet implements CoinWallet { throw Exception("Given index is larger than current account count"); } _accountIndex = accountIndex; + save(); } @override @@ -372,6 +379,27 @@ class MoneroWallet implements CoinWallet { throw Exception("Unable to handle ${ur.tag}. This is a offline wallet"); case "xmr-output": monero.Wallet_importOutputsUR(wptr, ur.inputs.join("\n")); + var status = monero.Wallet_status(wptr); + if (status != 0) { + final error = monero.Wallet_errorString(wptr); + throw CoinException(error); + } + final allImages = monero.Wallet_exportKeyImagesUR(wptr, + max_fragment_length: 130, all: true) + .split("\n"); + final someImages = monero.Wallet_exportKeyImagesUR(wptr, + max_fragment_length: 130, all: false) + .split("\n"); + await AnimatedURPage.staticPush( + context, + URQRViewModel( + urqrList: { + "Partial Key Images": someImages, + "All Key Images": allImages, + }, + ), + ); + save(); case "xmr-txunsigned": final txptr = monero.Wallet_loadUnsignedTxUR(wptr, input: ur.inputs.join("\n")); @@ -406,12 +434,16 @@ class MoneroWallet implements CoinWallet { wallet: this, destMap: destMap, fee: fee, - confirmCallback: () => { - // show the other URQR code. + confirmCallback: (BuildContext context) async { + final signedTx = + monero.UnsignedTransaction_signUR(txptr, 130).split("\n"); + await AnimatedURPage.staticPush( + context, URQRViewModel(urqrList: {"signedTx": signedTx})); }, - cancelCallback: () => {}, + cancelCallback: (BuildContext context) => {}, ), ); + save(); default: throw UnimplementedError("Unable to handle ${ur.tag}."); } diff --git a/lib/view_model/barcode_scanner_view_model.dart b/lib/view_model/barcode_scanner_view_model.dart index 2b9da5e..35ecc41 100644 --- a/lib/view_model/barcode_scanner_view_model.dart +++ b/lib/view_model/barcode_scanner_view_model.dart @@ -36,7 +36,7 @@ class BarcodeScannerViewModel extends ViewModel { } } - void handleBarcode(BuildContext context, BarcodeCapture barcodes) { + void handleBarcode(BuildContext context, BarcodeCapture barcodes) async { for (final barcode in barcodes.barcodes) { print(barcode.rawValue!); if (barcode.rawValue!.startsWith("ur:")) { @@ -46,10 +46,8 @@ class BarcodeScannerViewModel extends ViewModel { markNeedsBuild(); if (ur.progress == 1) { popped = true; + await handleUR(context); markNeedsBuild(); - SchedulerBinding.instance.addPostFrameCallback((_) { - Navigator.of(context).pop(ur.inputs.join("\n")); - }); return; } } @@ -59,9 +57,7 @@ class BarcodeScannerViewModel extends ViewModel { barcode = barcodes.barcodes.firstOrNull; if (barcode != null && popped != true) { popped = true; - SchedulerBinding.instance.addPostFrameCallback((_) { - Navigator.of(context).pop(barcode?.rawValue ?? ""); - }); + await handleUR(context); } markNeedsBuild(); } diff --git a/lib/view_model/unconfirmed_transaction_view_model.dart b/lib/view_model/unconfirmed_transaction_view_model.dart index 5d2a4d2..536d725 100644 --- a/lib/view_model/unconfirmed_transaction_view_model.dart +++ b/lib/view_model/unconfirmed_transaction_view_model.dart @@ -2,10 +2,16 @@ import 'dart:async'; import 'package:cup_cake/coins/abstract.dart'; import 'package:cup_cake/view_model/abstract.dart'; +import 'package:flutter/cupertino.dart'; class Address { Address(this.address); final String address; + + @override + String toString() { + return address; + } } class Amount { @@ -29,8 +35,8 @@ class UnconfirmedTransactionViewModel extends ViewModel { @override late String screenName = wallet.coin.strings.nameFull; - final FutureOr Function() confirmCallback; - final FutureOr Function() cancelCallback; + final FutureOr Function(BuildContext context) confirmCallback; + final FutureOr Function(BuildContext context) cancelCallback; final Amount fee; final Map destMap; diff --git a/lib/views/unconfirmed_transaction.dart b/lib/views/unconfirmed_transaction.dart index 899187e..8d3fba0 100644 --- a/lib/views/unconfirmed_transaction.dart +++ b/lib/views/unconfirmed_transaction.dart @@ -38,18 +38,22 @@ class UnconfirmedTransactionView extends AbstractView { items: const [ BottomNavigationBarItem( icon: Icon(Icons.cancel), + label: "Cancel", ), BottomNavigationBarItem( icon: Icon(Icons.check_circle), + label: "Confirm" ), ], - onTap: (int index) { + onTap: (int index) async { if (index == 0) { + await viewModel.cancelCallback(context); + if (!context.mounted) return; Navigator.of(context).pop(); - viewModel.cancelCallback(); } else { + await viewModel.confirmCallback(context); + if (!context.mounted) return; Navigator.of(context).pop(); - viewModel.confirmCallback(); } }, ); diff --git a/lib/views/urqr.dart b/lib/views/urqr.dart index 7b29559..68d6762 100644 --- a/lib/views/urqr.dart +++ b/lib/views/urqr.dart @@ -2,11 +2,21 @@ import 'dart:async'; import 'package:cup_cake/view_model/urqr_view_model.dart'; import 'package:cup_cake/views/abstract.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:qr_flutter/qr_flutter.dart'; //ignore: must_be_immutable class AnimatedURPage extends AbstractView { + static Future staticPush( + BuildContext context, URQRViewModel viewModel) async { + await Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) => AnimatedURPage(viewModel: viewModel), + ), + ); + } + AnimatedURPage({super.key, required this.viewModel}); @override