From 61f3135889d26a5fe5399890caa2c0ca27a48671 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 29 Nov 2022 13:41:47 -0600 Subject: [PATCH] port recent updates from bitcoin_wallet to particl_wallet --- .../coins/particl/particl_wallet.dart | 123 +++++++++++++----- 1 file changed, 92 insertions(+), 31 deletions(-) diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart index f35c13049..2392d82ad 100644 --- a/lib/services/coins/particl/particl_wallet.dart +++ b/lib/services/coins/particl/particl_wallet.dart @@ -10,8 +10,8 @@ import 'package:bitcoindart/bitcoindart.dart'; import 'package:bs58check/bs58check.dart' as bs58check; import 'package:crypto/crypto.dart'; import 'package:decimal/decimal.dart'; +import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:http/http.dart'; import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; @@ -194,20 +194,24 @@ class ParticlWallet extends CoinServiceAPI { Future get availableBalance async { final data = await utxoData; return Format.satoshisToAmount( - data.satoshiBalance - data.satoshiBalanceUnconfirmed); + data.satoshiBalance - data.satoshiBalanceUnconfirmed, + coin: coin); } @override Future get pendingBalance async { final data = await utxoData; - return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); + return Format.satoshisToAmount( + data.satoshiBalanceUnconfirmed, + coin: coin); } @override Future get balanceMinusMaxFee async => (await availableBalance) - - (Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) - .toDecimal(); + (Decimal.fromInt((await maxFee)) / + Decimal.fromInt(Constants.satsPerCoin(coin))) + .toDecimal(); @override Future get totalBalance async { @@ -216,13 +220,19 @@ class ParticlWallet extends CoinServiceAPI { .get(boxName: walletId, key: 'totalBalance') as int?; if (totalBalance == null) { final data = await utxoData; - return Format.satoshisToAmount(data.satoshiBalance); + return Format.satoshisToAmount( + data.satoshiBalance, + coin: coin); } else { - return Format.satoshisToAmount(totalBalance); + return Format.satoshisToAmount( + totalBalance, + coin: coin); } } final data = await utxoData; - return Format.satoshisToAmount(data.satoshiBalance); + return Format.satoshisToAmount( + data.satoshiBalance, + coin: coin); } @override @@ -260,7 +270,8 @@ class ParticlWallet extends CoinServiceAPI { @override Future get maxFee async { final fee = (await fees).fast as String; - final satsFee = Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin); + final satsFee = + Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin(coin)); return satsFee.floor().toBigInt().toInt(); } @@ -1083,7 +1094,8 @@ class ParticlWallet extends CoinServiceAPI { // check for send all bool isSendAll = false; - final balance = Format.decimalAmountToSatoshis(await availableBalance); + final balance = + Format.decimalAmountToSatoshis(await availableBalance, coin); if (satoshiAmount == balance) { isSendAll = true; } @@ -1273,6 +1285,55 @@ class ParticlWallet extends CoinServiceAPI { _transactionData ??= _fetchTransactionData(); Future? _transactionData; + TransactionData? cachedTxData; + + // TODO make sure this copied implementation from bitcoin_wallet.dart applies for particl just as well--or import it + // hack to add tx to txData before refresh completes + // required based on current app architecture where we don't properly store + // transactions locally in a good way + @override + Future updateSentCachedTxData(Map txData) async { + final priceData = + await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency); + Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero; + final locale = await Devicelocale.currentLocale; + final String worthNow = Format.localizedStringAsFixed( + value: + ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / + Decimal.fromInt(Constants.satsPerCoin(coin))) + .toDecimal(scaleOnInfinitePrecision: 2), + decimalPlaces: 2, + locale: locale!); + + final tx = models.Transaction( + txid: txData["txid"] as String, + confirmedStatus: false, + timestamp: DateTime.now().millisecondsSinceEpoch ~/ 1000, + txType: "Sent", + amount: txData["recipientAmt"] as int, + worthNow: worthNow, + worthAtBlockTimestamp: worthNow, + fees: txData["fee"] as int, + inputSize: 0, + outputSize: 0, + inputs: [], + outputs: [], + address: txData["address"] as String, + height: -1, + confirmations: 0, + ); + + if (cachedTxData == null) { + final data = await _fetchTransactionData(); + _transactionData = Future(() => data); + } + + final transactions = cachedTxData!.getAllTransactions(); + transactions[tx.txid] = tx; + cachedTxData = models.TransactionData.fromMap(transactions); + _transactionData = Future(() => cachedTxData!); + } + @override bool validateAddress(String address) { return Address.validateAddress(address, _network); @@ -1310,7 +1371,7 @@ class ParticlWallet extends CoinServiceAPI { required CachedElectrumX cachedClient, required TransactionNotificationTracker tracker, PriceAPI? priceAPI, - SecureStorageInterface? secureStore, + required SecureStorageInterface secureStore, }) { txTracker = tracker; _walletId = walletId; @@ -1320,13 +1381,12 @@ class ParticlWallet extends CoinServiceAPI { _cachedElectrumXClient = cachedClient; _priceAPI = priceAPI ?? PriceAPI(Client()); - _secureStore = - secureStore ?? const SecureStorageWrapper(FlutterSecureStorage()); + _secureStore = secureStore; } @override Future updateNode(bool shouldRefresh) async { - final failovers = NodeService() + final failovers = NodeService(secureStorageInterface: _secureStore) .failoverNodesFor(coin: coin) .map((e) => ElectrumXNode( address: e.host, @@ -1364,7 +1424,7 @@ class ParticlWallet extends CoinServiceAPI { } Future getCurrentNode() async { - final node = NodeService().getPrimaryNodeFor(coin: coin) ?? + final node = NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: coin) ?? DefaultNodes.getNodeFor(coin); return ElectrumXNode( @@ -1439,9 +1499,9 @@ class ParticlWallet extends CoinServiceAPI { numberOfBlocksFast: f, numberOfBlocksAverage: m, numberOfBlocksSlow: s, - fast: Format.decimalAmountToSatoshis(fast), - medium: Format.decimalAmountToSatoshis(medium), - slow: Format.decimalAmountToSatoshis(slow), + fast: Format.decimalAmountToSatoshis(fast, coin), + medium: Format.decimalAmountToSatoshis(medium, coin), + slow: Format.decimalAmountToSatoshis(slow, coin), ); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); @@ -1905,7 +1965,7 @@ class ParticlWallet extends CoinServiceAPI { utxo["status"]["block_time"] = txn["blocktime"]; final fiatValue = ((Decimal.fromInt(value) * currentPrice) / - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toDecimal(scaleOnInfinitePrecision: 2); utxo["rawWorth"] = fiatValue; utxo["fiatWorth"] = fiatValue.toString(); @@ -1914,16 +1974,17 @@ class ParticlWallet extends CoinServiceAPI { } Decimal currencyBalanceRaw = - ((Decimal.fromInt(satoshiBalance) * currentPrice) / - Decimal.fromInt(Constants.satsPerCoin)) - .toDecimal(scaleOnInfinitePrecision: 2); + ((Decimal.fromInt(satoshiBalance) * currentPrice) / + Decimal.fromInt(Constants.satsPerCoin(coin))) + .toDecimal(scaleOnInfinitePrecision: 2); final Map result = { "total_user_currency": currencyBalanceRaw.toString(), "total_sats": satoshiBalance, "total_btc": (Decimal.fromInt(satoshiBalance) / - Decimal.fromInt(Constants.satsPerCoin)) - .toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) + Decimal.fromInt(Constants.satsPerCoin(coin))) + .toDecimal( + scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin)) .toString(), "outputArray": outputArray, "unconfirmed": satoshiBalancePending, @@ -2469,7 +2530,7 @@ class ParticlWallet extends CoinServiceAPI { if (prevOut == out["n"]) { inputAmtSentFromWallet += (Decimal.parse(out["value"]!.toString()) * - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toBigInt() .toInt(); } @@ -2482,7 +2543,7 @@ class ParticlWallet extends CoinServiceAPI { final String address = output["scriptPubKey"]!["address"] as String; final value = output["value"]!; final _value = (Decimal.parse(value.toString()) * - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toBigInt() .toInt(); totalOutput += _value; @@ -2507,7 +2568,7 @@ class ParticlWallet extends CoinServiceAPI { final address = output["scriptPubKey"]["address"]; if (address != null) { final value = (Decimal.parse(output["value"].toString()) * - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toBigInt() .toInt(); totalOut += value; @@ -2530,7 +2591,7 @@ class ParticlWallet extends CoinServiceAPI { for (final out in tx["vout"] as List) { if (prevOut == out["n"]) { totalIn += (Decimal.parse(out["value"].toString()) * - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toBigInt() .toInt(); } @@ -2552,7 +2613,7 @@ class ParticlWallet extends CoinServiceAPI { midSortedTx["amount"] = inputAmtSentFromWallet; final String worthNow = ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toDecimal(scaleOnInfinitePrecision: 2) .toStringAsFixed(2); midSortedTx["worthNow"] = worthNow; @@ -2562,7 +2623,7 @@ class ParticlWallet extends CoinServiceAPI { midSortedTx["amount"] = outputAmtAddressedToWallet; final worthNow = ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / - Decimal.fromInt(Constants.satsPerCoin)) + Decimal.fromInt(Constants.satsPerCoin(coin))) .toDecimal(scaleOnInfinitePrecision: 2) .toStringAsFixed(2); midSortedTx["worthNow"] = worthNow; @@ -3689,7 +3750,7 @@ class ParticlWallet extends CoinServiceAPI { @override Future estimateFeeFor(int satoshiAmount, int feeRate) async { - final available = Format.decimalAmountToSatoshis(await availableBalance); + final available = Format.decimalAmountToSatoshis(await availableBalance, coin); if (available == satoshiAmount) { return satoshiAmount - sweepAllEstimate(feeRate);