mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-11 05:14:46 +00:00
tx history working and fiat fixes
This commit is contained in:
parent
9ebf74fa01
commit
d30de4dc3f
14 changed files with 492 additions and 119 deletions
|
@ -120,7 +120,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
|
||||||
static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png');
|
static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png');
|
||||||
static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/images/eth_icon.png');
|
static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/images/eth_icon.png');
|
||||||
static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/images/litecoin-ltc_icon.png');
|
static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/images/litecoin-ltc_icon.png');
|
||||||
static const nano = CryptoCurrency(title: 'NANO', raw: 10, name: 'nano', iconPath: 'assets/images/nano.png');
|
static const nano = CryptoCurrency(title: 'XNO', raw: 10, name: 'nano', iconPath: 'assets/images/nano.png');
|
||||||
static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/images/trx_icon.png');
|
static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/images/trx_icon.png');
|
||||||
static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'USDT Tether', raw: 12, name: 'usdt', iconPath: 'assets/images/usdt_icon.png');
|
static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'USDT Tether', raw: 12, name: 'usdt', iconPath: 'assets/images/usdt_icon.png');
|
||||||
static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'USDT Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/images/usdterc20_icon.png');
|
static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'USDT Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/images/usdterc20_icon.png');
|
||||||
|
|
|
@ -6,6 +6,10 @@ String rawToFormattedAmount(BigInt amount, Currency currency) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BigInt stringAmountToBigInt(String amount) {
|
||||||
|
return BigInt.zero;
|
||||||
|
}
|
||||||
|
|
||||||
class NanoBalance extends Balance {
|
class NanoBalance extends Balance {
|
||||||
final BigInt currentBalance;
|
final BigInt currentBalance;
|
||||||
final BigInt receivableBalance;
|
final BigInt receivableBalance;
|
||||||
|
@ -17,16 +21,19 @@ class NanoBalance extends Balance {
|
||||||
this.formattedReceivableBalance = "";
|
this.formattedReceivableBalance = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// NanoBalance.fromString(
|
NanoBalance.fromString(
|
||||||
// {required this.formattedCurrentBalance, required this.formattedReceivableBalance})
|
{required this.formattedCurrentBalance, required this.formattedReceivableBalance})
|
||||||
// : currentBalance = moneroParseAmount(amount: formattedCurrentBalance),
|
: currentBalance = stringAmountToBigInt(formattedCurrentBalance),
|
||||||
// receivableBalance = moneroParseAmount(amount: formattedReceivableBalance),
|
receivableBalance = stringAmountToBigInt(formattedReceivableBalance),
|
||||||
// super(moneroParseAmount(amount: formattedReceivableBalance),
|
super(0, 0);
|
||||||
// moneroParseAmount(amount: formattedCurrentBalance));
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get formattedAvailableBalance => "0";
|
String get formattedAvailableBalance {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get formattedAdditionalBalance => "0";
|
String get formattedAdditionalBalance {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
145
cw_nano/lib/nano_client.dart
Normal file
145
cw_nano/lib/nano_client.dart
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/erc20_token.dart';
|
||||||
|
import 'package:cw_nano/nano_balance.dart';
|
||||||
|
import 'package:cw_nano/nano_transaction_model.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:web3dart/web3dart.dart';
|
||||||
|
import 'package:web3dart/contracts/erc20.dart';
|
||||||
|
import 'package:cw_core/node.dart';
|
||||||
|
|
||||||
|
class NanoClient {
|
||||||
|
final _httpClient = Client();
|
||||||
|
StreamSubscription<Transfer>? subscription;
|
||||||
|
Node? _node;
|
||||||
|
|
||||||
|
bool connect(Node node) {
|
||||||
|
try {
|
||||||
|
_node = node;
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setListeners(EthereumAddress userAddress, Function(FilterEvent) onNewTransaction) async {}
|
||||||
|
|
||||||
|
Future<NanoBalance> getBalance(String address) async {
|
||||||
|
return NanoBalance(currentBalance: BigInt.zero, receivableBalance: BigInt.zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<PendingEthereumTransaction> signTransaction({
|
||||||
|
// required EthPrivateKey privateKey,
|
||||||
|
// required String toAddress,
|
||||||
|
// required String amount,
|
||||||
|
// required int gas,
|
||||||
|
// required EthereumTransactionPriority priority,
|
||||||
|
// required CryptoCurrency currency,
|
||||||
|
// required int exponent,
|
||||||
|
// String? contractAddress,
|
||||||
|
// }) async {
|
||||||
|
// assert(currency == CryptoCurrency.eth || contractAddress != null);
|
||||||
|
|
||||||
|
// bool _isEthereum = currency == CryptoCurrency.eth;
|
||||||
|
|
||||||
|
// final price = await _client!.getGasPrice();
|
||||||
|
|
||||||
|
// final Transaction transaction = Transaction(
|
||||||
|
// from: privateKey.address,
|
||||||
|
// to: EthereumAddress.fromHex(toAddress),
|
||||||
|
// maxGas: gas,
|
||||||
|
// gasPrice: price,
|
||||||
|
// value: _isEthereum ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// final signedTransaction = await _client!.signTransaction(privateKey, transaction);
|
||||||
|
|
||||||
|
// final BigInt estimatedGas;
|
||||||
|
// final Function _sendTransaction;
|
||||||
|
|
||||||
|
// if (_isEthereum) {
|
||||||
|
// estimatedGas = BigInt.from(21000);
|
||||||
|
// _sendTransaction = () async => await sendTransaction(signedTransaction);
|
||||||
|
// } else {
|
||||||
|
// estimatedGas = BigInt.from(50000);
|
||||||
|
|
||||||
|
// final erc20 = Erc20(
|
||||||
|
// client: _client!,
|
||||||
|
// address: EthereumAddress.fromHex(contractAddress!),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// _sendTransaction = () async {
|
||||||
|
// await erc20.transfer(
|
||||||
|
// EthereumAddress.fromHex(toAddress),
|
||||||
|
// BigInt.parse(amount),
|
||||||
|
// credentials: privateKey,
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return PendingEthereumTransaction(
|
||||||
|
// signedTransaction: signedTransaction,
|
||||||
|
// amount: amount,
|
||||||
|
// fee: estimatedGas * price.getInWei,
|
||||||
|
// sendTransaction: _sendTransaction,
|
||||||
|
// exponent: exponent,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
Future<dynamic> getTransactionDetails(String transactionHash) async {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
subscription?.cancel();
|
||||||
|
_httpClient?.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
|
||||||
|
try {
|
||||||
|
final response = await _httpClient.post(_node!.uri,
|
||||||
|
headers: {"Content-Type": "application/json"},
|
||||||
|
body: jsonEncode({
|
||||||
|
"action": "account_history",
|
||||||
|
"account": address,
|
||||||
|
"count": "250",// TODO: pick a number
|
||||||
|
// "raw": true,
|
||||||
|
}));
|
||||||
|
final data = await jsonDecode(response.body);
|
||||||
|
final transactions = data["history"] is List ? data["history"] as List<dynamic> : [];
|
||||||
|
|
||||||
|
// Map the transactions list to NanoTransactionModel using the factory
|
||||||
|
// reversed so that the DateTime is correct when local_timestamp is absent
|
||||||
|
return transactions.reversed
|
||||||
|
.map<NanoTransactionModel>(
|
||||||
|
(transaction) => NanoTransactionModel.fromJson(transaction as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<int> _getDecimalPlacesForContract(DeployedContract contract) async {
|
||||||
|
// final String abi = await rootBundle.loadString("assets/abi_json/erc20_abi.json");
|
||||||
|
// final contractAbi = ContractAbi.fromJson(abi, "ERC20");
|
||||||
|
//
|
||||||
|
// final contract = DeployedContract(
|
||||||
|
// contractAbi,
|
||||||
|
// EthereumAddress.fromHex(_erc20Currencies[erc20Currency]!),
|
||||||
|
// );
|
||||||
|
// final decimalsFunction = contract.function('decimals');
|
||||||
|
// final decimals = await _client!.call(
|
||||||
|
// contract: contract,
|
||||||
|
// function: decimalsFunction,
|
||||||
|
// params: [],
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// int exponent = int.parse(decimals.first.toString());
|
||||||
|
// return exponent;
|
||||||
|
// }
|
||||||
|
}
|
|
@ -1,28 +1,73 @@
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
import 'package:cw_nano/file.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_nano/nano_transaction_info.dart';
|
import 'package:cw_nano/nano_transaction_info.dart';
|
||||||
|
|
||||||
part 'nano_transaction_history.g.dart';
|
part 'nano_transaction_history.g.dart';
|
||||||
|
const transactionsHistoryFileName = 'transactions.json';
|
||||||
|
|
||||||
class NanoTransactionHistory = NanoTransactionHistoryBase
|
class NanoTransactionHistory = NanoTransactionHistoryBase with _$NanoTransactionHistory;
|
||||||
with _$NanoTransactionHistory;
|
|
||||||
|
|
||||||
abstract class NanoTransactionHistoryBase
|
abstract class NanoTransactionHistoryBase
|
||||||
extends TransactionHistoryBase<NanoTransactionInfo> with Store {
|
extends TransactionHistoryBase<NanoTransactionInfo> with Store {
|
||||||
NanoTransactionHistoryBase() {
|
NanoTransactionHistoryBase({required this.walletInfo, required String password})
|
||||||
|
: _password = password {
|
||||||
transactions = ObservableMap<String, NanoTransactionInfo>();
|
transactions = ObservableMap<String, NanoTransactionInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
final WalletInfo walletInfo;
|
||||||
Future<void> save() async {}
|
String _password;
|
||||||
|
|
||||||
|
Future<void> init() async => await _load();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void addOne(NanoTransactionInfo transaction) =>
|
Future<void> save() async {
|
||||||
transactions[transaction.id] = transaction;
|
try {
|
||||||
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
|
final data = json.encode({'transactions': transactions});
|
||||||
|
await writeData(path: path, password: _password, data: data);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error while save nano transaction history: ${e.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void addOne(NanoTransactionInfo transaction) => transactions[transaction.id] = transaction;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void addMany(Map<String, NanoTransactionInfo> transactions) =>
|
void addMany(Map<String, NanoTransactionInfo> transactions) =>
|
||||||
this.transactions.addAll(transactions);
|
this.transactions.addAll(transactions);
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> _read() async {
|
||||||
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
|
final content = await read(path: path, password: _password);
|
||||||
|
return json.decode(content) as Map<String, dynamic>;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _load() async {
|
||||||
|
try {
|
||||||
|
final content = await _read();
|
||||||
|
final txs = content['transactions'] as Map<String, dynamic>? ?? {};
|
||||||
|
|
||||||
|
txs.entries.forEach((entry) {
|
||||||
|
final val = entry.value;
|
||||||
|
|
||||||
|
if (val is Map<String, dynamic>) {
|
||||||
|
final tx = NanoTransactionInfo.fromJson(val);
|
||||||
|
_update(tx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _update(NanoTransactionInfo transaction) => transactions[transaction.id] = transaction;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,39 @@
|
||||||
import 'package:cw_core/transaction_info.dart';
|
|
||||||
import 'package:cw_core/monero_amount_format.dart';
|
|
||||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
|
||||||
import 'package:cw_core/parseBoolFromString.dart';
|
|
||||||
import 'package:cw_core/transaction_direction.dart';
|
|
||||||
import 'package:cw_core/format_amount.dart';
|
import 'package:cw_core/format_amount.dart';
|
||||||
import 'package:cw_monero/api/transaction_history.dart';
|
import 'package:cw_core/transaction_direction.dart';
|
||||||
|
import 'package:cw_core/transaction_info.dart';
|
||||||
|
import 'package:cw_nano/nano_util.dart';
|
||||||
|
|
||||||
class NanoTransactionInfo extends TransactionInfo {
|
class NanoTransactionInfo extends TransactionInfo {
|
||||||
NanoTransactionInfo(this.id, this.height, this.direction, this.date, this.isPending, this.amount,
|
NanoTransactionInfo({
|
||||||
this.accountIndex, this.addressIndex, this.amountRaw, this.confirmations);
|
required this.id,
|
||||||
|
required this.height,
|
||||||
// NanoTransactionInfo.fromMap(Map<String, Object?> map)
|
required this.amountRaw,
|
||||||
// : id = (map['hash'] ?? '') as String,
|
this.tokenSymbol = "XNO",
|
||||||
// height = (map['height'] ?? 0) as int,
|
required this.direction,
|
||||||
// direction = map['direction'] != null
|
required this.confirmed,
|
||||||
// ? parseTransactionDirectionFromNumber(map['direction'] as String)
|
required this.date,
|
||||||
// : TransactionDirection.incoming,
|
required this.confirmations,
|
||||||
// date = DateTime.fromMillisecondsSinceEpoch(
|
}) : this.amount = amountRaw.toInt();
|
||||||
// (int.tryParse(map['timestamp'] as String? ?? '') ?? 0) * 1000),
|
|
||||||
// isPending = parseBoolFromString(map['isPending'] as String),
|
|
||||||
// amount = map['amount'] as int,
|
|
||||||
// accountIndex = int.parse(map['accountIndex'] as String),
|
|
||||||
// addressIndex = map['addressIndex'] as int,
|
|
||||||
// confirmations = map['confirmations'] as int,
|
|
||||||
// key = getTxKey((map['hash'] ?? '') as String),
|
|
||||||
// fee = map['fee'] as int? ?? 0 {
|
|
||||||
// additionalInfo = <String, dynamic>{
|
|
||||||
// 'key': key,
|
|
||||||
// 'accountIndex': accountIndex,
|
|
||||||
// 'addressIndex': addressIndex
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// NanoTransactionInfo.fromRow(TransactionInfoRow row)
|
|
||||||
// : id = row.getHash(),
|
|
||||||
// height = row.blockHeight,
|
|
||||||
// direction = parseTransactionDirectionFromInt(row.direction),
|
|
||||||
// date = DateTime.fromMillisecondsSinceEpoch(row.getDatetime() * 1000),
|
|
||||||
// isPending = row.isPending != 0,
|
|
||||||
// amount = row.getAmount(),
|
|
||||||
// accountIndex = row.subaddrAccount,
|
|
||||||
// addressIndex = row.subaddrIndex,
|
|
||||||
// confirmations = row.confirmations,
|
|
||||||
// key = getTxKey(row.getHash()),
|
|
||||||
// fee = row.fee {
|
|
||||||
// additionalInfo = <String, dynamic>{
|
|
||||||
// 'key': key,
|
|
||||||
// 'accountIndex': accountIndex,
|
|
||||||
// 'addressIndex': addressIndex
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
final int height;
|
final int height;
|
||||||
final TransactionDirection direction;
|
|
||||||
final DateTime date;
|
|
||||||
final int accountIndex;
|
|
||||||
final bool isPending;
|
|
||||||
final int amount;
|
final int amount;
|
||||||
final BigInt amountRaw;
|
final BigInt amountRaw;
|
||||||
final int addressIndex;
|
final TransactionDirection direction;
|
||||||
|
final DateTime date;
|
||||||
|
final bool confirmed;
|
||||||
final int confirmations;
|
final int confirmations;
|
||||||
String? recipientAddress;
|
final String tokenSymbol;
|
||||||
String? key;
|
|
||||||
String? _fiatAmount;
|
String? _fiatAmount;
|
||||||
|
|
||||||
|
bool get isPending => !this.confirmed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String amountFormatted() => '${formatAmount(moneroAmountToString(amount: amount))} XNO';
|
String amountFormatted() {
|
||||||
|
final String amt = NanoUtil.getRawAsUsableString(amountRaw.toString(), NanoUtil.rawPerNano);
|
||||||
|
final String acc = NanoUtil.getRawAccuracy(amountRaw.toString(), NanoUtil.rawPerNano);
|
||||||
|
return "$acc$amt $tokenSymbol";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String fiatAmount() => _fiatAmount ?? '';
|
String fiatAmount() => _fiatAmount ?? '';
|
||||||
|
@ -75,5 +42,29 @@ class NanoTransactionInfo extends TransactionInfo {
|
||||||
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String feeFormatted() => '${formatAmount(moneroAmountToString(amount: 0))} XNO';
|
String feeFormatted() => "0 XNO";
|
||||||
|
|
||||||
|
factory NanoTransactionInfo.fromJson(Map<String, dynamic> data) {
|
||||||
|
return NanoTransactionInfo(
|
||||||
|
id: data['id'] as String,
|
||||||
|
height: data['height'] as int,
|
||||||
|
amountRaw: data['amountRaw'] as BigInt,
|
||||||
|
direction: parseTransactionDirectionFromInt(data['direction'] as int),
|
||||||
|
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
|
||||||
|
confirmed: data['confirmed'] as bool,
|
||||||
|
confirmations: data['confirmations'] as int,
|
||||||
|
tokenSymbol: data['tokenSymbol'] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'id': id,
|
||||||
|
'height': height,
|
||||||
|
'amountRaw': amountRaw,
|
||||||
|
'direction': direction.index,
|
||||||
|
'date': date.millisecondsSinceEpoch,
|
||||||
|
'confirmed': confirmed,
|
||||||
|
'confirmations': confirmations,
|
||||||
|
'tokenSymbol': tokenSymbol,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
39
cw_nano/lib/nano_transaction_model.dart
Normal file
39
cw_nano/lib/nano_transaction_model.dart
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
class NanoTransactionModel {
|
||||||
|
final DateTime? date;
|
||||||
|
final String hash;
|
||||||
|
final bool confirmed;
|
||||||
|
final String account;
|
||||||
|
final BigInt amount;
|
||||||
|
final int height;
|
||||||
|
final String type;
|
||||||
|
|
||||||
|
NanoTransactionModel({
|
||||||
|
this.date,
|
||||||
|
required this.hash,
|
||||||
|
required this.height,
|
||||||
|
required this.amount,
|
||||||
|
required this.confirmed,
|
||||||
|
required this.type,
|
||||||
|
required this.account,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory NanoTransactionModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
DateTime? local_timestamp;
|
||||||
|
try {
|
||||||
|
local_timestamp =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(int.parse(json["local_timeStamp"] as String) * 1000);
|
||||||
|
} catch (e) {
|
||||||
|
local_timestamp = DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NanoTransactionModel(
|
||||||
|
date: local_timestamp,
|
||||||
|
hash: json["hash"] as String,
|
||||||
|
height: int.parse(json["height"] as String),
|
||||||
|
type: json["type"] as String,
|
||||||
|
amount: BigInt.parse(json["amount"] as String),
|
||||||
|
account: json["account"] as String,
|
||||||
|
confirmed: (json["confirmed"] as String) == "true",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import 'package:libcrypto/libcrypto.dart';
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
import 'package:ed25519_hd_key/ed25519_hd_key.dart';
|
import 'package:ed25519_hd_key/ed25519_hd_key.dart';
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
|
import 'package:decimal/decimal.dart';
|
||||||
|
|
||||||
class NanoUtil {
|
class NanoUtil {
|
||||||
// standard:
|
// standard:
|
||||||
|
@ -120,4 +121,80 @@ class NanoUtil {
|
||||||
// Ensure seed only contains hex characters, 0-9;A-F
|
// Ensure seed only contains hex characters, 0-9;A-F
|
||||||
return NanoHelpers.isHexString(seed);
|
return NanoHelpers.isHexString(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// number util:
|
||||||
|
|
||||||
|
static const int maxDecimalDigits = 6; // Max digits after decimal
|
||||||
|
static BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000");
|
||||||
|
static BigInt rawPerNyano = BigInt.parse("1000000000000000000000000");
|
||||||
|
static BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000");
|
||||||
|
static BigInt rawPerXMR = BigInt.parse("1000000000000");
|
||||||
|
static BigInt convertXMRtoNano = BigInt.parse("1000000000000000000");
|
||||||
|
// static BigInt convertXMRtoNano = BigInt.parse("1000000000000000000000000000");
|
||||||
|
|
||||||
|
/// Convert raw to ban and return as BigDecimal
|
||||||
|
///
|
||||||
|
/// @param raw 100000000000000000000000000000
|
||||||
|
/// @return Decimal value 1.000000000000000000000000000000
|
||||||
|
///
|
||||||
|
static Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur) {
|
||||||
|
rawPerCur ??= rawPerNano;
|
||||||
|
final Decimal amount = Decimal.parse(raw.toString());
|
||||||
|
final Decimal result = (amount / Decimal.parse(rawPerCur.toString())).toDecimal();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String truncateDecimal(Decimal input, {int digits = maxDecimalDigits}) {
|
||||||
|
Decimal bigger = input.shift(digits);
|
||||||
|
bigger = bigger.floor(); // chop off the decimal: 1.059 -> 1.05
|
||||||
|
bigger = bigger.shift(-digits);
|
||||||
|
return bigger.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return raw as a NANO amount.
|
||||||
|
///
|
||||||
|
/// @param raw 100000000000000000000000000000
|
||||||
|
/// @returns 1
|
||||||
|
///
|
||||||
|
static String getRawAsUsableString(String? raw, BigInt rawPerCur) {
|
||||||
|
final String res =
|
||||||
|
truncateDecimal(getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9);
|
||||||
|
|
||||||
|
if (raw == null || raw == "0" || raw == "00000000000000000000000000000000") {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.contains(".")) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String numAmount = res.split(".")[0];
|
||||||
|
String decAmount = res.split(".")[1];
|
||||||
|
|
||||||
|
// truncate:
|
||||||
|
if (decAmount.length > maxDecimalDigits) {
|
||||||
|
decAmount = decAmount.substring(0, maxDecimalDigits);
|
||||||
|
// remove trailing zeros:
|
||||||
|
decAmount = decAmount.replaceAllMapped(RegExp(r'0+$'), (Match match) => '');
|
||||||
|
if (decAmount.isEmpty) {
|
||||||
|
return numAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "$numAmount.$decAmount";
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getRawAccuracy(String? raw, BigInt rawPerCur) {
|
||||||
|
final String rawString = getRawAsUsableString(raw, rawPerCur);
|
||||||
|
final String rawDecimalString = getRawAsDecimal(raw, rawPerCur).toString();
|
||||||
|
|
||||||
|
if (raw == null || raw.isEmpty || raw == "0") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawString != rawDecimalString) {
|
||||||
|
return "~";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,13 @@ import 'package:cw_core/node.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/pending_transaction.dart';
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
import 'package:cw_core/sync_status.dart';
|
import 'package:cw_core/sync_status.dart';
|
||||||
|
import 'package:cw_core/transaction_direction.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/wallet_addresses.dart';
|
import 'package:cw_core/wallet_addresses.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_nano/file.dart';
|
import 'package:cw_nano/file.dart';
|
||||||
import 'package:cw_nano/nano_balance.dart';
|
import 'package:cw_nano/nano_balance.dart';
|
||||||
|
import 'package:cw_nano/nano_client.dart';
|
||||||
import 'package:cw_nano/nano_transaction_history.dart';
|
import 'package:cw_nano/nano_transaction_history.dart';
|
||||||
import 'package:cw_nano/nano_transaction_info.dart';
|
import 'package:cw_nano/nano_transaction_info.dart';
|
||||||
import 'package:cw_nano/nano_util.dart';
|
import 'package:cw_nano/nano_util.dart';
|
||||||
|
@ -40,7 +42,7 @@ abstract class NanoWalletBase
|
||||||
_mnemonic = mnemonic,
|
_mnemonic = mnemonic,
|
||||||
_derivationType = derivationType,
|
_derivationType = derivationType,
|
||||||
_isTransactionUpdating = false,
|
_isTransactionUpdating = false,
|
||||||
_priorityFees = [],
|
_client = NanoClient(),
|
||||||
walletAddresses = NanoWalletAddresses(walletInfo),
|
walletAddresses = NanoWalletAddresses(walletInfo),
|
||||||
balance = ObservableMap<CryptoCurrency, NanoBalance>.of({
|
balance = ObservableMap<CryptoCurrency, NanoBalance>.of({
|
||||||
CryptoCurrency.nano: initialBalance ??
|
CryptoCurrency.nano: initialBalance ??
|
||||||
|
@ -48,7 +50,7 @@ abstract class NanoWalletBase
|
||||||
}),
|
}),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = NanoTransactionHistory();
|
transactionHistory = NanoTransactionHistory(walletInfo: walletInfo, password: password);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String _mnemonic;
|
final String _mnemonic;
|
||||||
|
@ -59,8 +61,7 @@ abstract class NanoWalletBase
|
||||||
late final String _publicAddress;
|
late final String _publicAddress;
|
||||||
late final String _seedKey;
|
late final String _seedKey;
|
||||||
|
|
||||||
List<int> _priorityFees;
|
late NanoClient _client;
|
||||||
int? _gasPrice;
|
|
||||||
bool _isTransactionUpdating;
|
bool _isTransactionUpdating;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -84,7 +85,7 @@ abstract class NanoWalletBase
|
||||||
this.walletInfo.address = _publicAddress;
|
this.walletInfo.address = _publicAddress;
|
||||||
|
|
||||||
await walletAddresses.init();
|
await walletAddresses.init();
|
||||||
// await transactionHistory.init();
|
await transactionHistory.init();
|
||||||
|
|
||||||
// walletAddresses.address = _privateKey.address.toString();
|
// walletAddresses.address = _privateKey.address.toString();
|
||||||
await save();
|
await save();
|
||||||
|
@ -103,14 +104,24 @@ abstract class NanoWalletBase
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void close() {
|
void close() {
|
||||||
// _client.stop();
|
_client.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
@override
|
@override
|
||||||
Future<void> connectToNode({required Node node}) async {
|
Future<void> connectToNode({required Node node}) async {
|
||||||
print("f");
|
try {
|
||||||
throw UnimplementedError();
|
syncStatus = ConnectingSyncStatus();
|
||||||
|
final isConnected = _client.connect(node);
|
||||||
|
if (!isConnected) {
|
||||||
|
throw Exception("Ethereum Node connection failed");
|
||||||
|
}
|
||||||
|
// _client.setListeners(_privateKey.address, _onNewTransaction);
|
||||||
|
_updateBalance();
|
||||||
|
syncStatus = ConnectedSyncStatus();
|
||||||
|
} catch (e) {
|
||||||
|
syncStatus = FailedSyncStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -120,14 +131,45 @@ abstract class NanoWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateTransactions() async {
|
Future<void> updateTransactions() async {
|
||||||
print("h");
|
print("updating_transactions");
|
||||||
throw UnimplementedError();
|
try {
|
||||||
|
if (_isTransactionUpdating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isTransactionUpdating = true;
|
||||||
|
final transactions = await fetchTransactions();
|
||||||
|
transactionHistory.addMany(transactions);
|
||||||
|
await transactionHistory.save();
|
||||||
|
_isTransactionUpdating = false;
|
||||||
|
} catch (_) {
|
||||||
|
_isTransactionUpdating = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, NanoTransactionInfo>> fetchTransactions() async {
|
Future<Map<String, NanoTransactionInfo>> fetchTransactions() async {
|
||||||
print("i");
|
String address = _publicAddress;
|
||||||
throw UnimplementedError();
|
|
||||||
|
final transactions = await _client.fetchTransactions(address);
|
||||||
|
|
||||||
|
final Map<String, NanoTransactionInfo> result = {};
|
||||||
|
|
||||||
|
for (var transactionModel in transactions) {
|
||||||
|
result[transactionModel.hash] = NanoTransactionInfo(
|
||||||
|
id: transactionModel.hash,
|
||||||
|
amountRaw: transactionModel.amount,
|
||||||
|
height: transactionModel.height,
|
||||||
|
direction: transactionModel.account == address
|
||||||
|
? TransactionDirection.outgoing
|
||||||
|
: TransactionDirection.incoming,
|
||||||
|
confirmed: transactionModel.confirmed,
|
||||||
|
date: transactionModel.date ?? DateTime.now(),
|
||||||
|
confirmations: transactionModel.confirmed ? 1 : 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -156,11 +198,15 @@ abstract class NanoWalletBase
|
||||||
@action
|
@action
|
||||||
@override
|
@override
|
||||||
Future<void> startSync() async {
|
Future<void> startSync() async {
|
||||||
throw UnimplementedError();
|
try {
|
||||||
}
|
syncStatus = AttemptingSyncStatus();
|
||||||
|
await _updateBalance();
|
||||||
|
await updateTransactions();
|
||||||
|
|
||||||
int feeRate(TransactionPriority priority) {
|
syncStatus = SyncedSyncStatus();
|
||||||
throw UnimplementedError();
|
} catch (e) {
|
||||||
|
syncStatus = FailedSyncStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||||
|
@ -177,16 +223,16 @@ abstract class NanoWalletBase
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
}) async {
|
}) async {
|
||||||
// TODO: finish
|
|
||||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await read(path: path, password: password);
|
||||||
final data = json.decode(jsonSource) as Map;
|
final data = json.decode(jsonSource) as Map;
|
||||||
final mnemonic = data['mnemonic'] as String;
|
final mnemonic = data['mnemonic'] as String;
|
||||||
final balance = /*NanoBalance.fromJSON(data['balance'] as String) ?? */
|
final balance = NanoBalance.fromString(
|
||||||
NanoBalance(currentBalance: BigInt.zero, receivableBalance: BigInt.zero);
|
formattedCurrentBalance: data['balance'] as String? ?? "0",
|
||||||
|
formattedReceivableBalance: "0");
|
||||||
|
|
||||||
DerivationType derivationType = DerivationType.bip39;
|
DerivationType derivationType = DerivationType.bip39;
|
||||||
if (data['derivationType'] == "nano") {
|
if (data['derivationType'] == "DerivationType.nano") {
|
||||||
derivationType = DerivationType.nano;
|
derivationType = DerivationType.nano;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,11 +249,6 @@ abstract class NanoWalletBase
|
||||||
await save();
|
await save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<EthPrivateKey> getPrivateKey(String mnemonic, String password) async {
|
|
||||||
print("o");
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void>? updateBalance() async => await _updateBalance();
|
Future<void>? updateBalance() async => await _updateBalance();
|
||||||
|
|
||||||
void _onNewTransaction(FilterEvent event) {
|
void _onNewTransaction(FilterEvent event) {
|
||||||
|
|
|
@ -208,6 +208,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.4"
|
version: "2.2.4"
|
||||||
|
decimal:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: decimal
|
||||||
|
sha256: "24a261d5d5c87e86c7651c417a5dbdf8bcd7080dd592533910e8d0505a279f21"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.3"
|
||||||
ed25519_hd_key:
|
ed25519_hd_key:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -586,6 +594,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.3"
|
version: "1.2.3"
|
||||||
|
rational:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: rational
|
||||||
|
sha256: ba58e9e18df9abde280e8b10051e4bce85091e41e8e7e411b6cde2e738d357cf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -17,6 +17,7 @@ dependencies:
|
||||||
bip39: ^1.0.6
|
bip39: ^1.0.6
|
||||||
bip32: ^2.0.0
|
bip32: ^2.0.0
|
||||||
nanodart: ^2.0.0
|
nanodart: ^2.0.0
|
||||||
|
decimal: ^2.3.3
|
||||||
libcrypto: ^0.2.2
|
libcrypto: ^0.2.2
|
||||||
ed25519_hd_key: ^2.2.0
|
ed25519_hd_key: ^2.2.0
|
||||||
hex: ^0.2.0
|
hex: ^0.2.0
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||||
import 'package:cake_wallet/haven/haven.dart';
|
import 'package:cake_wallet/haven/haven.dart';
|
||||||
import 'package:cake_wallet/monero/monero.dart';
|
import 'package:cake_wallet/monero/monero.dart';
|
||||||
|
import 'package:cake_wallet/nano/nano.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
|
@ -17,8 +18,11 @@ List<TransactionPriority> priorityForWalletType(WalletType type) {
|
||||||
return haven!.getTransactionPriorities();
|
return haven!.getTransactionPriorities();
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return ethereum!.getTransactionPriorities();
|
return ethereum!.getTransactionPriorities();
|
||||||
|
// we just get ethereum's here since there's no transaction priority in nano
|
||||||
|
// and so there's no point in bothering to implement it:
|
||||||
|
case WalletType.nano:
|
||||||
|
return ethereum!.getTransactionPriorities();
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||||
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
|
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
|
||||||
this.havenIcon = Image.asset('assets/images/haven_menu.png'),
|
this.havenIcon = Image.asset('assets/images/haven_menu.png'),
|
||||||
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
|
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
|
||||||
this.nanoIcon = Image.asset('assets/images/eth_icon.png'),
|
this.nanoIcon = Image.asset('assets/images/nano_icon.png'),
|
||||||
this.bananoIcon = Image.asset('assets/images/eth_icon.png');
|
this.bananoIcon = Image.asset('assets/images/nano_icon.png');
|
||||||
|
|
||||||
|
|
||||||
final largeScreen = 731;
|
final largeScreen = 731;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/nano/nano.dart';
|
||||||
import 'package:cw_core/transaction_direction.dart';
|
import 'package:cw_core/transaction_direction.dart';
|
||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
@ -13,12 +14,12 @@ import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
||||||
import 'package:cw_core/keyable.dart';
|
import 'package:cw_core/keyable.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:cw_nano/nano_transaction_info.dart';
|
||||||
|
import 'package:cw_nano/nano_util.dart';
|
||||||
|
|
||||||
class TransactionListItem extends ActionListItem with Keyable {
|
class TransactionListItem extends ActionListItem with Keyable {
|
||||||
TransactionListItem(
|
TransactionListItem(
|
||||||
{required this.transaction,
|
{required this.transaction, required this.balanceViewModel, required this.settingsStore});
|
||||||
required this.balanceViewModel,
|
|
||||||
required this.settingsStore});
|
|
||||||
|
|
||||||
final TransactionInfo transaction;
|
final TransactionInfo transaction;
|
||||||
final BalanceViewModel balanceViewModel;
|
final BalanceViewModel balanceViewModel;
|
||||||
|
@ -34,10 +35,9 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||||
dynamic get keyIndex => transaction.id;
|
dynamic get keyIndex => transaction.id;
|
||||||
|
|
||||||
String get formattedCryptoAmount {
|
String get formattedCryptoAmount {
|
||||||
return displayMode == BalanceDisplayMode.hiddenBalance
|
return displayMode == BalanceDisplayMode.hiddenBalance ? '---' : transaction.amountFormatted();
|
||||||
? '---'
|
|
||||||
: transaction.amountFormatted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String get formattedTitle {
|
String get formattedTitle {
|
||||||
if (transaction.direction == TransactionDirection.incoming) {
|
if (transaction.direction == TransactionDirection.incoming) {
|
||||||
return S.current.received;
|
return S.current.received;
|
||||||
|
@ -57,33 +57,33 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||||
if (transaction.direction == TransactionDirection.incoming) {
|
if (transaction.direction == TransactionDirection.incoming) {
|
||||||
if (balanceViewModel.wallet.type == WalletType.monero ||
|
if (balanceViewModel.wallet.type == WalletType.monero ||
|
||||||
balanceViewModel.wallet.type == WalletType.haven) {
|
balanceViewModel.wallet.type == WalletType.haven) {
|
||||||
return formattedPendingStatus;
|
return formattedPendingStatus;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return transaction.isPending ? S.current.pending : '';
|
|
||||||
}
|
}
|
||||||
|
return transaction.isPending ? S.current.pending : '';
|
||||||
|
}
|
||||||
|
|
||||||
String get formattedFiatAmount {
|
String get formattedFiatAmount {
|
||||||
var amount = '';
|
var amount = '';
|
||||||
|
|
||||||
switch(balanceViewModel.wallet.type) {
|
switch (balanceViewModel.wallet.type) {
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
amount = calculateFiatAmountRaw(
|
amount = calculateFiatAmountRaw(
|
||||||
cryptoAmount: monero!.formatterMoneroAmountToDouble(amount: transaction.amount),
|
cryptoAmount: monero!.formatterMoneroAmountToDouble(amount: transaction.amount),
|
||||||
price: price);
|
price: price);
|
||||||
break;
|
break;
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
amount = calculateFiatAmountRaw(
|
amount = calculateFiatAmountRaw(
|
||||||
cryptoAmount: bitcoin!.formatterBitcoinAmountToDouble(amount: transaction.amount),
|
cryptoAmount: bitcoin!.formatterBitcoinAmountToDouble(amount: transaction.amount),
|
||||||
price: price);
|
price: price);
|
||||||
break;
|
break;
|
||||||
case WalletType.haven:
|
case WalletType.haven:
|
||||||
final asset = haven!.assetOfTransaction(transaction);
|
final asset = haven!.assetOfTransaction(transaction);
|
||||||
final price = balanceViewModel.fiatConvertationStore.prices[asset];
|
final price = balanceViewModel.fiatConvertationStore.prices[asset];
|
||||||
amount = calculateFiatAmountRaw(
|
amount = calculateFiatAmountRaw(
|
||||||
cryptoAmount: haven!.formatterMoneroAmountToDouble(amount: transaction.amount),
|
cryptoAmount: haven!.formatterMoneroAmountToDouble(amount: transaction.amount),
|
||||||
price: price);
|
price: price);
|
||||||
break;
|
break;
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
final asset = ethereum!.assetOfTransaction(balanceViewModel.wallet, transaction);
|
final asset = ethereum!.assetOfTransaction(balanceViewModel.wallet, transaction);
|
||||||
|
@ -92,6 +92,14 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||||
cryptoAmount: ethereum!.formatterEthereumAmountToDouble(transaction: transaction),
|
cryptoAmount: ethereum!.formatterEthereumAmountToDouble(transaction: transaction),
|
||||||
price: price);
|
price: price);
|
||||||
break;
|
break;
|
||||||
|
case WalletType.nano:
|
||||||
|
final nanoTransaction = transaction as NanoTransactionInfo;
|
||||||
|
amount = calculateFiatAmountRaw(
|
||||||
|
cryptoAmount:
|
||||||
|
NanoUtil.getRawAsDecimal(nanoTransaction.amountRaw.toString(), NanoUtil.rawPerNano)
|
||||||
|
.toDouble(),
|
||||||
|
price: price);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,6 @@ class NanoURI extends PaymentURI {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
print(address);
|
|
||||||
var base = 'nano:' + address;
|
var base = 'nano:' + address;
|
||||||
|
|
||||||
if (amount.isNotEmpty) {
|
if (amount.isNotEmpty) {
|
||||||
|
|
Loading…
Reference in a new issue