port recent updates from bitcoin_wallet to particl_wallet

This commit is contained in:
sneurlax 2022-11-29 13:41:47 -06:00
parent 6c9690dcf5
commit 61f3135889

View file

@ -10,8 +10,8 @@ import 'package:bitcoindart/bitcoindart.dart';
import 'package:bs58check/bs58check.dart' as bs58check; import 'package:bs58check/bs58check.dart' as bs58check;
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:devicelocale/devicelocale.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart';
@ -194,20 +194,24 @@ class ParticlWallet extends CoinServiceAPI {
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount( return Format.satoshisToAmount(
data.satoshiBalance - data.satoshiBalanceUnconfirmed); data.satoshiBalance - data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get pendingBalance async { Future<Decimal> get pendingBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); return Format.satoshisToAmount(
data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
.toDecimal(); Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal();
@override @override
Future<Decimal> get totalBalance async { Future<Decimal> get totalBalance async {
@ -216,13 +220,19 @@ class ParticlWallet extends CoinServiceAPI {
.get<dynamic>(boxName: walletId, key: 'totalBalance') as int?; .get<dynamic>(boxName: walletId, key: 'totalBalance') as int?;
if (totalBalance == null) { if (totalBalance == null) {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(
data.satoshiBalance,
coin: coin);
} else { } else {
return Format.satoshisToAmount(totalBalance); return Format.satoshisToAmount(
totalBalance,
coin: coin);
} }
} }
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(
data.satoshiBalance,
coin: coin);
} }
@override @override
@ -260,7 +270,8 @@ class ParticlWallet extends CoinServiceAPI {
@override @override
Future<int> get maxFee async { Future<int> get maxFee async {
final fee = (await fees).fast as String; 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(); return satsFee.floor().toBigInt().toInt();
} }
@ -1083,7 +1094,8 @@ class ParticlWallet extends CoinServiceAPI {
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = Format.decimalAmountToSatoshis(await availableBalance); final balance =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1273,6 +1285,55 @@ class ParticlWallet extends CoinServiceAPI {
_transactionData ??= _fetchTransactionData(); _transactionData ??= _fetchTransactionData();
Future<TransactionData>? _transactionData; Future<TransactionData>? _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<void> updateSentCachedTxData(Map<String, dynamic> 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 @override
bool validateAddress(String address) { bool validateAddress(String address) {
return Address.validateAddress(address, _network); return Address.validateAddress(address, _network);
@ -1310,7 +1371,7 @@ class ParticlWallet extends CoinServiceAPI {
required CachedElectrumX cachedClient, required CachedElectrumX cachedClient,
required TransactionNotificationTracker tracker, required TransactionNotificationTracker tracker,
PriceAPI? priceAPI, PriceAPI? priceAPI,
SecureStorageInterface? secureStore, required SecureStorageInterface secureStore,
}) { }) {
txTracker = tracker; txTracker = tracker;
_walletId = walletId; _walletId = walletId;
@ -1320,13 +1381,12 @@ class ParticlWallet extends CoinServiceAPI {
_cachedElectrumXClient = cachedClient; _cachedElectrumXClient = cachedClient;
_priceAPI = priceAPI ?? PriceAPI(Client()); _priceAPI = priceAPI ?? PriceAPI(Client());
_secureStore = _secureStore = secureStore;
secureStore ?? const SecureStorageWrapper(FlutterSecureStorage());
} }
@override @override
Future<void> updateNode(bool shouldRefresh) async { Future<void> updateNode(bool shouldRefresh) async {
final failovers = NodeService() final failovers = NodeService(secureStorageInterface: _secureStore)
.failoverNodesFor(coin: coin) .failoverNodesFor(coin: coin)
.map((e) => ElectrumXNode( .map((e) => ElectrumXNode(
address: e.host, address: e.host,
@ -1364,7 +1424,7 @@ class ParticlWallet extends CoinServiceAPI {
} }
Future<ElectrumXNode> getCurrentNode() async { Future<ElectrumXNode> getCurrentNode() async {
final node = NodeService().getPrimaryNodeFor(coin: coin) ?? final node = NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: coin) ??
DefaultNodes.getNodeFor(coin); DefaultNodes.getNodeFor(coin);
return ElectrumXNode( return ElectrumXNode(
@ -1439,9 +1499,9 @@ class ParticlWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -1905,7 +1965,7 @@ class ParticlWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -1914,16 +1974,17 @@ class ParticlWallet extends CoinServiceAPI {
} }
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -2469,7 +2530,7 @@ class ParticlWallet extends CoinServiceAPI {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
inputAmtSentFromWallet += inputAmtSentFromWallet +=
(Decimal.parse(out["value"]!.toString()) * (Decimal.parse(out["value"]!.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2482,7 +2543,7 @@ class ParticlWallet extends CoinServiceAPI {
final String address = output["scriptPubKey"]!["address"] as String; final String address = output["scriptPubKey"]!["address"] as String;
final value = output["value"]!; final value = output["value"]!;
final _value = (Decimal.parse(value.toString()) * final _value = (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOutput += _value; totalOutput += _value;
@ -2507,7 +2568,7 @@ class ParticlWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["address"]; final address = output["scriptPubKey"]["address"];
if (address != null) { if (address != null) {
final value = (Decimal.parse(output["value"].toString()) * final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOut += value; totalOut += value;
@ -2530,7 +2591,7 @@ class ParticlWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) { for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
totalIn += (Decimal.parse(out["value"].toString()) * totalIn += (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2552,7 +2613,7 @@ class ParticlWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = final String worthNow =
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -2562,7 +2623,7 @@ class ParticlWallet extends CoinServiceAPI {
midSortedTx["amount"] = outputAmtAddressedToWallet; midSortedTx["amount"] = outputAmtAddressedToWallet;
final worthNow = final worthNow =
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -3689,7 +3750,7 @@ class ParticlWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
final available = Format.decimalAmountToSatoshis(await availableBalance); final available = Format.decimalAmountToSatoshis(await availableBalance, coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);