mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-02-02 03:06:29 +00:00
various epiccash tweaks and fixes
This commit is contained in:
parent
68754e3329
commit
c4a3874bf0
7 changed files with 167 additions and 216 deletions
|
@ -155,6 +155,10 @@ class TransactionV2 {
|
|||
}
|
||||
|
||||
if (isEpiccashTransaction) {
|
||||
if (slateId == null) {
|
||||
return "Restored Funds";
|
||||
}
|
||||
|
||||
if (isCancelled) {
|
||||
return "Cancelled";
|
||||
} else if (type == TransactionType.incoming) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue