Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cw_core/lib/wallet_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class WalletInfoAddressInfo {
required this.accountIndex,
required this.address,
required this.label,
this.txCount,
this.balance,
});

int id;
Expand All @@ -69,6 +71,8 @@ class WalletInfoAddressInfo {
int accountIndex;
String address;
String label;
int? txCount;
int? balance;

static String get tableName => 'walletInfoAddressInfo';

Expand Down
28 changes: 25 additions & 3 deletions cw_zcash/lib/src/zcash_taddress_rotation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ class ZcashTaddressRotation {
static Map<int, List<Account>> rotationAccounts = {};
static Map<int, List<Account>> rotationAccountsUsable = {};
static Map<int, List<ShieldedTx>> shieldedAccountsTx = {};
static final Map<String, int> addressBalances = {};
static final Map<String, int> addressTxCounts = {};

static void refreshAddressMetadata(final Account account) {
try {
final address = WarpApi.getTAddr(coin, account.id);
addressBalances[address] =
WarpApi.getPoolBalances(coin, account.id, 0, true).transparent;
addressTxCounts[address] = WarpApi.getTxsSync(coin, account.id).length;
} catch (e) {
printV("Failed to refresh metadata for Zcash account ${account.id}: $e");
}
}

static int? balanceForAddress(final String address) => addressBalances[address];

static int? txCountForAddress(final String address) => addressTxCounts[address];

static List<Account> accountsForAccount(final int accountId) =>
rotationAccounts[accountId]?.toList() ?? [];

static Future<void> init() async {
printV("Deserializing previous state");
if (_isStarted) {
Expand Down Expand Up @@ -416,21 +437,22 @@ class ZcashTaddressRotation {
for (int i = 0; i < acc.length; i++) {
final b = WarpApi.getBackup(coin, acc[i].id);
printV("$i. ${b.seed?.split(" ").last}, ${b.index}, ${WarpApi.getTAddr(coin, acc[i].id)}");
refreshAddressMetadata(acc[i]);
}
return acc.map((final a) => WarpApi.getTAddr(coin, a.id)).toList();
}

static List<String>? allUsedAddressesForAccount(final int accountId) {
final seed = WarpApi.getBackup(coin, accountId).seed;
if (seed == null) return [];
final acc = rotationAccounts[seed]?.toList();
final acc = rotationAccounts[accountId]?.toList();
if (acc == null) {
printV("Nothing found");
return null;
}
acc.removeWhere((final a1) {
for (int i = 0; i < (rotationAccountsUsable[seed]?.length ?? 0); i++) {
if (rotationAccountsUsable[seed]?[i].id == a1.id) {
for (int i = 0; i < (rotationAccountsUsable[accountId]?.length ?? 0); i++) {
if (rotationAccountsUsable[accountId]?[i].id == a1.id) {
return true;
}
}
Expand Down
14 changes: 10 additions & 4 deletions cw_zcash/lib/src/zcash_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -784,21 +784,27 @@ abstract class ZcashWalletBase

final confirmedPoolBalances = WarpApi.getPoolBalances(coin, accountId, 3, true);
final confirmedBalances = confirmedPoolBalances.unpack();
final confirmedTotal =
confirmedBalances.orchard + confirmedBalances.sapling + confirmedBalances.transparent;

int rotatedTransparentBalance = 0;
for (final account in ZcashTaddressRotation.accountsForAccount(accountId)) {
final accountBalances = WarpApi.getPoolBalances(coin, account.id, 0, true);
rotatedTransparentBalance += accountBalances.transparent;
ZcashTaddressRotation.refreshAddressMetadata(account);
}

int knownOutPending = 0;
ZcashWalletBase.temporarySentTx[accountId]?.forEach((final sTx) {
knownOutPending += sTx.value; // it's negative
});
final confirmedSpendable = confirmedTotal - balances.transparent + knownOutPending;
final confirmedSpendable =
confirmedBalances.orchard + confirmedBalances.sapling + knownOutPending;

unawaited(_autoShield());

balance[CryptoCurrency.zec] = ZcashBalance(
Money.fromInt(confirmedSpendable, currency),
Money.fromInt(spendable - confirmedSpendable, currency),
frozen: Money.zero(currency),
frozen: Money.fromInt(balances.transparent + rotatedTransparentBalance, currency),
);
} catch (e, stackTrace) {
printV("Balance update error: $e");
Expand Down
67 changes: 52 additions & 15 deletions cw_zcash/lib/src/zcash_wallet_addresses.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ abstract class ZcashWalletAddressesBase extends WalletAddresses with Store {

@override
bool containsAddress(final String address) {
return this.address == address || addressesMap.values.contains(address);
return this.address == address ||
addressesMap.values.contains(address) ||
addressInfos.values.any((final infos) {
return infos.any((final info) => info.address == address);
});
}

static int get coin => ZcashWalletBase.coin;
Expand All @@ -149,25 +153,42 @@ abstract class ZcashWalletAddressesBase extends WalletAddresses with Store {
address = latestAddress;
}

Map<String, String> _labelsByAddress() {
final labels = <String, String>{};
for (final infos in addressInfos.values) {
for (final info in infos) {
labels[info.address] = info.label;
}
}
return labels;
}

Map<int, List<WalletInfoAddressInfo>> _buildTransparentAddressInfos(
final Map<String, String> labels,
) {
int mapKey = 0;
final infos = ZcashTaddressRotation.accountsForAccount(accountId).map((final account) {
final address = WarpApi.getTAddr(coin, account.id);
ZcashTaddressRotation.refreshAddressMetadata(account);
return WalletInfoAddressInfo(
walletInfoId: walletInfo.internalId,
mapKey: ++mapKey,
accountIndex: account.id,
address: address,
label: labels[address] ?? "",
txCount: ZcashTaddressRotation.txCountForAddress(address),
balance: ZcashTaddressRotation.balanceForAddress(address),
);
}).toList();
return {0: infos};
}

@override
Future<void> init() async {
await _initAddresses();

await ZcashTaddressRotation.init();
int accountIndex = 0;
addressInfos = {
0:
ZcashTaddressRotation.allAddressesForAccount(accountId)?.map((final v) {
return WalletInfoAddressInfo(
walletInfoId: walletInfo.internalId,
mapKey: ++accountIndex,
accountIndex: 0,
address: v,
label: "",
);
}).toList() ??
[],
};
addressInfos = _buildTransparentAddressInfos(_labelsByAddress());
hiddenAddresses.addAll(
ZcashTaddressRotation.allUsedAddressesForAccount(accountId)?.toSet() ?? {},
);
Expand Down Expand Up @@ -227,8 +248,24 @@ abstract class ZcashWalletAddressesBase extends WalletAddresses with Store {
if (addressPageType != ZcashAddressType.transparentRotated) {
return [];
}
final knownAddresses = addressInfos.values
.expand((final infos) => infos)
.map((final info) => info.address)
.toSet();
final currentAddresses = ZcashTaddressRotation.accountsForAccount(accountId)
.map((final account) => WarpApi.getTAddr(coin, account.id))
.toSet();
if (knownAddresses.length != currentAddresses.length ||
!knownAddresses.containsAll(currentAddresses)) {
addressInfos = _buildTransparentAddressInfos(_labelsByAddress());
}

final List<WalletInfoAddressInfo> allInfos = [];
for (final entry in addressInfos.entries) {
for (final info in entry.value) {
info.txCount = ZcashTaddressRotation.txCountForAddress(info.address);
info.balance = ZcashTaddressRotation.balanceForAddress(info.address);
}
allInfos.addAll(entry.value);
}
return allInfos;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
return;
}

if (wallet.type == WalletType.zcash) {
for (final infos in wallet.walletAddresses.addressInfos.values) {
for (final info in infos) {
if (info.address == _item!.address) {
info.label = label;
}
}
}
await wallet.walletAddresses.saveAddressesInBox();
return;
}

final index = _item?.id;
if (index != null) {
if (wallet.type == WalletType.monero) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,17 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
if (wallet.type == WalletType.zcash) {
final addrInfos = zcash!.getAddressInfos(wallet);
addrInfos.forEach((info) {
addressList.add(
new WalletAddressListItem(isPrimary: false, address: info.address, name: info.label));
addressList.add(WalletAddressListItem(
id: info.mapKey,
isPrimary: false,
address: info.address,
name: info.label,
txCount: info.txCount,
balance: info.balance == null
? null
: _appStore.amountParsingProxy
.getDisplayCryptoString(info.balance!, walletTypeToCryptoCurrency(type)),
));
});
}

Expand Down Expand Up @@ -566,7 +575,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
String get monoImage => getChainMonoImage(type);

@computed
bool get isBalanceAvailable => isElectrumWallet;
bool get isBalanceAvailable =>
isElectrumWallet || (wallet.type == WalletType.zcash && isZCashTransparent);

@computed
bool get isReceivedAvailable => [WalletType.monero, WalletType.wownero].contains(wallet.type);
Expand Down