balance fixes, sync status working, and transaction view working

This commit is contained in:
fossephate 2023-05-26 14:47:50 -04:00
parent e0efbe669d
commit 3586383f93
5 changed files with 119 additions and 46 deletions

View file

@ -123,7 +123,8 @@ enum AddressType {
mimbleWimble, mimbleWimble,
unknown, unknown,
nonWallet, nonWallet,
ethereum; ethereum,
nano;
String get readableName { String get readableName {
switch (this) { switch (this) {
@ -143,6 +144,8 @@ enum AddressType {
return "Non wallet/unknown"; return "Non wallet/unknown";
case AddressType.ethereum: case AddressType.ethereum:
return "Ethereum"; return "Ethereum";
case AddressType.nano:
return "Nano";
} }
} }
} }

View file

@ -261,6 +261,7 @@ const _AddresstypeEnumValueMap = {
'unknown': 5, 'unknown': 5,
'nonWallet': 6, 'nonWallet': 6,
'ethereum': 7, 'ethereum': 7,
'nano': 8,
}; };
const _AddresstypeValueEnumMap = { const _AddresstypeValueEnumMap = {
0: AddressType.p2pkh, 0: AddressType.p2pkh,
@ -271,6 +272,7 @@ const _AddresstypeValueEnumMap = {
5: AddressType.unknown, 5: AddressType.unknown,
6: AddressType.nonWallet, 6: AddressType.nonWallet,
7: AddressType.ethereum, 7: AddressType.ethereum,
8: AddressType.nano,
}; };
Id _addressGetId(Address object) { Id _addressGetId(Address object) {

View file

@ -9,6 +9,8 @@ import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/coin_control_interface.dart'; import 'package:stackwallet/services/mixins/coin_control_interface.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart';
@ -16,6 +18,7 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/log_level_enum.dart'; import 'package:stackwallet/utilities/enums/log_level_enum.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
import 'package:tuple/tuple.dart';
import '../../../db/isar/main_db.dart'; import '../../../db/isar/main_db.dart';
import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/address.dart';
@ -179,8 +182,8 @@ class NanoWallet extends CoinServiceAPI
headers: headers, headers: headers,
body: balanceBody, body: balanceBody,
); );
final balanceData = jsonDecode(balanceResponse.body); final balanceData = jsonDecode(balanceResponse.body);
final BigInt currentBalance = final BigInt currentBalance =
BigInt.parse(balanceData["balance"].toString()); BigInt.parse(balanceData["balance"].toString());
final BigInt txAmount = txData["recipientAmt"].raw as BigInt; final BigInt txAmount = txData["recipientAmt"].raw as BigInt;
@ -272,7 +275,8 @@ class NanoWallet extends CoinServiceAPI
@override @override
Future<Amount> estimateFeeFor(Amount amount, int feeRate) { Future<Amount> estimateFeeFor(Amount amount, int feeRate) {
// fees are always 0 :) // fees are always 0 :)
return Future.value(Amount(rawValue: BigInt.from(0), fractionDigits: 7)); return Future.value(
Amount(rawValue: BigInt.from(0), fractionDigits: coin.decimals));
} }
@override @override
@ -297,18 +301,17 @@ class NanoWallet extends CoinServiceAPI
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
_balance = Balance( _balance = Balance(
total: Amount( total: Amount(
rawValue: (BigInt.parse(data["balance"].toString())) ~/ rawValue: (BigInt.parse(data["balance"].toString()) +
BigInt.from(10).pow(23), BigInt.parse(data["receivable"].toString())),
fractionDigits: 7), fractionDigits: coin.decimals),
spendable: Amount( spendable: Amount(
rawValue: BigInt.parse(data["balance"].toString()) ~/ rawValue: BigInt.parse(data["balance"].toString()),
BigInt.from(10).pow(23), fractionDigits: coin.decimals),
fractionDigits: 7), blockedTotal:
blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: 30), Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals),
pendingSpendable: Amount( pendingSpendable: Amount(
rawValue: BigInt.parse(data["receivable"].toString()) ~/ rawValue: BigInt.parse(data["receivable"].toString()),
BigInt.from(10).pow(23), fractionDigits: coin.decimals),
fractionDigits: 7),
); );
await updateCachedBalance(_balance!); await updateCachedBalance(_balance!);
} }
@ -464,11 +467,12 @@ class NanoWallet extends CoinServiceAPI
Future<void> updateTransactions() async { Future<void> updateTransactions() async {
await confirmAllReceivable(); await confirmAllReceivable();
final String publicAddress = await getAddressFromMnemonic();
final response = await http.post(Uri.parse(getCurrentNode().host), final response = await http.post(Uri.parse(getCurrentNode().host),
headers: {"Content-Type": "application/json"}, headers: {"Content-Type": "application/json"},
body: jsonEncode({ body: jsonEncode({
"action": "account_history", "action": "account_history",
"account": await getAddressFromMnemonic(), "account": publicAddress,
"count": "-1", "count": "-1",
})); }));
final data = await jsonDecode(response.body); final data = await jsonDecode(response.body);
@ -476,14 +480,14 @@ class NanoWallet extends CoinServiceAPI
if (transactions.isEmpty) { if (transactions.isEmpty) {
return; return;
} else { } else {
List<Transaction> transactionList = []; List<Tuple2<Transaction, Address?>> transactionList = [];
for (var tx in transactions) { for (var tx in transactions) {
var typeString = tx["type"].toString(); var typeString = tx["type"].toString();
TransactionType type = TransactionType.unknown; TransactionType transactionType = TransactionType.unknown;
if (typeString == "send") { if (typeString == "send") {
type = TransactionType.outgoing; transactionType = TransactionType.outgoing;
} else if (typeString == "receive") { } else if (typeString == "receive") {
type = TransactionType.incoming; transactionType = TransactionType.incoming;
} }
final amount = Amount( final amount = Amount(
rawValue: BigInt.parse(tx["amount"].toString()), rawValue: BigInt.parse(tx["amount"].toString()),
@ -491,30 +495,45 @@ class NanoWallet extends CoinServiceAPI
); );
var transaction = Transaction( var transaction = Transaction(
walletId: walletId, walletId: walletId,
txid: tx["hash"].toString(), txid: tx["hash"].toString(),
timestamp: int.parse(tx["local_timestamp"].toString()), timestamp: int.parse(tx["local_timestamp"].toString()),
type: type, type: transactionType,
subType: TransactionSubType.none, subType: TransactionSubType.none,
amount: 0, amount: 0,
amountString: amount.toJsonString(), amountString: amount.toJsonString(),
fee: 0, fee: 0,
height: int.parse(tx["height"].toString()), height: int.parse(tx["height"].toString()),
isCancelled: false, isCancelled: false,
isLelantus: false, isLelantus: false,
slateId: "", slateId: "",
otherData: "", otherData: "",
inputs: [], inputs: [],
outputs: [], outputs: [],
nonce: 0); nonce: 0,
transactionList.add(transaction); );
}
try { Address address = Address(
await db.putTransactions(transactionList); walletId: walletId,
} catch (e) { publicKey: [],
// I don't know why this fails sometimes, but it does value: transactionType == TransactionType.incoming
print(e); ? publicAddress
: tx["account"].toString(),
derivationIndex: 0,
derivationPath: null,
type: transactionType == TransactionType.incoming
? AddressType.nonWallet
: AddressType.nano,
subType: transactionType == TransactionType.incoming
? AddressSubType.receiving
: AddressSubType.nonWallet,
);
Tuple2<Transaction, Address> tuple = Tuple2(transaction, address);
transactionList.add(tuple);
} }
await db.addNewTransactionData(transactionList, walletId);
return; return;
} }
} }
@ -523,8 +542,8 @@ class NanoWallet extends CoinServiceAPI
Future<void> fullRescan( Future<void> fullRescan(
int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) async { int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) async {
await _prefs.init(); await _prefs.init();
await updateBalance();
await updateTransactions(); await updateTransactions();
await updateBalance();
} }
@override @override
@ -686,8 +705,36 @@ class NanoWallet extends CoinServiceAPI
@override @override
Future<void> refresh() async { Future<void> refresh() async {
await _prefs.init(); await _prefs.init();
await updateBalance();
await updateTransactions(); GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.syncing,
walletId,
coin,
),
);
try {
await updateChainHeight();
await updateTransactions();
await updateBalance();
GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.synced,
walletId,
coin,
),
);
} catch (e) {
GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.unableToSync,
walletId,
coin,
),
);
}
} }
@override @override
@ -741,4 +788,25 @@ class NanoWallet extends CoinServiceAPI
bool validateAddress(String address) { bool validateAddress(String address) {
return NanoAccounts.isValid(NanoAccountType.NANO, address); return NanoAccounts.isValid(NanoAccountType.NANO, address);
} }
Future<void> updateChainHeight() async {
final String publicAddress = await getAddressFromMnemonic();
// first get the account balance:
final infoBody = jsonEncode({
"action": "account_info",
"account": publicAddress,
});
final headers = {
"Content-Type": "application/json",
};
final infoResponse = await http.post(
Uri.parse(getCurrentNode().host),
headers: headers,
body: infoBody,
);
final infoData = jsonDecode(infoResponse.body);
final int height = int.parse(infoData["confirmation_height"].toString());
await updateCachedChainHeight(height);
}
} }

View file

@ -90,7 +90,7 @@ class PriceAPI {
Uri.parse("https://api.coingecko.com/api/v3/coins/markets?vs_currency" Uri.parse("https://api.coingecko.com/api/v3/coins/markets?vs_currency"
"=${baseCurrency.toLowerCase()}" "=${baseCurrency.toLowerCase()}"
"&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin,"
"bitcoin-cash,namecoin,wownero,ethereum,particl" "bitcoin-cash,namecoin,wownero,ethereum,particl,nano"
"&order=market_cap_desc&per_page=50&page=1&sparkline=false"); "&order=market_cap_desc&per_page=50&page=1&sparkline=false");
final coinGeckoResponse = await client.get( final coinGeckoResponse = await client.get(

View file

@ -33,7 +33,7 @@ abstract class Constants {
BigInt.parse("1000000000000000000000000000000"); BigInt.parse("1000000000000000000000000000000");
static final BigInt _satsPerCoin = BigInt.from(100000000); static final BigInt _satsPerCoin = BigInt.from(100000000);
static const int _decimalPlaces = 8; static const int _decimalPlaces = 8;
static const int _decimalPlacesNano = 6; static const int _decimalPlacesNano = 30;
static const int _decimalPlacesWownero = 11; static const int _decimalPlacesWownero = 11;
static const int _decimalPlacesMonero = 12; static const int _decimalPlacesMonero = 12;
static const int _decimalPlacesEthereum = 18; static const int _decimalPlacesEthereum = 18;