mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-03 17:40:43 +00:00
transfers in different assets
This commit is contained in:
parent
b2b6578972
commit
c74a114209
20 changed files with 211 additions and 186 deletions
|
@ -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;
|
||||
|
|
|
@ -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<String, dynamic> 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,
|
||||
// );
|
||||
|
||||
// }
|
|
@ -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<String, dynamic> 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? ?? '',
|
||||
);
|
||||
|
|
|
@ -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>? history;
|
||||
final List<Transfer>? history;
|
||||
final int lastItemIndex;
|
||||
final int totalHistoryItems;
|
||||
|
||||
|
@ -12,7 +12,7 @@ class RecentHistory {
|
|||
|
||||
factory RecentHistory.fromJson(Map<String, dynamic> json) => RecentHistory(
|
||||
history: json['history'] == null ? null : (json['history'] as List<dynamic>)
|
||||
.map((e) => History.fromJson(e as Map<String, dynamic>))
|
||||
.map((e) => Transfer.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
lastItemIndex: json['last_item_index'] as int? ?? 0,
|
||||
totalHistoryItems: json['total_history_items'] as int? ?? 0,
|
||||
|
|
|
@ -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<String, dynamic> json) => History(
|
||||
factory Transfer.fromJson(Map<String, dynamic> json) => Transfer(
|
||||
comment: json['comment'] as String? ?? '',
|
||||
employedEntries: EmployedEntries.fromJson(
|
||||
json['employed_entries'] as Map<String, dynamic>? ?? {}),
|
|
@ -2,7 +2,7 @@ import 'package:cw_zano/api/model/destination.dart';
|
|||
|
||||
class TransferParams {
|
||||
final List<Destination> 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<String, dynamic> json) => TransferParams(
|
||||
destinations: (json['destinations'] as List<dynamic>?)?.map((e) => Destination.fromJson(e as Map<String, dynamic>)).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? ?? '',
|
||||
|
|
|
@ -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<Destination> 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 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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<String, dynamic> 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';
|
||||
}
|
||||
|
|
24
cw_zano/lib/zano_formatter.dart
Normal file
24
cw_zano/lib/zano_formatter.dart
Normal file
|
@ -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))),
|
||||
),);
|
||||
}
|
|
@ -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<OutputInfo> outputs;
|
||||
final MoneroTransactionPriority priority;
|
||||
final String assetType;
|
||||
final CryptoCurrency currency;
|
||||
//final String assetType;
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
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 = history.subtransfers.first.amount,
|
||||
amount = transfer.subtransfers.first.amount,
|
||||
accountIndex = 0,
|
||||
addressIndex = 0,
|
||||
fee = history.fee,
|
||||
fee = transfer.fee,
|
||||
confirmations = 1,
|
||||
assetType = 'ZANO', // TODO: FIXIT:
|
||||
recipientAddress = history.remoteAddresses.isNotEmpty ? history.remoteAddresses.first : '';
|
||||
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';
|
||||
}
|
||||
|
|
|
@ -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<ZanoBalance, ZanoTransactionHistory, ZanoTransactionInfo> with Store, ZanoWalletApi {
|
||||
static const int _autoSaveInterval = 30;
|
||||
|
||||
List<History> history = [];
|
||||
List<Transfer> transfers = [];
|
||||
//String defaultAsssetId = '';
|
||||
@override
|
||||
ZanoWalletAddresses walletAddresses;
|
||||
|
@ -60,6 +61,7 @@ abstract class ZanoWalletBase extends WalletBase<ZanoBalance, ZanoTransactionHis
|
|||
@override
|
||||
ZanoWalletKeys keys = ZanoWalletKeys(privateSpendKey: '', privateViewKey: '', publicSpendKey: '', publicViewKey: '');
|
||||
|
||||
static const String zanoAssetId = 'd6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a';
|
||||
late final Box<ZanoAsset> zanoAssetsBox;
|
||||
List<ZanoAsset> get zanoAssets => zanoAssetsBox.values.toList();
|
||||
|
||||
|
@ -128,45 +130,64 @@ abstract class ZanoWalletBase extends WalletBase<ZanoBalance, ZanoTransactionHis
|
|||
|
||||
@override
|
||||
Future<PendingTransaction> 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<Destination> 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 {
|
||||
amount = output.formattedCryptoAmount!;
|
||||
totalAmount = unlockedBalanceCurrency;
|
||||
}
|
||||
if (amount + fee > unlockedBalance) {
|
||||
throw ZanoTransactionCreationException(
|
||||
"You don't have enough coins (required: ${moneroAmountToString(amount: amount + fee)}, unlocked ${moneroAmountToString(amount: unlockedBalance)}).");
|
||||
} else {
|
||||
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<ZanoBalance, ZanoTransactionHis
|
|||
destinations: destinations,
|
||||
fee: fee,
|
||||
comment: outputs.first.note ?? '',
|
||||
assetId: assetId,
|
||||
ticker: credentials.currency.title,
|
||||
amount: totalAmount,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, ZanoTransactionInfo>> fetchTransactions() async {
|
||||
try {
|
||||
await _refreshTransactions();
|
||||
return history.map<ZanoTransactionInfo>((history) => ZanoTransactionInfo.fromHistory(history)).fold<Map<String, ZanoTransactionInfo>>(
|
||||
<String, ZanoTransactionInfo>{},
|
||||
(Map<String, ZanoTransactionInfo> 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<ZanoBalance, ZanoTransactionHis
|
|||
_cachedBlockchainHeight = 0;
|
||||
_lastKnownBlockHeight = 0;
|
||||
_initialSyncHeight = 0;
|
||||
_updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: /*1200*/5000), (_) async {
|
||||
_updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: /*1200*/ 5000), (_) async {
|
||||
/*if (isNewTransactionExist()) {
|
||||
onNewTransaction?.call();
|
||||
}*/
|
||||
|
@ -468,14 +498,6 @@ abstract class ZanoWalletBase extends WalletBase<ZanoBalance, ZanoTransactionHis
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _refreshTransactions() async {
|
||||
try {
|
||||
history = await getRecentTxsAndInfo();
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void _updateSyncProgress(GetWalletStatusResult walletStatus) {
|
||||
final syncHeight = walletStatus.currentWalletHeight;
|
||||
if (_initialSyncHeight <= 0) {
|
||||
|
|
|
@ -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<List<History>> getRecentTxsAndInfo() async {
|
||||
Future<List<Transfer>> 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<String, dynamic>?;
|
||||
_checkForErrors(map);
|
||||
final transfers = map?['result']?['result']?['transfers'] as List<dynamic>?;
|
||||
|
@ -160,7 +161,7 @@ mixin ZanoWalletApi {
|
|||
print('get_recent_txs_and_info empty transfers');
|
||||
return [];
|
||||
}
|
||||
return transfers.map((e) => History.fromJson(e as Map<String, dynamic>)).toList();
|
||||
return transfers.map((e) => Transfer.fromJson(e as Map<String, dynamic>)).toList();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return [];
|
||||
|
|
|
@ -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<ZanoNewWalletCredentials, ZanoRest
|
|||
final wallet = ZanoWallet(credentials.walletInfo!);
|
||||
await wallet.connectToNode(node: Node());
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
final result = ApiCalls.createWallet(language: '', path: path, password: credentials.password!);
|
||||
final map = json.decode(result) as Map<String, dynamic>;
|
||||
final json = ApiCalls.createWallet(language: '', path: path, password: credentials.password!);
|
||||
final map = jsonDecode(json) as Map<String, dynamic>;
|
||||
_checkForCreateWalletError(map);
|
||||
final createWalletResult = CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
|
||||
_parseCreateWalletResult(createWalletResult, wallet);
|
||||
|
@ -111,9 +111,9 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials, ZanoRest
|
|||
final walletInfo = walletInfoSource.values.firstWhereOrNull((info) => 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<String, dynamic>;
|
||||
final json = wallet.loadWallet(path, password);
|
||||
debugPrint('load wallet result $json');
|
||||
final map = jsonDecode(json) as Map<String, dynamic>;
|
||||
_checkForCreateWalletError(map);
|
||||
final createWalletResult = CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
|
||||
_parseCreateWalletResult(createWalletResult, wallet);
|
||||
|
@ -144,6 +144,7 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials, ZanoRest
|
|||
wallet.walletAddresses.address = result.wi.address;
|
||||
for (final item in result.wi.balances) {
|
||||
if (item.assetInfo.ticker == 'ZANO') {
|
||||
//wallet.zanoAssetId = item.assetInfo.assetId;
|
||||
wallet.balance[CryptoCurrency.zano] = ZanoBalance(total: item.total, unlocked: item.unlocked);
|
||||
} else {
|
||||
for (final asset in wallet.balance.keys) {
|
||||
|
@ -154,7 +155,7 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials, ZanoRest
|
|||
}
|
||||
}
|
||||
if (result.recentHistory.history != null) {
|
||||
wallet.history = result.recentHistory.history!;
|
||||
wallet.transfers = result.recentHistory.history!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,8 +198,8 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials, ZanoRest
|
|||
final wallet = ZanoWallet(credentials.walletInfo!);
|
||||
await wallet.connectToNode(node: Node());
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
final result = ApiCalls.restoreWalletFromSeed(path: path, password: credentials.password!, seed: credentials.mnemonic);
|
||||
final map = json.decode(result) as Map<String, dynamic>;
|
||||
final json = ApiCalls.restoreWalletFromSeed(path: path, password: credentials.password!, seed: credentials.mnemonic);
|
||||
final map = jsonDecode(json) as Map<String, dynamic>;
|
||||
if (map['result'] != null) {
|
||||
final createWalletResult = CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
|
||||
_parseCreateWalletResult(createWalletResult, wallet);
|
||||
|
|
|
@ -185,7 +185,7 @@ packages:
|
|||
source: hosted
|
||||
version: "2.2.4"
|
||||
decimal:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: decimal
|
||||
sha256: "24a261d5d5c87e86c7651c417a5dbdf8bcd7080dd592533910e8d0505a279f21"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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<Output>(),
|
||||
_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}');
|
||||
}
|
||||
|
|
|
@ -80,21 +80,18 @@ class CWZano extends Zano {
|
|||
}*/
|
||||
|
||||
List<ZanoAsset> getZanoAssets(WalletBase wallet) {
|
||||
final zanoWallet = wallet as ZanoWallet;
|
||||
return zanoWallet.zanoAssets;
|
||||
wallet as ZanoWallet;
|
||||
return wallet.zanoAssets;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CryptoCurrency> addZanoAssetById(WalletBase wallet, String assetId) async =>
|
||||
await (wallet as ZanoWallet).addZanoAssetById(assetId);
|
||||
Future<CryptoCurrency> addZanoAssetById(WalletBase wallet, String assetId) async => await (wallet as ZanoWallet).addZanoAssetById(assetId);
|
||||
|
||||
@override
|
||||
Future<void> addZanoAsset(WalletBase wallet, CryptoCurrency token) async =>
|
||||
await (wallet as ZanoWallet).addRemoveZanoAsset(token as ZanoAsset);
|
||||
Future<void> addZanoAsset(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).addRemoveZanoAsset(token as ZanoAsset);
|
||||
|
||||
@override
|
||||
Future<void> deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async =>
|
||||
await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset);
|
||||
Future<void> deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset);
|
||||
|
||||
@override
|
||||
Future<ZanoAsset?> 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,7 +168,7 @@ class CWZano extends Zano {
|
|||
}
|
||||
|
||||
@override
|
||||
Object createZanoTransactionCreationCredentials({required List<Output> outputs, required TransactionPriority priority, required String assetType}) {
|
||||
Object createZanoTransactionCredentials({required List<Output> outputs, required TransactionPriority priority, required CryptoCurrency currency}) {
|
||||
return ZanoTransactionCredentials(
|
||||
outputs: outputs
|
||||
.map((out) => OutputInfo(
|
||||
|
@ -177,7 +182,8 @@ class CWZano extends Zano {
|
|||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as MoneroTransactionPriority,
|
||||
assetType: assetType);
|
||||
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;
|
||||
|
|
|
@ -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<String, String> getKeys(Object wallet);
|
||||
Object createZanoTransactionCreationCredentials({required List<Output> outputs, required TransactionPriority priority, required String assetType});
|
||||
Object createZanoTransactionCredentials({required List<Output> 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<WalletInfo> walletInfoSource);
|
||||
CryptoCurrency assetOfTransaction(TransactionInfo tx);
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo tx);
|
||||
List<ZanoAsset> getZanoAssets(WalletBase wallet);
|
||||
String getZanoAssetAddress(CryptoCurrency asset);
|
||||
Future<void> addZanoAsset(WalletBase wallet, CryptoCurrency token);
|
||||
|
|
Loading…
Reference in a new issue