various epiccash tweaks and fixes

This commit is contained in:
julian 2024-01-09 14:43:58 -06:00
parent 68754e3329
commit c4a3874bf0
7 changed files with 167 additions and 216 deletions

View file

@ -155,6 +155,10 @@ class TransactionV2 {
}
if (isEpiccashTransaction) {
if (slateId == null) {
return "Restored Funds";
}
if (isCancelled) {
return "Cancelled";
} else if (type == TransactionType.incoming) {

View file

@ -10,6 +10,7 @@
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
@ -50,6 +51,8 @@ import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
@ -202,6 +205,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
mnemonic = mnemonic.trim();
int height = 0;
String? otherDataJsonString;
if (widget.coin == Coin.monero) {
height = monero.getHeigthByDate(date: widget.restoreFromDate);
@ -228,6 +232,22 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
if (height < 0) {
height = 0;
}
otherDataJsonString = jsonEncode(
{
WalletInfoKeys.epiccashData: jsonEncode(
ExtraEpiccashWalletInfo(
receivingIndex: 0,
changeIndex: 0,
slatesToAddresses: {},
slatesToCommits: {},
lastScannedBlock: height,
restoreHeight: height,
creationHeight: height,
).toMap(),
),
},
);
}
// TODO: do actual check to make sure it is a valid mnemonic for monero
@ -244,6 +264,8 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
final info = WalletInfo.createNew(
coin: widget.coin,
name: widget.walletName,
restoreHeight: height,
otherDataJsonString: otherDataJsonString,
);
bool isRestoring = true;
@ -292,7 +314,12 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
mnemonic: mnemonic,
);
await wallet.init();
if (wallet is EpiccashWallet) {
await wallet.init(isRestore: true);
} else {
await wallet.init();
}
await wallet.recover(isRescan: false);
// check if state is still active before continuing

View file

@ -110,7 +110,25 @@ class _TransactionV2DetailsViewState
unit = coin.ticker;
if (_transaction.subType == TransactionSubType.cashFusion) {
if (_transaction.isEpiccashTransaction) {
switch (_transaction.type) {
case TransactionType.outgoing:
case TransactionType.unknown:
amount = _transaction.getAmountSentFromThisWallet(coin: coin);
break;
case TransactionType.incoming:
case TransactionType.sentToSelf:
amount = _transaction.getAmountReceivedInThisWallet(coin: coin);
break;
}
data = _transaction.outputs
.map((e) => (
addresses: e.addresses,
amount: Amount(rawValue: e.value, fractionDigits: coin.decimals)
))
.toList();
} else if (_transaction.subType == TransactionSubType.cashFusion) {
amount = _transaction.getAmountReceivedInThisWallet(coin: coin);
data = _transaction.outputs
.where((e) => e.walletOwns)

View file

@ -1,122 +0,0 @@
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import 'package:stackwallet/db/hive/db.dart';
mixin EpicCashHive {
late final String _walletId;
void initEpicCashHive(String walletId) {
_walletId = walletId;
}
// receiving index
int? epicGetReceivingIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "receivingIndex")
as int?;
}
Future<void> epicUpdateReceivingIndex(int index) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "receivingIndex",
value: index,
);
}
// change index
int? epicGetChangeIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "changeIndex")
as int?;
}
Future<void> epicUpdateChangeIndex(int index) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "changeIndex",
value: index,
);
}
// slateToAddresses
Map epicGetSlatesToAddresses() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: "slate_to_address",
) as Map? ??
{};
}
Future<void> epicUpdateSlatesToAddresses(Map map) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "slate_to_address",
value: map,
);
}
// slatesToCommits
Map? epicGetSlatesToCommits() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: "slatesToCommits",
) as Map?;
}
Future<void> epicUpdateSlatesToCommits(Map map) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "slatesToCommits",
value: map,
);
}
// last scanned block
int? epicGetLastScannedBlock() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "lastScannedBlock")
as int?;
}
Future<void> epicUpdateLastScannedBlock(int blockHeight) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "lastScannedBlock",
value: blockHeight,
);
}
// epic restore height
int? epicGetRestoreHeight() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "restoreHeight")
as int?;
}
Future<void> epicUpdateRestoreHeight(int height) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "restoreHeight",
value: height,
);
}
// epic creation height
int? epicGetCreationHeight() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "creationHeight")
as int?;
}
Future<void> epicUpdateCreationHeight(int height) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "creationHeight",
value: height,
);
}
}

View file

@ -259,7 +259,6 @@ abstract class Constants {
case Coin.litecoinTestNet:
case Coin.firo:
case Coin.firoTestNet:
case Coin.epicCash:
case Coin.namecoin:
case Coin.particl:
case Coin.ethereum:
@ -270,6 +269,7 @@ abstract class Constants {
case Coin.nano:
case Coin.banano:
case Coin.epicCash:
case Coin.stellar:
case Coin.stellarTestnet:
case Coin.tezos:

View file

@ -353,7 +353,6 @@ class WalletInfo implements IsarId {
int favouriteOrderIndex = -1,
int cachedChainHeight = 0,
int restoreHeight = 0,
bool isMnemonicVerified = false,
String? cachedBalanceString,
String? cachedBalanceSecondaryString,
String? cachedBalanceTertiaryString,

View file

@ -501,79 +501,87 @@ class EpiccashWallet extends Bip39Wallet {
FilterGroup.and(standardReceivingAddressFilters);
@override
Future<void> init() async {
String? encodedWallet =
await secureStorageInterface.read(key: "${walletId}_wallet");
Future<void> init({bool? isRestore}) async {
if (isRestore != true) {
String? encodedWallet =
await secureStorageInterface.read(key: "${walletId}_wallet");
// check if should create a new wallet
if (encodedWallet == null) {
await updateNode();
final mnemonicString = await getMnemonic();
// check if should create a new wallet
if (encodedWallet == null) {
await updateNode();
final mnemonicString = await getMnemonic();
final String password = generatePassword();
final String stringConfig = await _getConfig();
final EpicBoxConfigModel epicboxConfig = await getEpicBoxConfig();
final String password = generatePassword();
final String stringConfig = await _getConfig();
final EpicBoxConfigModel epicboxConfig = await getEpicBoxConfig();
await secureStorageInterface.write(
key: '${walletId}_config', value: stringConfig);
await secureStorageInterface.write(
key: '${walletId}_password', value: password);
await secureStorageInterface.write(
key: '${walletId}_epicboxConfig', value: epicboxConfig.toString());
await secureStorageInterface.write(
key: '${walletId}_config', value: stringConfig);
await secureStorageInterface.write(
key: '${walletId}_password', value: password);
await secureStorageInterface.write(
key: '${walletId}_epicboxConfig', value: epicboxConfig.toString());
String name = walletId;
String name = walletId;
await epiccash.LibEpiccash.initializeNewWallet(
config: stringConfig,
mnemonic: mnemonicString,
password: password,
name: name,
);
await epiccash.LibEpiccash.initializeNewWallet(
config: stringConfig,
mnemonic: mnemonicString,
password: password,
name: name,
);
//Open wallet
encodedWallet = await epiccash.LibEpiccash.openWallet(
config: stringConfig, password: password);
await secureStorageInterface.write(
key: '${walletId}_wallet', value: encodedWallet);
//Open wallet
encodedWallet = await epiccash.LibEpiccash.openWallet(
config: stringConfig,
password: password,
);
await secureStorageInterface.write(
key: '${walletId}_wallet',
value: encodedWallet,
);
//Store Epic box address info
await _generateAndStoreReceivingAddressForIndex(0);
//Store Epic box address info
await _generateAndStoreReceivingAddressForIndex(0);
// subtract a couple days to ensure we have a buffer for SWB
final bufferedCreateHeight = _calculateRestoreHeightFrom(
date: DateTime.now().subtract(const Duration(days: 2)));
// subtract a couple days to ensure we have a buffer for SWB
final bufferedCreateHeight = _calculateRestoreHeightFrom(
date: DateTime.now().subtract(const Duration(days: 2)));
final epicData = ExtraEpiccashWalletInfo(
receivingIndex: 0,
changeIndex: 0,
slatesToAddresses: {},
slatesToCommits: {},
lastScannedBlock: bufferedCreateHeight,
restoreHeight: bufferedCreateHeight,
creationHeight: bufferedCreateHeight,
);
final epicData = ExtraEpiccashWalletInfo(
receivingIndex: 0,
changeIndex: 0,
slatesToAddresses: {},
slatesToCommits: {},
lastScannedBlock: bufferedCreateHeight,
restoreHeight: bufferedCreateHeight,
creationHeight: bufferedCreateHeight,
);
await info.updateExtraEpiccashWalletInfo(
epicData: epicData,
isar: mainDB.isar,
);
} else {
Logging.instance.log(
"initializeExisting() ${cryptoCurrency.coin.prettyName} wallet",
level: LogLevel.Info);
await info.updateExtraEpiccashWalletInfo(
epicData: epicData,
isar: mainDB.isar,
);
} else {
Logging.instance.log(
"initializeExisting() ${cryptoCurrency.coin.prettyName} wallet",
level: LogLevel.Info);
final config = await _getRealConfig();
final password =
await secureStorageInterface.read(key: '${walletId}_password');
final config = await _getRealConfig();
final password =
await secureStorageInterface.read(key: '${walletId}_password');
final walletOpen = await epiccash.LibEpiccash.openWallet(
config: config, password: password!);
await secureStorageInterface.write(
key: '${walletId}_wallet', value: walletOpen);
final walletOpen = await epiccash.LibEpiccash.openWallet(
config: config,
password: password!,
);
await secureStorageInterface.write(
key: '${walletId}_wallet', value: walletOpen);
await updateNode();
await updateBalance();
// TODO: is there anything else that should be set up here whenever this wallet is first loaded again?
await updateNode();
await updateBalance();
// TODO: is there anything else that should be set up here whenever this wallet is first loaded again?
}
}
return await super.init();
@ -695,7 +703,7 @@ class EpiccashWallet extends Bip39Wallet {
isar: mainDB.isar,
);
await _startScans();
unawaited(_startScans());
} else {
await updateNode();
final String password = generatePassword();
@ -754,7 +762,7 @@ class EpiccashWallet extends Bip39Wallet {
}
});
await refresh();
unawaited(refresh());
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from electrumx_mixin recover(): $e\n$s",
@ -945,10 +953,9 @@ class EpiccashWallet extends Bip39Wallet {
for (final tx in transactions) {
// Logging.instance.log("tx: $tx", level: LogLevel.Info);
// unsure if needed
// final isIncoming =
// tx.txType == epic_models.TransactionType.TxReceived ||
// tx.txType == epic_models.TransactionType.TxReceivedCancelled;
final isIncoming =
tx.txType == epic_models.TransactionType.TxReceived ||
tx.txType == epic_models.TransactionType.TxReceivedCancelled;
final slateId = tx.txSlateId;
final commitId = slatesToCommits[slateId]?['commitId'] as String?;
final numberOfMessages = tx.messages?.messages.length;
@ -956,43 +963,57 @@ class EpiccashWallet extends Bip39Wallet {
final addressFrom = slatesToCommits[slateId]?["from"] as String?;
final addressTo = slatesToCommits[slateId]?["to"] as String?;
final credit = int.parse(tx.amountCredited);
final debit = int.parse(tx.amountDebited);
final fee = int.tryParse(tx.fee ?? "0") ?? 0;
// hack epic tx data into inputs and outputs
final List<OutputV2> outputs = [];
final List<InputV2> inputs = [];
// TODO: [prio=high] should addressFrom and addressTo be swapped??
final addressFromIsMine = myAddressesSet.contains(addressFrom);
final addressToIsMine = myAddressesSet.contains(addressTo);
outputs.add(
OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: "00",
valueStringSats: tx.amountCredited,
addresses: [if (addressFrom != null) addressFrom],
walletOwns: addressFromIsMine,
),
OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: "00",
valueStringSats: credit.toString(),
addresses: [
if (addressFrom != null) addressFrom,
],
walletOwns: true,
);
inputs.add(
InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: null,
sequence: null,
outpoint: null,
addresses: [if (addressTo != null) addressTo],
valueStringSats: tx.amountDebited,
witness: null,
innerRedeemScriptAsm: null,
coinbase: null,
walletOwns: addressToIsMine,
),
InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: null,
sequence: null,
outpoint: null,
addresses: [if (addressTo != null) addressTo],
valueStringSats: debit.toString(),
witness: null,
innerRedeemScriptAsm: null,
coinbase: null,
walletOwns: true,
);
final TransactionType txType;
if (addressFromIsMine && addressToIsMine) {
txType = TransactionType.sentToSelf;
} else if (addressFromIsMine) {
txType = TransactionType.incoming;
if (isIncoming) {
if (addressToIsMine && addressFromIsMine) {
txType = TransactionType.sentToSelf;
} else {
txType = TransactionType.incoming;
}
output = output.copyWith(
addresses: [
myAddressesSet
.first, // Must be changed if we ever do more than a single wallet address!!!
],
walletOwns: true,
);
} else {
txType = TransactionType.outgoing;
}
outputs.add(output);
inputs.add(input);
final otherData = {
"isEpiccashTransaction": true,
"numberOfMessages": numberOfMessages,
@ -1001,6 +1022,10 @@ class EpiccashWallet extends Bip39Wallet {
"isCancelled":
tx.txType == epic_models.TransactionType.TxSentCancelled ||
tx.txType == epic_models.TransactionType.TxReceivedCancelled,
"anonFees": Amount(
rawValue: BigInt.from(fee),
fractionDigits: cryptoCurrency.fractionDigits,
).toJsonString(),
};
final txn = TransactionV2(