mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 01:37:54 +00:00
monero refactor with some fixes applied to wownero as well
This commit is contained in:
parent
4232ef8d8a
commit
f43ae8788d
11 changed files with 2469 additions and 1303 deletions
|
@ -500,7 +500,13 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
Constants.defaultSeedPhraseLengthFor(
|
||||
coin: info.coin,
|
||||
);
|
||||
if (wordCount > 0) {
|
||||
|
||||
if (coin == Coin.monero ||
|
||||
coin == Coin.wownero) {
|
||||
// currently a special case due to the
|
||||
// xmr/wow libraries handling their
|
||||
// own mnemonic generation
|
||||
} else if (wordCount > 0) {
|
||||
if (ref
|
||||
.read(pNewWalletOptions.state)
|
||||
.state !=
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart';
|
||||
|
@ -79,8 +81,8 @@ class CoinWalletsTable extends ConsumerWidget {
|
|||
ref.read(pWallets).getWallet(walletIds[i]);
|
||||
if (wallet.info.coin == Coin.monero ||
|
||||
wallet.info.coin == Coin.wownero) {
|
||||
// TODO: this can cause ui lag
|
||||
await wallet.init();
|
||||
// TODO: this can cause ui lag if awaited
|
||||
unawaited(wallet.init());
|
||||
}
|
||||
|
||||
await Navigator.of(context).pushNamed(
|
||||
|
|
|
@ -16,7 +16,6 @@ import 'package:stackwallet/models/node_model.dart';
|
|||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/particl/particl_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/stellar/stellar_wallet.dart';
|
||||
|
@ -120,13 +119,7 @@ abstract class CoinServiceAPI {
|
|||
);
|
||||
|
||||
case Coin.monero:
|
||||
return MoneroWallet(
|
||||
walletId: walletId,
|
||||
walletName: walletName,
|
||||
coin: coin,
|
||||
secureStorage: secureStorageInterface,
|
||||
// tracker: tracker,
|
||||
);
|
||||
throw UnimplementedError("moved");
|
||||
|
||||
case Coin.particl:
|
||||
return ParticlWallet(
|
||||
|
|
File diff suppressed because it is too large
Load diff
47
lib/wallets/crypto_currency/coins/monero.dart
Normal file
47
lib/wallets/crypto_currency/coins/monero.dart
Normal file
|
@ -0,0 +1,47 @@
|
|||
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/intermediate/cryptonote_currency.dart';
|
||||
|
||||
class Monero extends CryptonoteCurrency {
|
||||
Monero(super.network) {
|
||||
switch (network) {
|
||||
case CryptoCurrencyNetwork.main:
|
||||
coin = Coin.monero;
|
||||
default:
|
||||
throw Exception("Unsupported network: $network");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get minConfirms => 10;
|
||||
|
||||
@override
|
||||
bool validateAddress(String address) {
|
||||
return monero_wallet.validateAddress(address);
|
||||
}
|
||||
|
||||
@override
|
||||
NodeModel get defaultNode {
|
||||
switch (network) {
|
||||
case CryptoCurrencyNetwork.main:
|
||||
return NodeModel(
|
||||
host: "https://monero.stackwallet.com",
|
||||
port: 18081,
|
||||
name: DefaultNodes.defaultName,
|
||||
id: DefaultNodes.buildId(Coin.monero),
|
||||
useSSL: true,
|
||||
enabled: true,
|
||||
coinName: Coin.monero.name,
|
||||
isFailover: true,
|
||||
isDown: false,
|
||||
trusted: true,
|
||||
);
|
||||
|
||||
default:
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -286,7 +286,7 @@ class WalletInfo implements IsarId {
|
|||
}
|
||||
}
|
||||
|
||||
/// copies this with a new name and updates the db
|
||||
/// Can be dangerous. Don't use unless you know the consequences
|
||||
Future<void> setMnemonicVerified({
|
||||
required Isar isar,
|
||||
}) async {
|
||||
|
@ -294,7 +294,6 @@ class WalletInfo implements IsarId {
|
|||
await isar.walletInfoMeta.where().walletIdEqualTo(walletId).findFirst();
|
||||
if (meta == null) {
|
||||
await isar.writeTxn(() async {
|
||||
await isar.walletInfoMeta.deleteByWalletId(walletId);
|
||||
await isar.walletInfoMeta.put(
|
||||
WalletInfoMeta(
|
||||
walletId: walletId,
|
||||
|
@ -304,6 +303,7 @@ class WalletInfo implements IsarId {
|
|||
});
|
||||
} else if (meta.isMnemonicVerified == false) {
|
||||
await isar.writeTxn(() async {
|
||||
await isar.walletInfoMeta.deleteByWalletId(walletId);
|
||||
await isar.walletInfoMeta.put(
|
||||
WalletInfoMeta(
|
||||
walletId: walletId,
|
||||
|
@ -319,6 +319,26 @@ class WalletInfo implements IsarId {
|
|||
}
|
||||
}
|
||||
|
||||
/// copies this with a new name and updates the db
|
||||
Future<void> updateRestoreHeight({
|
||||
required int newRestoreHeight,
|
||||
required Isar isar,
|
||||
}) async {
|
||||
// don't allow empty names
|
||||
if (newRestoreHeight < 0) {
|
||||
throw Exception("Negative restore height not allowed!");
|
||||
}
|
||||
|
||||
// only update if there were changes to the name
|
||||
if (restoreHeight != newRestoreHeight) {
|
||||
_restoreHeight = newRestoreHeight;
|
||||
await isar.writeTxn(() async {
|
||||
await isar.walletInfo.deleteByWalletId(walletId);
|
||||
await isar.walletInfo.put(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
WalletInfo({
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cw_monero/pending_monero_transaction.dart';
|
||||
import 'package:cw_wownero/pending_wownero_transaction.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
|
@ -45,6 +46,9 @@ class TxData {
|
|||
// wownero specific
|
||||
final PendingWowneroTransaction? pendingWowneroTransaction;
|
||||
|
||||
// monero specific
|
||||
final PendingMoneroTransaction? pendingMoneroTransaction;
|
||||
|
||||
// firo lelantus specific
|
||||
final int? jMintValue;
|
||||
final List<int>? spendCoinIndexes;
|
||||
|
@ -91,6 +95,7 @@ class TxData {
|
|||
this.chainId,
|
||||
this.feeInWei,
|
||||
this.pendingWowneroTransaction,
|
||||
this.pendingMoneroTransaction,
|
||||
this.jMintValue,
|
||||
this.spendCoinIndexes,
|
||||
this.height,
|
||||
|
@ -165,6 +170,7 @@ class TxData {
|
|||
BigInt? chainId,
|
||||
BigInt? feeInWei,
|
||||
PendingWowneroTransaction? pendingWowneroTransaction,
|
||||
PendingMoneroTransaction? pendingMoneroTransaction,
|
||||
int? jMintValue,
|
||||
List<int>? spendCoinIndexes,
|
||||
int? height,
|
||||
|
@ -207,6 +213,8 @@ class TxData {
|
|||
feeInWei: feeInWei ?? this.feeInWei,
|
||||
pendingWowneroTransaction:
|
||||
pendingWowneroTransaction ?? this.pendingWowneroTransaction,
|
||||
pendingMoneroTransaction:
|
||||
pendingMoneroTransaction ?? this.pendingMoneroTransaction,
|
||||
jMintValue: jMintValue ?? this.jMintValue,
|
||||
spendCoinIndexes: spendCoinIndexes ?? this.spendCoinIndexes,
|
||||
height: height ?? this.height,
|
||||
|
@ -244,6 +252,7 @@ class TxData {
|
|||
'chainId: $chainId, '
|
||||
'feeInWei: $feeInWei, '
|
||||
'pendingWowneroTransaction: $pendingWowneroTransaction, '
|
||||
'pendingMoneroTransaction: $pendingMoneroTransaction, '
|
||||
'jMintValue: $jMintValue, '
|
||||
'spendCoinIndexes: $spendCoinIndexes, '
|
||||
'height: $height, '
|
||||
|
|
1040
lib/wallets/wallet/impl/monero_wallet.dart
Normal file
1040
lib/wallets/wallet/impl/monero_wallet.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -42,6 +42,7 @@ import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
|
|||
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/intermediate/cryptonote_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
|
@ -312,6 +313,7 @@ class WowneroWallet extends CryptonoteWallet with MultiAddressInterface {
|
|||
}
|
||||
cwWalletBase = (await cwWalletService!.openWallet(walletId, password))
|
||||
as WowneroWalletBase;
|
||||
unawaited(_start());
|
||||
} else {
|
||||
WalletInfo walletInfo;
|
||||
WalletCredentials credentials;
|
||||
|
@ -358,11 +360,21 @@ class WowneroWallet extends CryptonoteWallet with MultiAddressInterface {
|
|||
// 2))); // subtract a couple days to ensure we have a buffer for SWB
|
||||
final bufferedCreateHeight = getSeedHeightSync(wallet!.seed.trim());
|
||||
|
||||
// TODO: info.updateRestoreHeight
|
||||
await DB.instance.put<dynamic>(
|
||||
boxName: walletId,
|
||||
key: "restoreHeight",
|
||||
value: bufferedCreateHeight);
|
||||
await info.updateRestoreHeight(
|
||||
newRestoreHeight: bufferedCreateHeight,
|
||||
isar: mainDB.isar,
|
||||
);
|
||||
|
||||
// special case for xmr/wow. Normally mnemonic + passphrase is saved
|
||||
// before wallet.init() is called
|
||||
await secureStorageInterface.write(
|
||||
key: Wallet.mnemonicKey(walletId: walletId),
|
||||
value: wallet.seed.trim(),
|
||||
);
|
||||
await secureStorageInterface.write(
|
||||
key: Wallet.mnemonicPassphraseKey(walletId: walletId),
|
||||
value: "",
|
||||
);
|
||||
|
||||
walletInfo.restoreHeight = bufferedCreateHeight;
|
||||
|
||||
|
@ -372,6 +384,7 @@ class WowneroWallet extends CryptonoteWallet with MultiAddressInterface {
|
|||
|
||||
cwWalletBase?.close();
|
||||
cwWalletBase = wallet as WowneroWalletBase;
|
||||
unawaited(_start());
|
||||
} catch (e, s) {
|
||||
Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
|
||||
cwWalletBase?.close();
|
||||
|
@ -379,7 +392,7 @@ class WowneroWallet extends CryptonoteWallet with MultiAddressInterface {
|
|||
await updateNode();
|
||||
await cwWalletBase?.startSync();
|
||||
|
||||
cwWalletBase?.close();
|
||||
// cwWalletBase?.close();
|
||||
}
|
||||
|
||||
return super.init();
|
||||
|
@ -723,6 +736,31 @@ class WowneroWallet extends CryptonoteWallet with MultiAddressInterface {
|
|||
|
||||
// ====== private ============================================================
|
||||
|
||||
Future<void> _start() async {
|
||||
cwWalletBase?.onNewBlock = onNewBlock;
|
||||
cwWalletBase?.onNewTransaction = onNewTransaction;
|
||||
cwWalletBase?.syncStatusChanged = syncStatusChanged;
|
||||
|
||||
if (cwWalletBase != null && !(await cwWalletBase!.isConnected())) {
|
||||
final node = getCurrentNode();
|
||||
final host = Uri.parse(node.host).host;
|
||||
await cwWalletBase?.connectToNode(
|
||||
node: Node(
|
||||
uri: "$host:${node.port}",
|
||||
type: WalletType.monero,
|
||||
trusted: node.trusted ?? false,
|
||||
),
|
||||
);
|
||||
}
|
||||
await cwWalletBase?.startSync();
|
||||
unawaited(refresh());
|
||||
_autoSaveTimer?.cancel();
|
||||
_autoSaveTimer = Timer.periodic(
|
||||
const Duration(seconds: 193),
|
||||
(_) async => await cwWalletBase?.save(),
|
||||
);
|
||||
}
|
||||
|
||||
void onNewBlock({required int height, required int blocksLeft}) {
|
||||
_currentKnownChainHeight = height;
|
||||
updateChainHeight();
|
||||
|
@ -742,7 +780,7 @@ class WowneroWallet extends CryptonoteWallet with MultiAddressInterface {
|
|||
void syncStatusChanged() async {
|
||||
final syncStatus = cwWalletBase?.syncStatus;
|
||||
if (syncStatus != null) {
|
||||
if (syncStatus.progress() == 1) {
|
||||
if (syncStatus.progress() == 1 && refreshMutex.isLocked) {
|
||||
refreshMutex.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,13 @@ import 'package:stackwallet/wallets/wallet/impl/ecash_wallet.dart';
|
|||
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/litecoin_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/namecoin_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/nano_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/particl_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/tezos_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/intermediate/cryptonote_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/private_key_based_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart';
|
||||
|
@ -139,6 +141,10 @@ abstract class Wallet<T extends CryptoCurrency> {
|
|||
);
|
||||
|
||||
if (wallet is MnemonicInterface) {
|
||||
if (wallet is CryptonoteWallet) {
|
||||
// currently a special case due to the xmr/wow libraries handling their
|
||||
// own mnemonic generation
|
||||
} else {
|
||||
await secureStorageInterface.write(
|
||||
key: mnemonicKey(walletId: walletInfo.walletId),
|
||||
value: mnemonic!,
|
||||
|
@ -148,6 +154,7 @@ abstract class Wallet<T extends CryptoCurrency> {
|
|||
value: mnemonicPassphrase!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (wallet is PrivateKeyBasedWallet) {
|
||||
await secureStorageInterface.write(
|
||||
|
@ -281,6 +288,9 @@ abstract class Wallet<T extends CryptoCurrency> {
|
|||
case Coin.litecoinTestNet:
|
||||
return LitecoinWallet(CryptoCurrencyNetwork.test);
|
||||
|
||||
case Coin.monero:
|
||||
return MoneroWallet(CryptoCurrencyNetwork.main);
|
||||
|
||||
case Coin.namecoin:
|
||||
return NamecoinWallet(CryptoCurrencyNetwork.main);
|
||||
|
||||
|
|
|
@ -97,7 +97,8 @@ class SimpleWalletCard extends ConsumerWidget {
|
|||
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
if (wallet.info.coin == Coin.monero || wallet.info.coin == Coin.wownero) {
|
||||
await wallet.init();
|
||||
// TODO: this can cause ui lag if awaited
|
||||
unawaited(wallet.init());
|
||||
}
|
||||
if (context.mounted) {
|
||||
if (popPrevious) nav.pop();
|
||||
|
|
Loading…
Reference in a new issue