diff --git a/Makefile b/Makefile index f8205ab9d..3eaef2370 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # TODO(mrcyjanek): Cleanup, this is borrowed from unnamed_monero_wallet repo. -MONERO_C_TAG=v0.18.3.3-RC21 +MONERO_C_TAG=v0.18.3.3-RC27 LIBCPP_SHARED_SO_TAG=latest-RC1 LIBCPP_SHARED_SO_NDKVERSION=r17c diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index e2dd94d7a..f7aa1e104 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -245,8 +245,8 @@ packages: dependency: transitive description: path: "." - ref: master - resolved-ref: "08c5a32cbcf1f04dbae5826c83abda8fb0dbdcce" + ref: ada81417cb53d8b0e34022df1dd3d9dc1fe62ab5 + resolved-ref: ada81417cb53d8b0e34022df1dd3d9dc1fe62ab5 url: "https://git.mrcyjanek.net/mrcyjanek/monero.dart" source: git version: "0.0.0" diff --git a/cw_monero/lib/api/account_list.dart b/cw_monero/lib/api/account_list.dart index ae94d16ea..199896631 100644 --- a/cw_monero/lib/api/account_list.dart +++ b/cw_monero/lib/api/account_list.dart @@ -2,6 +2,18 @@ import 'package:cw_monero/api/wallet.dart'; import 'package:monero/monero.dart' as monero; monero.wallet? wptr = null; + +int _wlptrForW = 0; +monero.WalletListener? _wlptr = null; + +monero.WalletListener getWlptr() { + if (wptr!.address == _wlptrForW) return _wlptr!; + _wlptrForW = wptr!.address; + _wlptr = monero.MONERO_cw_getWalletListener(wptr!); + return _wlptr!; +} + + monero.SubaddressAccount? subaddressAccount; bool isUpdating = false; diff --git a/cw_monero/lib/api/structs/pending_transaction.dart b/cw_monero/lib/api/structs/pending_transaction.dart index 656ed333f..dc5fbddd0 100644 --- a/cw_monero/lib/api/structs/pending_transaction.dart +++ b/cw_monero/lib/api/structs/pending_transaction.dart @@ -1,25 +1,3 @@ -import 'dart:ffi'; -import 'package:ffi/ffi.dart'; - -class PendingTransactionRaw extends Struct { - @Int64() - external int amount; - - @Int64() - external int fee; - - external Pointer hash; - - external Pointer hex; - - external Pointer txKey; - - String getHash() => hash.toDartString(); - - String getHex() => hex.toDartString(); - - String getKey() => txKey.toDartString(); -} class PendingTransactionDescription { PendingTransactionDescription({ diff --git a/cw_monero/lib/api/subaddress_list.dart b/cw_monero/lib/api/subaddress_list.dart index a172b93c4..57edea76e 100644 --- a/cw_monero/lib/api/subaddress_list.dart +++ b/cw_monero/lib/api/subaddress_list.dart @@ -1,14 +1,23 @@ + import 'package:cw_monero/api/account_list.dart'; import 'package:cw_monero/api/wallet.dart'; import 'package:monero/monero.dart' as monero; bool isUpdating = false; -monero.Subaddress? subaddressPtr = null; + +class SubaddressInfoMetadata { + SubaddressInfoMetadata({ + required this.accountIndex, + }); + int accountIndex; +} + +SubaddressInfoMetadata? subaddress = null; + void refreshSubaddresses({required int accountIndex}) { try { isUpdating = true; - subaddressPtr = monero.Wallet_subaddress(wptr!); - monero.Subaddress_refresh(subaddressPtr!,accountIndex: accountIndex, label: ''); + subaddress = SubaddressInfoMetadata(accountIndex: accountIndex); isUpdating = false; } catch (e) { isUpdating = false; @@ -16,17 +25,29 @@ void refreshSubaddresses({required int accountIndex}) { } } -List getAllSubaddresses() { - monero.Subaddress_refresh(subaddressPtr!, - accountIndex: 0, - label: '' // BUG: by me (mrcyjanek), it isn't used, will remove. - ); - final size = monero.Subaddress_getAll_size(subaddressPtr!); - - - return List.generate(size, (index) { - return monero.Subaddress_getAll_byIndex(subaddressAccount!, index: index); +class Subaddress { + Subaddress({ + required this.addressIndex, + required this.accountIndex, }); + String get address => monero.Wallet_address( + wptr!, + accountIndex: accountIndex, + addressIndex: addressIndex, + ); + final int addressIndex; + final int accountIndex; + String get label => monero.Wallet_getSubaddressLabel(wptr!, accountIndex: accountIndex, addressIndex: addressIndex); +} + +List getAllSubaddresses() { + final size = monero.Wallet_numSubaddresses(wptr!, accountIndex: subaddress!.accountIndex); + return List.generate(size, (index) { + return Subaddress( + accountIndex: subaddress!.accountIndex, + addressIndex: index, + ); + }).reversed.toList(); } void addSubaddressSync({required int accountIndex, required String label}) { diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index 4dff7dfe3..020b19981 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -1,10 +1,8 @@ -import 'dart:ffi'; import 'package:cw_monero/api/account_list.dart'; import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart'; import 'package:cw_monero/api/monero_output.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; -import 'package:ffi/ffi.dart'; import 'package:monero/monero.dart' as monero; @@ -39,16 +37,6 @@ PendingTransactionDescription createTransactionSync( String? amount, int accountIndex = 0, List preferredInputs = const []}) { - final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr; - - final int preferredInputsSize = preferredInputs.length; - final List> preferredInputsPointers = - preferredInputs.map((output) => output.toNativeUtf8()).toList(); - final Pointer> preferredInputsPointerPointer = calloc(preferredInputsSize); - - for (int i = 0; i < preferredInputsSize; i++) { - preferredInputsPointerPointer[i] = preferredInputsPointers[i]; - } final amt = amount == null ? 0 : monero.Wallet_amountFromString(amount); final pendingTx = monero.Wallet_createTransaction( @@ -74,12 +62,17 @@ PendingTransactionDescription createTransactionSync( throw CreationTransactionException(message: message); } + final rAmt = monero.PendingTransaction_amount(pendingTx); + final rFee = monero.PendingTransaction_fee(pendingTx); + final rHash = monero.PendingTransaction_txid(pendingTx, ''); + final rTxKey = rHash; + return PendingTransactionDescription( - amount: monero.PendingTransaction_amount(wptr!), - fee: monero.PendingTransaction_fee(wptr!), - hash: monero.PendingTransaction_txid(wptr!, ''), + amount: rAmt, + fee: rFee, + hash: rHash, hex: '', - txKey: monero.PendingTransaction_txid(wptr!, ''), + txKey: rTxKey, pointerAddress: pendingTx.address, ); } diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart deleted file mode 100644 index 40a1e0321..000000000 --- a/cw_monero/lib/api/types.dart +++ /dev/null @@ -1,153 +0,0 @@ -import 'dart:ffi'; -import 'package:cw_monero/api/structs/coins_info_row.dart'; -import 'package:cw_monero/api/structs/pending_transaction.dart'; -import 'package:cw_monero/api/structs/transaction_info_row.dart'; -import 'package:cw_monero/api/structs/ut8_box.dart'; -import 'package:ffi/ffi.dart'; - -typedef CreateWallet = int Function( - Pointer, Pointer, Pointer, int, Pointer); - -typedef RestoreWalletFromSeed = int Function( - Pointer, Pointer, Pointer, int, int, Pointer); - -typedef RestoreWalletFromKeys = int Function(Pointer, Pointer, - Pointer, Pointer, Pointer, Pointer, int, int, Pointer); - -typedef RestoreWalletFromSpendKey = int Function(Pointer, Pointer, Pointer, - Pointer, Pointer, int, int, Pointer); - -typedef IsWalletExist = int Function(Pointer); - -typedef LoadWallet = int Function(Pointer, Pointer, int); - -typedef ErrorString = Pointer Function(); - -typedef GetFilename = Pointer Function(); - -typedef GetSeed = Pointer Function(); - -typedef GetAddress = Pointer Function(int, int); - -typedef GetFullBalance = int Function(int); - -typedef GetUnlockedBalance = int Function(int); - -typedef GetCurrentHeight = int Function(); - -typedef GetNodeHeight = int Function(); - -typedef IsConnected = int Function(); - -typedef SetupNode = int Function( - Pointer, Pointer?, Pointer?, int, int, Pointer?, Pointer); - -typedef StartRefresh = void Function(); - -typedef ConnectToNode = int Function(); - -typedef SetRefreshFromBlockHeight = void Function(int); - -typedef SetRecoveringFromSeed = void Function(int); - -typedef Store = void Function(Pointer); - -typedef SetPassword = int Function(Pointer password, Pointer error); - -typedef SetListener = void Function(); - -typedef GetSyncingHeight = int Function(); - -typedef IsNeededToRefresh = int Function(); - -typedef IsNewTransactionExist = int Function(); - -typedef SubaddressSize = int Function(); - -typedef SubaddressRefresh = void Function(int); - -typedef SubaddressGetAll = Pointer Function(); - -typedef SubaddressAddNew = void Function(int accountIndex, Pointer label); - -typedef SubaddressSetLabel = void Function( - int accountIndex, int addressIndex, Pointer label); - -typedef AccountSize = int Function(); - -typedef AccountRefresh = void Function(); - -typedef AccountGetAll = Pointer Function(); - -typedef AccountAddNew = void Function(Pointer label); - -typedef AccountSetLabel = void Function(int accountIndex, Pointer label); - -typedef TransactionsRefresh = void Function(); - -typedef GetTransaction = Pointer Function(Pointer txId); - -typedef GetTxKey = Pointer? Function(Pointer txId); - -typedef TransactionsCount = int Function(); - -typedef TransactionsGetAll = Pointer Function(); - -typedef TransactionCreate = int Function( - Pointer address, - Pointer paymentId, - Pointer amount, - int priorityRaw, - int subaddrAccount, - Pointer> preferredInputs, - int preferredInputsSize, - Pointer error, - Pointer pendingTransaction); - -typedef TransactionCreateMultDest = int Function( - Pointer> addresses, - Pointer paymentId, - Pointer> amounts, - int size, - int priorityRaw, - int subaddrAccount, - Pointer> preferredInputs, - int preferredInputsSize, - Pointer error, - Pointer pendingTransaction); - -typedef TransactionCommit = int Function(Pointer, Pointer); - -typedef SecretViewKey = Pointer Function(); - -typedef PublicViewKey = Pointer Function(); - -typedef SecretSpendKey = Pointer Function(); - -typedef PublicSpendKey = Pointer Function(); - -typedef CloseCurrentWallet = void Function(); - -typedef OnStartup = void Function(); - -typedef RescanBlockchainAsync = void Function(); - -typedef GetSubaddressLabel = Pointer Function( - int accountIndex, - int addressIndex); - -typedef SetTrustedDaemon = void Function(int); - -typedef TrustedDaemon = int Function(); - -typedef RefreshCoins = void Function(int); - -typedef CoinsCount = int Function(); - -typedef GetCoin = Pointer Function(int); - -typedef FreezeCoin = void Function(int); - -typedef ThawCoin = void Function(int); - -typedef SignMessage = Pointer Function(Pointer, Pointer); diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index 79b067768..0f354bea9 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -6,12 +6,19 @@ import 'package:monero/monero.dart' as monero; int _boolToInt(bool value) => value ? 1 : 0; -int getSyncingHeight() => monero.Wallet_blockChainHeight(wptr!); +int getSyncingHeight() => monero.MONERO_cw_WalletListener_height(getWlptr()); -bool isNeededToRefresh() => false; // TODO(mrcyjanek): ? - -bool isNewTransactionExist() => false; +bool isNeededToRefresh() { + final ret = monero.MONERO_cw_WalletListener_isNeedToRefresh(getWlptr()); + monero.MONERO_cw_WalletListener_resetNeedToRefresh(getWlptr()); + return ret; +} +bool isNewTransactionExist() { + final ret = monero.MONERO_cw_WalletListener_isNewTransactionExist(getWlptr()); + monero.MONERO_cw_WalletListener_resetIsNewTransactionExist(getWlptr()); + return ret; +} String getFilename() => monero.Wallet_filename(wptr!); // TODO(mrcyjanek): Cake polyseed support diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index 84860e642..aeacf2769 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -1,4 +1,6 @@ +import 'dart:ffi'; + import 'package:cw_monero/api/account_list.dart'; import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart'; import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; @@ -7,7 +9,6 @@ import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart import 'package:cw_monero/api/wallet.dart'; import 'package:ffi/ffi.dart'; import 'package:monero/monero.dart' as monero; -import 'dart:ffi'; monero.WalletManager? _wmPtr; final monero.WalletManager wmPtr = Pointer.fromAddress((() { @@ -135,12 +136,20 @@ void restoreWalletFromSpendKeySync( storeSync(); } +String _lastOpenedWallet = ""; + void loadWallet({ required String path, required String password, int nettype = 0}) { try { - wptr ??= monero.WalletManager_openWallet(wmPtr, path: path, password: password); + if (wptr == null || path != _lastOpenedWallet) { + if (wptr != null) { + monero.Wallet_store(wptr!); + } + wptr = monero.WalletManager_openWallet(wmPtr, path: path, password: password); + _lastOpenedWallet = path; + } } catch (e) { print(e); } diff --git a/cw_monero/lib/monero_subaddress_list.dart b/cw_monero/lib/monero_subaddress_list.dart index 2d3ecdb7e..676a9536c 100644 --- a/cw_monero/lib/monero_subaddress_list.dart +++ b/cw_monero/lib/monero_subaddress_list.dart @@ -1,9 +1,8 @@ -import 'package:flutter/services.dart'; -import 'package:mobx/mobx.dart'; +import 'package:cw_core/subaddress.dart'; import 'package:cw_monero/api/coins_info.dart'; import 'package:cw_monero/api/subaddress_list.dart' as subaddress_list; -import 'package:cw_core/subaddress.dart'; -import 'package:monero/monero.dart' as monero; +import 'package:flutter/services.dart'; +import 'package:mobx/mobx.dart'; part 'monero_subaddress_list.g.dart'; @@ -51,10 +50,10 @@ abstract class MoneroSubaddressListBase with Store { subaddresses = [primary] + rest.toList(); } - return subaddresses.map((subaddressRow) { - final label = monero.SubaddressRow_getLabel(subaddressRow); - final id = monero.SubaddressRow_getRowId(subaddressRow); - final address = monero.SubaddressRow_getAddress(subaddressRow); + return subaddresses.map((s) { + final address = s.address; + final label = s.label; + final id = s.addressIndex; final hasDefaultAddressName = label.toLowerCase() == 'Primary account'.toLowerCase() || label.toLowerCase() == 'Untitled account'.toLowerCase(); @@ -125,7 +124,7 @@ abstract class MoneroSubaddressListBase with Store { Future> _getAllUnusedAddresses( {required int accountIndex, required String label}) async { final allAddresses = subaddress_list.getAllSubaddresses(); - final lastAddress = monero.SubaddressRow_getAddress(allAddresses.last); + final lastAddress = allAddresses.last.address; if (allAddresses.isEmpty || _usedAddresses.contains(lastAddress)) { final isAddressUnused = await _newSubaddress(accountIndex: accountIndex, label: label); if (!isAddressUnused) { @@ -134,10 +133,10 @@ abstract class MoneroSubaddressListBase with Store { } return allAddresses - .map((subaddressRow) { - final id = monero.SubaddressRow_getRowId(subaddressRow); - final address = monero.SubaddressRow_getAddress(subaddressRow); - final label = monero.SubaddressRow_getLabel(subaddressRow); + .map((s) { + final id = s.addressIndex; + final address = s.address; + final label = s.label; return Subaddress( id: id, address: address, @@ -154,8 +153,8 @@ abstract class MoneroSubaddressListBase with Store { return subaddress_list .getAllSubaddresses() - .where((subaddressRow) { - final address = monero.SubaddressRow_getAddress(subaddressRow); + .where((s) { + final address = s.address; return !_usedAddresses.contains(address); }) .isNotEmpty; diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 0faf7dab8..4ce0f7776 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -414,8 +414,8 @@ packages: dependency: "direct main" description: path: "." - ref: master - resolved-ref: "08c5a32cbcf1f04dbae5826c83abda8fb0dbdcce" + ref: ada81417cb53d8b0e34022df1dd3d9dc1fe62ab5 + resolved-ref: ada81417cb53d8b0e34022df1dd3d9dc1fe62ab5 url: "https://git.mrcyjanek.net/mrcyjanek/monero.dart" source: git version: "0.0.0" diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index e94b65067..6527dbee5 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: monero: git: url: https://git.mrcyjanek.net/mrcyjanek/monero.dart - ref: master + ref: ada81417cb53d8b0e34022df1dd3d9dc1fe62ab5 dev_dependencies: flutter_test: