From c74a1142090fe1a16e7952833bd44d828874a2b6 Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 16 Mar 2024 10:55:03 +0000 Subject: [PATCH] transfers in different assets --- cw_core/lib/amount_converter.dart | 1 - cw_zano/lib/api/model/asset_descriptor.dart | 38 -------- cw_zano/lib/api/model/destination.dart | 4 +- cw_zano/lib/api/model/recent_history.dart | 6 +- .../api/model/{history.dart => transfer.dart} | 6 +- cw_zano/lib/api/model/transfer_params.dart | 4 +- cw_zano/lib/pending_zano_transaction.dart | 22 +++-- cw_zano/lib/zano_asset.dart | 9 +- cw_zano/lib/zano_formatter.dart | 24 +++++ cw_zano/lib/zano_transaction_credentials.dart | 6 +- cw_zano/lib/zano_transaction_info.dart | 65 +++++++------ cw_zano/lib/zano_wallet.dart | 96 ++++++++++++------- cw_zano/lib/zano_wallet_api.dart | 9 +- cw_zano/lib/zano_wallet_service.dart | 19 ++-- cw_zano/pubspec.lock | 2 +- cw_zano/pubspec.yaml | 1 + .../dashboard/transaction_list_item.dart | 2 +- lib/view_model/send/send_view_model.dart | 12 +-- lib/zano/cw_zano.dart | 67 +++++++------ lib/zano/zano.dart | 4 +- 20 files changed, 211 insertions(+), 186 deletions(-) delete mode 100644 cw_zano/lib/api/model/asset_descriptor.dart rename cw_zano/lib/api/model/{history.dart => transfer.dart} (96%) create mode 100644 cw_zano/lib/zano_formatter.dart diff --git a/cw_core/lib/amount_converter.dart b/cw_core/lib/amount_converter.dart index 785d9a18a..a790e500f 100644 --- a/cw_core/lib/amount_converter.dart +++ b/cw_core/lib/amount_converter.dart @@ -2,7 +2,6 @@ import 'package:decimal/decimal.dart'; import 'package:decimal/intl.dart'; import 'package:intl/intl.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:rational/rational.dart'; class AmountConverter { static const _moneroAmountLength = 12; diff --git a/cw_zano/lib/api/model/asset_descriptor.dart b/cw_zano/lib/api/model/asset_descriptor.dart deleted file mode 100644 index 6f4ec5e6b..000000000 --- a/cw_zano/lib/api/model/asset_descriptor.dart +++ /dev/null @@ -1,38 +0,0 @@ -// class AssetDescriptor { -// static const defaultDecimalPoint = 12; -// final String assetId; -// final int currentSupply; -// final int decimalPoint; -// final String fullName; -// final bool hiddenSupply; -// final String metaInfo; -// final String owner; -// final String ticker; -// final int totalMaxSupply; - -// AssetDescriptor({ -// required this.assetId, -// required this.currentSupply, -// required this.decimalPoint, -// required this.fullName, -// required this.hiddenSupply, -// required this.metaInfo, -// required this.owner, -// required this.ticker, -// required this.totalMaxSupply, -// }); - -// factory AssetDescriptor.fromJson(Map json) => -// AssetDescriptor( -// assetId: json['asset_id'] as String? ?? '', -// currentSupply: json['current_supply'] as int? ?? 0, -// decimalPoint: json['decimal_point'] as int? ?? defaultDecimalPoint, -// fullName: json['full_name'] as String? ?? '', -// hiddenSupply: json['hidden_supply'] as bool? ?? false, -// metaInfo: json['meta_info'] as String? ?? '', -// owner: json['owner'] as String? ?? '', -// ticker: json['ticker'] as String? ?? '', -// totalMaxSupply: json['total_max_supply'] as int? ?? 0, -// ); - -// } diff --git a/cw_zano/lib/api/model/destination.dart b/cw_zano/lib/api/model/destination.dart index dd3867511..3db4f6652 100644 --- a/cw_zano/lib/api/model/destination.dart +++ b/cw_zano/lib/api/model/destination.dart @@ -1,5 +1,5 @@ class Destination { - final int amount; // transfered as string + final BigInt amount; // transfered as string final String address; final String assetId; @@ -7,7 +7,7 @@ class Destination { {required this.amount, required this.address, required this.assetId}); factory Destination.fromJson(Map json) => Destination( - amount: int.parse(json['amount'] as String? ?? '0'), + amount: BigInt.parse(json['amount'] as String? ?? '0'), address: json['address'] as String? ?? '', assetId: json['asset_id'] as String? ?? '', ); diff --git a/cw_zano/lib/api/model/recent_history.dart b/cw_zano/lib/api/model/recent_history.dart index 82e71ef44..6591f426d 100644 --- a/cw_zano/lib/api/model/recent_history.dart +++ b/cw_zano/lib/api/model/recent_history.dart @@ -1,7 +1,7 @@ -import 'package:cw_zano/api/model/history.dart'; +import 'package:cw_zano/api/model/transfer.dart'; class RecentHistory { - final List? history; + final List? history; final int lastItemIndex; final int totalHistoryItems; @@ -12,7 +12,7 @@ class RecentHistory { factory RecentHistory.fromJson(Map json) => RecentHistory( history: json['history'] == null ? null : (json['history'] as List) - .map((e) => History.fromJson(e as Map)) + .map((e) => Transfer.fromJson(e as Map)) .toList(), lastItemIndex: json['last_item_index'] as int? ?? 0, totalHistoryItems: json['total_history_items'] as int? ?? 0, diff --git a/cw_zano/lib/api/model/history.dart b/cw_zano/lib/api/model/transfer.dart similarity index 96% rename from cw_zano/lib/api/model/history.dart rename to cw_zano/lib/api/model/transfer.dart index faadfcdc2..5c8b66047 100644 --- a/cw_zano/lib/api/model/history.dart +++ b/cw_zano/lib/api/model/transfer.dart @@ -1,7 +1,7 @@ import 'package:cw_zano/api/model/employed_entries.dart'; import 'package:cw_zano/api/model/subtransfer.dart'; -class History { +class Transfer { final String comment; final EmployedEntries employedEntries; final int fee; @@ -21,7 +21,7 @@ class History { final int txType; final int unlockTime; - History({ + Transfer({ required this.comment, required this.employedEntries, required this.fee, @@ -42,7 +42,7 @@ class History { required this.unlockTime, }); - factory History.fromJson(Map json) => History( + factory Transfer.fromJson(Map json) => Transfer( comment: json['comment'] as String? ?? '', employedEntries: EmployedEntries.fromJson( json['employed_entries'] as Map? ?? {}), diff --git a/cw_zano/lib/api/model/transfer_params.dart b/cw_zano/lib/api/model/transfer_params.dart index 4f252c402..f1df727f5 100644 --- a/cw_zano/lib/api/model/transfer_params.dart +++ b/cw_zano/lib/api/model/transfer_params.dart @@ -2,7 +2,7 @@ import 'package:cw_zano/api/model/destination.dart'; class TransferParams { final List destinations; - final int fee; + final BigInt fee; final int mixin; final String paymentId; final String comment; @@ -31,7 +31,7 @@ class TransferParams { factory TransferParams.fromJson(Map json) => TransferParams( destinations: (json['destinations'] as List?)?.map((e) => Destination.fromJson(e as Map)).toList() ?? [], - fee: json['fee'] as int? ?? 0, + fee: BigInt.from(json['fee'] as int? ?? 0), mixin: json['mixin'] as int? ?? 0, paymentId: json['payment_id'] as String? ?? '', comment: json['comment'] as String? ?? '', diff --git a/cw_zano/lib/pending_zano_transaction.dart b/cw_zano/lib/pending_zano_transaction.dart index fc08b1840..726dda7f4 100644 --- a/cw_zano/lib/pending_zano_transaction.dart +++ b/cw_zano/lib/pending_zano_transaction.dart @@ -1,13 +1,11 @@ import 'dart:convert'; +import 'package:cw_core/pending_transaction.dart'; import 'package:cw_zano/api/exceptions/transfer_exception.dart'; import 'package:cw_zano/api/model/destination.dart'; -import 'package:cw_zano/api/model/history.dart'; import 'package:cw_zano/api/model/transfer_params.dart'; import 'package:cw_zano/api/model/transfer_result.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/amount_converter.dart'; -import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_zano/zano_formatter.dart'; import 'package:cw_zano/zano_wallet.dart'; class PendingZanoTransaction with PendingTransaction { @@ -16,12 +14,20 @@ class PendingZanoTransaction with PendingTransaction { required this.destinations, required this.fee, required this.comment, + required this.assetId, + required this.ticker, + this.decimalPoint = 12, + required this.amount, }); final ZanoWalletBase zanoWallet; final List destinations; - final int fee; + final BigInt fee; final String comment; + final String assetId; + final String ticker; + final int decimalPoint; + final BigInt amount; @override String get id => transferResult?.txHash ?? ''; @@ -30,10 +36,10 @@ class PendingZanoTransaction with PendingTransaction { String get hex => ''; @override - String get amountFormatted => AmountConverter.amountIntToString(CryptoCurrency.zano, destinations.first.amount); + String get amountFormatted => '${ZanoFormatter.bigIntAmountToString(amount, decimalPoint)} $ticker'; @override - String get feeFormatted => AmountConverter.amountIntToString(CryptoCurrency.zano, fee); + String get feeFormatted => '${ZanoFormatter.bigIntAmountToString(fee)} ZANO'; TransferResult? transferResult; @@ -66,4 +72,6 @@ class PendingZanoTransaction with PendingTransaction { } } } + + } diff --git a/cw_zano/lib/zano_asset.dart b/cw_zano/lib/zano_asset.dart index 376bd78eb..e2e80b450 100644 --- a/cw_zano/lib/zano_asset.dart +++ b/cw_zano/lib/zano_asset.dart @@ -1,5 +1,6 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/hive_type_ids.dart'; +import 'package:cw_zano/zano_formatter.dart'; import 'package:hive/hive.dart'; part 'zano_asset.g.dart'; @@ -39,7 +40,7 @@ class ZanoAsset extends CryptoCurrency with HiveObjectMixin { this.fullName = '', this.ticker = '', required this.assetId, - this.decimalPoint = defaultDecimalPoint, + this.decimalPoint = ZanoFormatter.defaultDecimalPoint, bool enabled = true, this.iconPath, this.tag, @@ -83,7 +84,7 @@ class ZanoAsset extends CryptoCurrency with HiveObjectMixin { factory ZanoAsset.fromJson(Map json) => ZanoAsset( assetId: json['asset_id'] as String? ?? '', currentSupply: json['current_supply'] as int? ?? 0, - decimalPoint: json['decimal_point'] as int? ?? defaultDecimalPoint, + decimalPoint: json['decimal_point'] as int? ?? ZanoFormatter.defaultDecimalPoint, fullName: json['full_name'] as String? ?? '', hiddenSupply: json['hidden_supply'] as bool? ?? false, metaInfo: json['meta_info'] as String? ?? '', @@ -92,11 +93,7 @@ class ZanoAsset extends CryptoCurrency with HiveObjectMixin { totalMaxSupply: json['total_max_supply'] as int? ?? 0, ); - @override - String toString() => '$ticker (${assetId.substring(0, 4)}...${assetId.substring(assetId.length - 4)})'; - static const typeId = ZANO_ASSET_TYPE_ID; static const zanoAssetsBoxName = 'zanoAssetsBox'; - static const defaultDecimalPoint = 12; static const defaultOwner = '0000000000000000000000000000000000000000000000000000000000000000'; } diff --git a/cw_zano/lib/zano_formatter.dart b/cw_zano/lib/zano_formatter.dart new file mode 100644 index 000000000..2b8d4977d --- /dev/null +++ b/cw_zano/lib/zano_formatter.dart @@ -0,0 +1,24 @@ +import 'dart:math'; + +import 'package:decimal/decimal.dart'; +import 'package:decimal/intl.dart'; +import 'package:intl/intl.dart'; + +class ZanoFormatter { + static const defaultDecimalPoint = 12; + + //static const _moneroAmountLength = 12; + static final numberFormat = NumberFormat() + ..maximumFractionDigits = defaultDecimalPoint + ..minimumFractionDigits = 1; + + static Decimal _intDivision({required int amount, required BigInt divider}) => (Decimal.fromInt(amount) / Decimal.fromBigInt(divider)).toDecimal(); + static Decimal _bigIntDivision({required BigInt amount, required BigInt divider}) => (Decimal.fromBigInt(amount) / Decimal.fromBigInt(divider)).toDecimal(); + + static String intAmountToString(int amount, [int decimalPoint = defaultDecimalPoint]) => numberFormat.format(DecimalIntl( + _intDivision(amount: amount, divider: BigInt.from(pow(10, decimalPoint))), + ),); + static String bigIntAmountToString(BigInt amount, [int decimalPoint = defaultDecimalPoint]) => numberFormat.format(DecimalIntl( + _bigIntDivision(amount: amount, divider: BigInt.from(pow(10, decimalPoint))), + ),); +} diff --git a/cw_zano/lib/zano_transaction_credentials.dart b/cw_zano/lib/zano_transaction_credentials.dart index 474a5b07f..d7a491b6a 100644 --- a/cw_zano/lib/zano_transaction_credentials.dart +++ b/cw_zano/lib/zano_transaction_credentials.dart @@ -1,10 +1,12 @@ +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/monero_transaction_priority.dart'; import 'package:cw_core/output_info.dart'; class ZanoTransactionCredentials { - ZanoTransactionCredentials({required this.outputs, required this.priority, required this.assetType}); + ZanoTransactionCredentials({required this.outputs, required this.priority, required this.currency}); final List outputs; final MoneroTransactionPriority priority; - final String assetType; + final CryptoCurrency currency; + //final String assetType; } diff --git a/cw_zano/lib/zano_transaction_info.dart b/cw_zano/lib/zano_transaction_info.dart index c332bf4d6..7f3ad1885 100644 --- a/cw_zano/lib/zano_transaction_info.dart +++ b/cw_zano/lib/zano_transaction_info.dart @@ -2,35 +2,37 @@ import 'package:cw_core/format_amount.dart'; import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; -import 'package:cw_zano/api/model/history.dart'; +import 'package:cw_zano/api/model/transfer.dart'; class ZanoTransactionInfo extends TransactionInfo { - ZanoTransactionInfo( - this.id, - this.height, - this.direction, - this.date, - this.isPending, - this.amount, - this.accountIndex, - this.addressIndex, - this.fee, - this.confirmations); + ZanoTransactionInfo({ + required this.id, + required this.height, + required this.direction, + required this.date, + required this.isPending, + required this.amount, + required this.accountIndex, + required this.addressIndex, + required this.fee, + required this.assetId, + required this.confirmations, + required this.tokenSymbol, + }); - ZanoTransactionInfo.fromHistory(History history) - : id = history.txHash, - height = history.height, - direction = history.subtransfers.first.isIncome ? TransactionDirection.incoming : - TransactionDirection.outgoing, - date = DateTime.fromMillisecondsSinceEpoch(history.timestamp * 1000), - isPending = false, - amount = history.subtransfers.first.amount, - accountIndex = 0, - addressIndex = 0, - fee = history.fee, - confirmations = 1, - assetType = 'ZANO', // TODO: FIXIT: - recipientAddress = history.remoteAddresses.isNotEmpty ? history.remoteAddresses.first : ''; + ZanoTransactionInfo.fromTransfer(Transfer transfer, this.tokenSymbol) + : id = transfer.txHash, + height = transfer.height, + direction = transfer.subtransfers.first.isIncome ? TransactionDirection.incoming : TransactionDirection.outgoing, + date = DateTime.fromMillisecondsSinceEpoch(transfer.timestamp * 1000), + isPending = false, + amount = transfer.subtransfers.first.amount, + accountIndex = 0, + addressIndex = 0, + fee = transfer.fee, + confirmations = 1, + assetId = transfer.subtransfers.first.assetId, + recipientAddress = transfer.remoteAddresses.isNotEmpty ? transfer.remoteAddresses.first : ''; final String id; final int height; @@ -43,13 +45,13 @@ class ZanoTransactionInfo extends TransactionInfo { final int addressIndex; final int confirmations; late String recipientAddress; - late String assetType; + final String tokenSymbol; + late String assetId; String? _fiatAmount; String? key; @override - String amountFormatted() => - '${formatAmount(moneroAmountToString(amount: amount))} $assetType'; + String amountFormatted() => '${formatAmount(moneroAmountToString(amount: amount))} $tokenSymbol'; @override String fiatAmount() => _fiatAmount ?? ''; @@ -58,6 +60,7 @@ class ZanoTransactionInfo extends TransactionInfo { void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); @override - String feeFormatted() => - '${formatAmount(moneroAmountToString(amount: fee))} $assetType'; + String feeFormatted() => '${formatAmount(moneroAmountToString(amount: fee))} $feeCurrency'; + + String get feeCurrency => 'ZANO'; } diff --git a/cw_zano/lib/zano_wallet.dart b/cw_zano/lib/zano_wallet.dart index 4ee2e3b1a..15098366b 100644 --- a/cw_zano/lib/zano_wallet.dart +++ b/cw_zano/lib/zano_wallet.dart @@ -15,12 +15,13 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_zano/api/api_calls.dart'; import 'package:cw_zano/api/model/destination.dart'; import 'package:cw_zano/api/model/get_wallet_status_result.dart'; -import 'package:cw_zano/api/model/history.dart'; +import 'package:cw_zano/api/model/transfer.dart'; import 'package:cw_zano/api/model/zano_wallet_keys.dart'; import 'package:cw_zano/exceptions/zano_transaction_creation_exception.dart'; import 'package:cw_zano/pending_zano_transaction.dart'; import 'package:cw_zano/zano_asset.dart'; import 'package:cw_zano/zano_balance.dart'; +import 'package:cw_zano/zano_formatter.dart'; import 'package:cw_zano/zano_transaction_credentials.dart'; import 'package:cw_zano/zano_transaction_history.dart'; import 'package:cw_zano/zano_transaction_info.dart'; @@ -41,7 +42,7 @@ class ZanoWallet = ZanoWalletBase with _$ZanoWallet; abstract class ZanoWalletBase extends WalletBase with Store, ZanoWalletApi { static const int _autoSaveInterval = 30; - List history = []; + List transfers = []; //String defaultAsssetId = ''; @override ZanoWalletAddresses walletAddresses; @@ -60,6 +61,7 @@ abstract class ZanoWalletBase extends WalletBase zanoAssetsBox; List get zanoAssets => zanoAssetsBox.values.toList(); @@ -128,45 +130,64 @@ abstract class ZanoWalletBase extends WalletBase createTransaction(Object credentials) async { - final creds = credentials as ZanoTransactionCredentials; - final outputs = creds.outputs; + credentials as ZanoTransactionCredentials; + bool isZano() => credentials.currency == CryptoCurrency.zano; + final outputs = credentials.outputs; final hasMultiDestination = outputs.length > 1; - final unlockedBalance = balance[CryptoCurrency.zano]?.unlocked ?? 0; - final fee = calculateEstimatedFee(creds.priority); + final unlockedBalanceZano = BigInt.from(balance[CryptoCurrency.zano]?.unlocked ?? 0); + final unlockedBalanceCurrency = BigInt.from(balance[credentials.currency]?.unlocked ?? 0); + final fee = BigInt.from(calculateEstimatedFee(credentials.priority)); + late BigInt totalAmount; + void checkForEnoughBalances() { + if (isZano()) { + if (totalAmount + fee > unlockedBalanceZano) { + throw ZanoTransactionCreationException( + "You don't have enough coins (required: ${ZanoFormatter.bigIntAmountToString(totalAmount + fee)} ZANO, unlocked ${ZanoFormatter.bigIntAmountToString(unlockedBalanceZano)} ZANO)."); + } + } else { + if (fee > unlockedBalanceZano) { + throw ZanoTransactionCreationException( + "You don't have enough coins (required: ${ZanoFormatter.bigIntAmountToString(fee)} ZANO, unlocked ${ZanoFormatter.bigIntAmountToString(unlockedBalanceZano)} ZANO)."); + } + if (totalAmount > unlockedBalanceCurrency) { + throw ZanoTransactionCreationException( + "You don't have enough coins (required: ${ZanoFormatter.bigIntAmountToString(totalAmount)} ${credentials.currency.title}, unlocked ${ZanoFormatter.bigIntAmountToString(unlockedBalanceZano)} ${credentials.currency.title})."); + } + } + } + + final assetId = isZano() ? zanoAssetId : (currency as ZanoAsset).assetId; late List destinations; if (hasMultiDestination) { if (outputs.any((output) => output.sendAll || (output.formattedCryptoAmount ?? 0) <= 0)) { throw ZanoTransactionCreationException("You don't have enough coins."); } - final int totalAmount = outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)); - if (totalAmount + fee > unlockedBalance) { - throw ZanoTransactionCreationException( - "You don't have enough coins (required: ${moneroAmountToString(amount: totalAmount + fee)}, unlocked ${moneroAmountToString(amount: unlockedBalance)})."); - } + totalAmount = outputs.fold(BigInt.zero, (acc, value) => acc + BigInt.from(value.formattedCryptoAmount ?? 0)); + checkForEnoughBalances(); destinations = outputs .map((output) => Destination( - amount: output.formattedCryptoAmount ?? 0, + amount: BigInt.from(output.formattedCryptoAmount ?? 0), address: output.isParsedAddress ? output.extractedAddress! : output.address, - assetId: "defaultAsssetId", + assetId: assetId, )) .toList(); } else { final output = outputs.first; - late int amount; if (output.sendAll) { - amount = unlockedBalance - fee; + if (isZano()) { + totalAmount = unlockedBalanceZano - fee; + } else { + totalAmount = unlockedBalanceCurrency; + } } else { - amount = output.formattedCryptoAmount!; - } - if (amount + fee > unlockedBalance) { - throw ZanoTransactionCreationException( - "You don't have enough coins (required: ${moneroAmountToString(amount: amount + fee)}, unlocked ${moneroAmountToString(amount: unlockedBalance)})."); + totalAmount = BigInt.from(output.formattedCryptoAmount!); } + checkForEnoughBalances(); destinations = [ Destination( - amount: amount, + amount: totalAmount, address: output.isParsedAddress ? output.extractedAddress! : output.address, - assetId: "defaultAsssetId", + assetId: assetId, ) ]; } @@ -178,18 +199,27 @@ abstract class ZanoWalletBase extends WalletBase> fetchTransactions() async { try { - await _refreshTransactions(); - return history.map((history) => ZanoTransactionInfo.fromHistory(history)).fold>( - {}, - (Map acc, ZanoTransactionInfo tx) { - acc[tx.id] = tx; - return acc; + transfers = await getRecentTxsAndInfo(); + return Map.fromIterable( + transfers, + key: (item) => (item as Transfer).txHash, + value: (item) { + item as Transfer; + if (item.subtransfers.first.assetId == zanoAssetId) { + return ZanoTransactionInfo.fromTransfer(item, 'ZANO'); + } else { + final tokenSymbol = zanoAssets.firstWhere((element) => element.assetId == item.subtransfers.first.assetId).ticker; + return ZanoTransactionInfo.fromTransfer(item, tokenSymbol); + } }, ); } catch (e) { @@ -286,7 +316,7 @@ abstract class ZanoWalletBase extends WalletBase _refreshTransactions() async { - try { - history = await getRecentTxsAndInfo(); - } catch (e) { - print(e.toString()); - } - } - void _updateSyncProgress(GetWalletStatusResult walletStatus) { final syncHeight = walletStatus.currentWalletHeight; if (_initialSyncHeight <= 0) { diff --git a/cw_zano/lib/zano_wallet_api.dart b/cw_zano/lib/zano_wallet_api.dart index d4bcf9230..b88948bce 100644 --- a/cw_zano/lib/zano_wallet_api.dart +++ b/cw_zano/lib/zano_wallet_api.dart @@ -3,12 +3,12 @@ import 'dart:convert'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_zano/api/api_calls.dart'; import 'package:cw_zano/api/model/add_remove_assets_whitelist_params.dart'; -import 'package:cw_zano/api/model/asset_descriptor.dart'; import 'package:cw_zano/api/model/get_recent_txs_and_info_params.dart'; import 'package:cw_zano/api/model/get_wallet_info_result.dart'; import 'package:cw_zano/api/model/get_wallet_status_result.dart'; -import 'package:cw_zano/api/model/history.dart'; +import 'package:cw_zano/api/model/transfer.dart'; import 'package:cw_zano/zano_asset.dart'; +import 'package:flutter/foundation.dart'; import 'api/model/store_result.dart'; @@ -150,9 +150,10 @@ mixin ZanoWalletApi { } } - Future> getRecentTxsAndInfo() async { + Future> getRecentTxsAndInfo() async { try { final json = await invokeMethod('get_recent_txs_and_info', GetRecentTxsAndInfoParams(offset: 0, count: 30)); + debugPrint('get_recent_txs_and_info $json'); final map = jsonDecode(json) as Map?; _checkForErrors(map); final transfers = map?['result']?['result']?['transfers'] as List?; @@ -160,7 +161,7 @@ mixin ZanoWalletApi { print('get_recent_txs_and_info empty transfers'); return []; } - return transfers.map((e) => History.fromJson(e as Map)).toList(); + return transfers.map((e) => Transfer.fromJson(e as Map)).toList(); } catch (e) { print(e); return []; diff --git a/cw_zano/lib/zano_wallet_service.dart b/cw_zano/lib/zano_wallet_service.dart index b1d0f8b02..136a4b7f1 100644 --- a/cw_zano/lib/zano_wallet_service.dart +++ b/cw_zano/lib/zano_wallet_service.dart @@ -10,7 +10,6 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cw_zano/api/api_calls.dart' as calls; import 'package:cw_zano/api/api_calls.dart'; import 'package:cw_zano/api/consts.dart'; import 'package:cw_zano/api/exceptions/already_exists_exception.dart'; @@ -21,6 +20,7 @@ import 'package:cw_zano/api/model/create_wallet_result.dart'; import 'package:cw_zano/zano_asset.dart'; import 'package:cw_zano/zano_balance.dart'; import 'package:cw_zano/zano_wallet.dart'; +import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -71,8 +71,8 @@ class ZanoWalletService extends WalletService; + final json = ApiCalls.createWallet(language: '', path: path, password: credentials.password!); + final map = jsonDecode(json) as Map; _checkForCreateWalletError(map); final createWalletResult = CreateWalletResult.fromJson(map['result'] as Map); _parseCreateWalletResult(createWalletResult, wallet); @@ -111,9 +111,9 @@ class ZanoWalletService extends WalletService info.id == WalletBase.idFor(name, getType()))!; final wallet = ZanoWallet(walletInfo); await wallet.connectToNode(node: Node()); - final result = wallet.loadWallet(path, password); - print('load wallet result $result'); - final map = json.decode(result) as Map; + final json = wallet.loadWallet(path, password); + debugPrint('load wallet result $json'); + final map = jsonDecode(json) as Map; _checkForCreateWalletError(map); final createWalletResult = CreateWalletResult.fromJson(map['result'] as Map); _parseCreateWalletResult(createWalletResult, wallet); @@ -144,6 +144,7 @@ class ZanoWalletService extends WalletService; + final json = ApiCalls.restoreWalletFromSeed(path: path, password: credentials.password!, seed: credentials.mnemonic); + final map = jsonDecode(json) as Map; if (map['result'] != null) { final createWalletResult = CreateWalletResult.fromJson(map['result'] as Map); _parseCreateWalletResult(createWalletResult, wallet); diff --git a/cw_zano/pubspec.lock b/cw_zano/pubspec.lock index a13bbc5f4..4d22dcfb8 100644 --- a/cw_zano/pubspec.lock +++ b/cw_zano/pubspec.lock @@ -185,7 +185,7 @@ packages: source: hosted version: "2.2.4" decimal: - dependency: transitive + dependency: "direct main" description: name: decimal sha256: "24a261d5d5c87e86c7651c417a5dbdf8bcd7080dd592533910e8d0505a279f21" diff --git a/cw_zano/pubspec.yaml b/cw_zano/pubspec.yaml index a1e76d72e..b09080e48 100644 --- a/cw_zano/pubspec.yaml +++ b/cw_zano/pubspec.yaml @@ -18,6 +18,7 @@ dependencies: mobx: ^2.0.7+4 flutter_mobx: ^2.0.6+1 intl: ^0.18.0 + decimal: ^2.3.3 cw_core: path: ../cw_core diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index 277b977e2..f2a594474 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -116,7 +116,7 @@ class TransactionListItem extends ActionListItem with Keyable { ); break; case WalletType.zano: - final asset = zano!.assetOfTransaction(transaction); + final asset = zano!.assetOfTransaction(balanceViewModel.wallet, transaction); final price = balanceViewModel.fiatConvertationStore.prices[asset]; amount = calculateFiatAmountRaw( cryptoAmount: zano!.formatterMoneroAmountToDouble(amount: transaction.amount), diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 5651d2780..66c84ed1d 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -46,7 +46,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor void onWalletChange(wallet) { currencies = wallet.balance.keys.toList(); selectedCryptoCurrency = wallet.currency; - hasMultipleTokens = isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana; + hasMultipleTokens = isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana || wallet.type == WalletType.zano; } SendViewModelBase( @@ -60,7 +60,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor currencies = appStore.wallet!.balance.keys.toList(), selectedCryptoCurrency = appStore.wallet!.currency, hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type) || - appStore.wallet!.type == WalletType.solana, + appStore.wallet!.type == WalletType.solana || appStore.wallet!.type == WalletType.zano, outputs = ObservableList(), _settingsStore = appStore.settingsStore, fiatFromSettings = appStore.settingsStore.fiatCurrency, @@ -387,12 +387,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return solana! .createSolanaTransactionCredentials(outputs, currency: selectedCryptoCurrency); case WalletType.zano: - final priority = _settingsStore.priority[wallet.type]; - if (priority == null) { - throw Exception('Priority is null for wallet type: ${wallet.type}'); - } - return zano!.createZanoTransactionCreationCredentials( - outputs: outputs, priority: priority, assetType: selectedCryptoCurrency.title); + return zano!.createZanoTransactionCredentials( + outputs: outputs, priority: priority!, currency: selectedCryptoCurrency); default: throw Exception('Unexpected wallet type: ${wallet.type}'); } diff --git a/lib/zano/cw_zano.dart b/lib/zano/cw_zano.dart index 22e67309c..50b2d6632 100644 --- a/lib/zano/cw_zano.dart +++ b/lib/zano/cw_zano.dart @@ -80,21 +80,18 @@ class CWZano extends Zano { }*/ List getZanoAssets(WalletBase wallet) { - final zanoWallet = wallet as ZanoWallet; - return zanoWallet.zanoAssets; + wallet as ZanoWallet; + return wallet.zanoAssets; } @override - Future addZanoAssetById(WalletBase wallet, String assetId) async => - await (wallet as ZanoWallet).addZanoAssetById(assetId); + Future addZanoAssetById(WalletBase wallet, String assetId) async => await (wallet as ZanoWallet).addZanoAssetById(assetId); @override - Future addZanoAsset(WalletBase wallet, CryptoCurrency token) async => - await (wallet as ZanoWallet).addRemoveZanoAsset(token as ZanoAsset); + Future addZanoAsset(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).addRemoveZanoAsset(token as ZanoAsset); @override - Future deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async => - await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset); + Future deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset); @override Future getZanoAsset(WalletBase wallet, String assetId) async { @@ -136,12 +133,20 @@ class CWZano extends Zano { @override WalletCredentials createZanoRestoreWalletFromKeysCredentials( - {required String name, required String spendKey, required String viewKey, required String address, required String password, required String language, required int height}) { - return ZanoRestoreWalletFromKeysCredentials(name: name, spendKey: spendKey, viewKey: viewKey, address: address, password: password, language: language, height: height); + {required String name, + required String spendKey, + required String viewKey, + required String address, + required String password, + required String language, + required int height}) { + return ZanoRestoreWalletFromKeysCredentials( + name: name, spendKey: spendKey, viewKey: viewKey, address: address, password: password, language: language, height: height); } @override - WalletCredentials createZanoRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic}) { + WalletCredentials createZanoRestoreWalletFromSeedCredentials( + {required String name, required String password, required int height, required String mnemonic}) { return ZanoRestoreWalletFromSeedCredentials(name: name, password: password, height: height, mnemonic: mnemonic); } @@ -163,21 +168,22 @@ class CWZano extends Zano { } @override - Object createZanoTransactionCreationCredentials({required List outputs, required TransactionPriority priority, required String assetType}) { + Object createZanoTransactionCredentials({required List outputs, required TransactionPriority priority, required CryptoCurrency currency}) { return ZanoTransactionCredentials( - outputs: outputs - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as MoneroTransactionPriority, - assetType: assetType); + outputs: outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as MoneroTransactionPriority, + currency: currency, + ); } @override @@ -231,10 +237,13 @@ class CWZano extends Zano { // } @override - CryptoCurrency assetOfTransaction(TransactionInfo tx) { - final transaction = tx as ZanoTransactionInfo; - final asset = CryptoCurrency.fromString(transaction.assetType); - return asset; + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { + transaction as ZanoTransactionInfo; + if (transaction.tokenSymbol == CryptoCurrency.zano.title) { + return CryptoCurrency.zano; + } + wallet as ZanoWallet; + return wallet.zanoAssets.firstWhere((element) => element.ticker == transaction.tokenSymbol); } String getZanoAssetAddress(CryptoCurrency asset) => (asset as ZanoAsset).assetId; diff --git a/lib/zano/zano.dart b/lib/zano/zano.dart index e64c33c25..bd1c0a569 100644 --- a/lib/zano/zano.dart +++ b/lib/zano/zano.dart @@ -104,7 +104,7 @@ abstract class Zano { WalletCredentials createZanoRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic}); WalletCredentials createZanoNewWalletCredentials({required String name, String password}); Map getKeys(Object wallet); - Object createZanoTransactionCreationCredentials({required List outputs, required TransactionPriority priority, required String assetType}); + Object createZanoTransactionCredentials({required List outputs, required TransactionPriority priority, required CryptoCurrency currency}); String formatterMoneroAmountToString({required int amount}); double formatterMoneroAmountToDouble({required int amount}); int formatterMoneroParseAmount({required String amount}); @@ -113,7 +113,7 @@ abstract class Zano { void onStartup(); int getTransactionInfoAccountId(TransactionInfo tx); WalletService createZanoWalletService(Box walletInfoSource); - CryptoCurrency assetOfTransaction(TransactionInfo tx); + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo tx); List getZanoAssets(WalletBase wallet); String getZanoAssetAddress(CryptoCurrency asset); Future addZanoAsset(WalletBase wallet, CryptoCurrency token);