mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-27 06:18:50 +01:00
CW-415 add coin control for xmr (#985)
* Added CoinsInfo to monero_api_cpp * Add struct on dart * Add struct on dart * Set coins value * CW-415 Use add-coin-to-monero branch * CW-415 Add get Coin and build Monero Deps using Docker * CW-415 Fix Typo * CW-415 add debug log info * CW-415 Add preferred key Images for coin control to Monero * CW-415 Fix generation * CW-415 Skip GA Cache Externals * CW-415 Skip GA Cache Externals * CW-415 Coin Control: remove Block Explorer for Monero, Add Tx hash, save note on field exit * CW-415 Coin Control: Throw Exception when all outputs are deselected * CW-415 Coin Control: Show Frozen Balance on Dashboard * CW-415 Coin Control: Show Frozen Balance on Dashboard * CW-415 Ignore cached Monero deps in Workflow * CW-415 Fix displaying frozen Balance * Use own Translator with http 1.1.0 * CW-415 Resolve requested Changes * CW-415 Resolve requested Changes * CW-415 Resolve requested Changes * CW-415 Apply requested Changes * CW-415 Apply requested Changes * CW-415 Ensure opening of UnspentCoinsInfo Box, even for Monero.com --------- Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>
This commit is contained in:
co-authored by
Konstantin Ullrich
parent
3577730de8
commit
f6670c0236
@@ -128,7 +128,8 @@ class CWBitcoin extends Bitcoin {
|
||||
bitcoinUnspent.address.address,
|
||||
bitcoinUnspent.hash,
|
||||
bitcoinUnspent.value,
|
||||
bitcoinUnspent.vout))
|
||||
bitcoinUnspent.vout,
|
||||
null))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -160,4 +161,4 @@ class CWBitcoin extends Bitcoin {
|
||||
@override
|
||||
TransactionPriority getLitecoinTransactionPrioritySlow()
|
||||
=> LitecoinTransactionPriority.slow;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -216,10 +216,10 @@ late Box<Template> _templates;
|
||||
late Box<ExchangeTemplate> _exchangeTemplates;
|
||||
late Box<TransactionDescription> _transactionDescriptionBox;
|
||||
late Box<Order> _ordersSource;
|
||||
late Box<UnspentCoinsInfo>? _unspentCoinsInfoSource;
|
||||
late Box<UnspentCoinsInfo> _unspentCoinsInfoSource;
|
||||
late Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource;
|
||||
|
||||
Future setup({
|
||||
Future<void> setup({
|
||||
required Box<WalletInfo> walletInfoSource,
|
||||
required Box<Node> nodeSource,
|
||||
required Box<Contact> contactSource,
|
||||
@@ -228,7 +228,7 @@ Future setup({
|
||||
required Box<ExchangeTemplate> exchangeTemplates,
|
||||
required Box<TransactionDescription> transactionDescriptionBox,
|
||||
required Box<Order> ordersSource,
|
||||
Box<UnspentCoinsInfo>? unspentCoinsInfoSource,
|
||||
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
|
||||
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource,
|
||||
}) async {
|
||||
_walletInfoSource = walletInfoSource;
|
||||
@@ -731,11 +731,11 @@ Future setup({
|
||||
case WalletType.haven:
|
||||
return haven!.createHavenWalletService(_walletInfoSource);
|
||||
case WalletType.monero:
|
||||
return monero!.createMoneroWalletService(_walletInfoSource);
|
||||
return monero!.createMoneroWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
case WalletType.bitcoin:
|
||||
return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!);
|
||||
return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!);
|
||||
return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumWalletService(_walletInfoSource);
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
class Unspent {
|
||||
Unspent(this.address, this.hash, this.value, this.vout, this.keyImage)
|
||||
: isSending = true,
|
||||
isFrozen = false,
|
||||
note = '';
|
||||
|
||||
final String address;
|
||||
final String hash;
|
||||
final int value;
|
||||
final int vout;
|
||||
final String? keyImage;
|
||||
|
||||
bool isSending;
|
||||
bool isFrozen;
|
||||
String note;
|
||||
|
||||
bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc');
|
||||
}
|
||||
+2
-6
@@ -133,11 +133,7 @@ Future<void> initializeAppConfigs() async {
|
||||
final templates = await CakeHive.openBox<Template>(Template.boxName);
|
||||
final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||
final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
|
||||
Box<UnspentCoinsInfo>? unspentCoinsInfoSource;
|
||||
|
||||
if (!isMoneroOnly) {
|
||||
unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
|
||||
}
|
||||
final unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
|
||||
|
||||
await initialSetup(
|
||||
sharedPreferences: await SharedPreferences.getInstance(),
|
||||
@@ -169,7 +165,7 @@ Future<void> initialSetup(
|
||||
required Box<TransactionDescription> transactionDescriptions,
|
||||
required FlutterSecureStorage secureStorage,
|
||||
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo,
|
||||
Box<UnspentCoinsInfo>? unspentCoinsInfoSource,
|
||||
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
|
||||
int initialMigrationVersion = 15}) async {
|
||||
LanguageService.loadLocaleList();
|
||||
await defaultSettingsMigration(
|
||||
|
||||
+272
-270
@@ -1,361 +1,363 @@
|
||||
part of 'monero.dart';
|
||||
|
||||
class CWMoneroAccountList extends MoneroAccountList {
|
||||
CWMoneroAccountList(this._wallet);
|
||||
final Object _wallet;
|
||||
CWMoneroAccountList(this._wallet);
|
||||
|
||||
@override
|
||||
@computed
|
||||
final Object _wallet;
|
||||
|
||||
@override
|
||||
@computed
|
||||
ObservableList<Account> get accounts {
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final accounts = moneroWallet.walletAddresses.accountList
|
||||
.accounts
|
||||
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
|
||||
.toList();
|
||||
return ObservableList<Account>.of(accounts);
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final accounts = moneroWallet.walletAddresses.accountList.accounts
|
||||
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
|
||||
.toList();
|
||||
return ObservableList<Account>.of(accounts);
|
||||
}
|
||||
|
||||
@override
|
||||
void update(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.accountList.update();
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.accountList.update();
|
||||
}
|
||||
|
||||
@override
|
||||
void refresh(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.accountList.refresh();
|
||||
}
|
||||
void refresh(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.accountList.refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
@override
|
||||
List<Account> getAll(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.walletAddresses.accountList
|
||||
.getAll()
|
||||
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
|
||||
.toList();
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.walletAddresses.accountList
|
||||
.getAll()
|
||||
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addAccount(Object wallet, {required String label}) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.accountList.addAccount(label: label);
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.accountList.addAccount(label: label);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label}) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.accountList
|
||||
.setLabelAccount(
|
||||
accountIndex: accountIndex,
|
||||
label: label);
|
||||
Future<void> setLabelAccount(Object wallet,
|
||||
{required int accountIndex, required String label}) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.accountList
|
||||
.setLabelAccount(accountIndex: accountIndex, label: label);
|
||||
}
|
||||
}
|
||||
|
||||
class CWMoneroSubaddressList extends MoneroSubaddressList {
|
||||
CWMoneroSubaddressList(this._wallet);
|
||||
final Object _wallet;
|
||||
CWMoneroSubaddressList(this._wallet);
|
||||
|
||||
@override
|
||||
@computed
|
||||
final Object _wallet;
|
||||
|
||||
@override
|
||||
@computed
|
||||
ObservableList<Subaddress> get subaddresses {
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final subAddresses = moneroWallet.walletAddresses.subaddressList
|
||||
.subaddresses
|
||||
.map((sub) => Subaddress(
|
||||
id: sub.id,
|
||||
address: sub.address,
|
||||
label: sub.label))
|
||||
.toList();
|
||||
return ObservableList<Subaddress>.of(subAddresses);
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final subAddresses = moneroWallet.walletAddresses.subaddressList.subaddresses
|
||||
.map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label))
|
||||
.toList();
|
||||
return ObservableList<Subaddress>.of(subAddresses);
|
||||
}
|
||||
|
||||
@override
|
||||
void update(Object wallet, {required int accountIndex}) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
void refresh(Object wallet, {required int accountIndex}) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Subaddress> getAll(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.walletAddresses
|
||||
.subaddressList
|
||||
.getAll()
|
||||
.map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
|
||||
.toList();
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.walletAddresses.subaddressList
|
||||
.getAll()
|
||||
.map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addSubaddress(Object wallet, {required int accountIndex, required String label}) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.subaddressList
|
||||
.addSubaddress(
|
||||
accountIndex: accountIndex,
|
||||
label: label);
|
||||
Future<void> addSubaddress(Object wallet,
|
||||
{required int accountIndex, required String label}) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.subaddressList
|
||||
.addSubaddress(accountIndex: accountIndex, label: label);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setLabelSubaddress(Object wallet,
|
||||
{required int accountIndex, required int addressIndex, required String label}) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.subaddressList
|
||||
.setLabelSubaddress(
|
||||
accountIndex: accountIndex,
|
||||
addressIndex: addressIndex,
|
||||
label: label);
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.walletAddresses.subaddressList
|
||||
.setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
||||
}
|
||||
}
|
||||
|
||||
class CWMoneroWalletDetails extends MoneroWalletDetails {
|
||||
CWMoneroWalletDetails(this._wallet);
|
||||
final Object _wallet;
|
||||
CWMoneroWalletDetails(this._wallet);
|
||||
|
||||
@computed
|
||||
final Object _wallet;
|
||||
|
||||
@computed
|
||||
@override
|
||||
Account get account {
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final acc = moneroWallet.walletAddresses.account;
|
||||
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final acc = moneroWallet.walletAddresses.account;
|
||||
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
|
||||
}
|
||||
|
||||
@computed
|
||||
@override
|
||||
MoneroBalance get balance {
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final balance = moneroWallet.balance;
|
||||
MoneroBalance get balance {
|
||||
final moneroWallet = _wallet as MoneroWallet;
|
||||
final balance = moneroWallet.balance;
|
||||
throw Exception('Unimplemented');
|
||||
// return MoneroBalance();
|
||||
//return MoneroBalance(
|
||||
// fullBalance: balance.fullBalance,
|
||||
// unlockedBalance: balance.unlockedBalance);
|
||||
}
|
||||
// return MoneroBalance();
|
||||
//return MoneroBalance(
|
||||
// fullBalance: balance.fullBalance,
|
||||
// unlockedBalance: balance.unlockedBalance);
|
||||
}
|
||||
}
|
||||
|
||||
class CWMonero extends Monero {
|
||||
@override
|
||||
MoneroAccountList getAccountList(Object wallet) {
|
||||
return CWMoneroAccountList(wallet);
|
||||
}
|
||||
|
||||
@override
|
||||
MoneroSubaddressList getSubaddressList(Object wallet) {
|
||||
return CWMoneroSubaddressList(wallet);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionHistoryBase getTransactionHistory(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.transactionHistory;
|
||||
}
|
||||
|
||||
@override
|
||||
MoneroWalletDetails getMoneroWalletDetails(Object wallet) {
|
||||
return CWMoneroWalletDetails(wallet);
|
||||
}
|
||||
|
||||
@override
|
||||
int getHeigthByDate({required DateTime date}) {
|
||||
return getMoneroHeigthByDate(date: date);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getDefaultTransactionPriority() {
|
||||
return MoneroTransactionPriority.automatic;
|
||||
}
|
||||
MoneroAccountList getAccountList(Object wallet) {
|
||||
return CWMoneroAccountList(wallet);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getMoneroTransactionPrioritySlow()
|
||||
=> MoneroTransactionPriority.slow;
|
||||
MoneroSubaddressList getSubaddressList(Object wallet) {
|
||||
return CWMoneroSubaddressList(wallet);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getMoneroTransactionPriorityAutomatic()
|
||||
=> MoneroTransactionPriority.automatic;
|
||||
TransactionHistoryBase getTransactionHistory(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.transactionHistory;
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
|
||||
return MoneroTransactionPriority.deserialize(raw: raw);
|
||||
}
|
||||
@override
|
||||
MoneroWalletDetails getMoneroWalletDetails(Object wallet) {
|
||||
return CWMoneroWalletDetails(wallet);
|
||||
}
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities() {
|
||||
return MoneroTransactionPriority.all;
|
||||
}
|
||||
@override
|
||||
int getHeigthByDate({required DateTime date}) {
|
||||
return getMoneroHeigthByDate(date: date);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> getMoneroWordList(String language) {
|
||||
switch (language.toLowerCase()) {
|
||||
case 'english':
|
||||
return EnglishMnemonics.words;
|
||||
case 'chinese (simplified)':
|
||||
return ChineseSimplifiedMnemonics.words;
|
||||
case 'dutch':
|
||||
return DutchMnemonics.words;
|
||||
case 'german':
|
||||
return GermanMnemonics.words;
|
||||
case 'japanese':
|
||||
return JapaneseMnemonics.words;
|
||||
case 'portuguese':
|
||||
return PortugueseMnemonics.words;
|
||||
case 'russian':
|
||||
return RussianMnemonics.words;
|
||||
case 'spanish':
|
||||
return SpanishMnemonics.words;
|
||||
case 'french':
|
||||
return FrenchMnemonics.words;
|
||||
case 'italian':
|
||||
return ItalianMnemonics.words;
|
||||
default:
|
||||
return EnglishMnemonics.words;
|
||||
}
|
||||
}
|
||||
@override
|
||||
TransactionPriority getDefaultTransactionPriority() {
|
||||
return MoneroTransactionPriority.automatic;
|
||||
}
|
||||
|
||||
@override
|
||||
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
|
||||
required String name,
|
||||
required String spendKey,
|
||||
required String viewKey,
|
||||
required String address,
|
||||
required String password,
|
||||
required String language,
|
||||
required int height}) {
|
||||
return MoneroRestoreWalletFromKeysCredentials(
|
||||
name: name,
|
||||
spendKey: spendKey,
|
||||
viewKey: viewKey,
|
||||
address: address,
|
||||
password: password,
|
||||
language: language,
|
||||
height: height);
|
||||
}
|
||||
|
||||
@override
|
||||
WalletCredentials createMoneroRestoreWalletFromSeedCredentials({
|
||||
required String name,
|
||||
required String password,
|
||||
required int height,
|
||||
required String mnemonic}) {
|
||||
return MoneroRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
password: password,
|
||||
height: height,
|
||||
mnemonic: mnemonic);
|
||||
}
|
||||
@override
|
||||
TransactionPriority getMoneroTransactionPrioritySlow() => MoneroTransactionPriority.slow;
|
||||
|
||||
@override
|
||||
WalletCredentials createMoneroNewWalletCredentials({
|
||||
@override
|
||||
TransactionPriority getMoneroTransactionPriorityAutomatic() =>
|
||||
MoneroTransactionPriority.automatic;
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
|
||||
return MoneroTransactionPriority.deserialize(raw: raw);
|
||||
}
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities() {
|
||||
return MoneroTransactionPriority.all;
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> getMoneroWordList(String language) {
|
||||
switch (language.toLowerCase()) {
|
||||
case 'english':
|
||||
return EnglishMnemonics.words;
|
||||
case 'chinese (simplified)':
|
||||
return ChineseSimplifiedMnemonics.words;
|
||||
case 'dutch':
|
||||
return DutchMnemonics.words;
|
||||
case 'german':
|
||||
return GermanMnemonics.words;
|
||||
case 'japanese':
|
||||
return JapaneseMnemonics.words;
|
||||
case 'portuguese':
|
||||
return PortugueseMnemonics.words;
|
||||
case 'russian':
|
||||
return RussianMnemonics.words;
|
||||
case 'spanish':
|
||||
return SpanishMnemonics.words;
|
||||
case 'french':
|
||||
return FrenchMnemonics.words;
|
||||
case 'italian':
|
||||
return ItalianMnemonics.words;
|
||||
default:
|
||||
return EnglishMnemonics.words;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
WalletCredentials createMoneroRestoreWalletFromKeysCredentials(
|
||||
{required String name,
|
||||
required String spendKey,
|
||||
required String viewKey,
|
||||
required String address,
|
||||
required String password,
|
||||
required String language,
|
||||
required int height}) {
|
||||
return MoneroRestoreWalletFromKeysCredentials(
|
||||
name: name,
|
||||
spendKey: spendKey,
|
||||
viewKey: viewKey,
|
||||
address: address,
|
||||
password: password,
|
||||
language: language,
|
||||
height: height);
|
||||
}
|
||||
|
||||
@override
|
||||
WalletCredentials createMoneroRestoreWalletFromSeedCredentials(
|
||||
{required String name,
|
||||
required String password,
|
||||
required int height,
|
||||
required String mnemonic}) {
|
||||
return MoneroRestoreWalletFromSeedCredentials(
|
||||
name: name, password: password, height: height, mnemonic: mnemonic);
|
||||
}
|
||||
|
||||
@override
|
||||
WalletCredentials createMoneroNewWalletCredentials({
|
||||
required String name,
|
||||
required String language,
|
||||
String? password,}) {
|
||||
return MoneroNewWalletCredentials(
|
||||
name: name,
|
||||
password: password,
|
||||
language: language);
|
||||
}
|
||||
String? password,
|
||||
}) {
|
||||
return MoneroNewWalletCredentials(name: name, password: password, language: language);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, String> getKeys(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
final keys = moneroWallet.keys;
|
||||
return <String, String>{
|
||||
'privateSpendKey': keys.privateSpendKey,
|
||||
@override
|
||||
Map<String, String> getKeys(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
final keys = moneroWallet.keys;
|
||||
return <String, String>{
|
||||
'privateSpendKey': keys.privateSpendKey,
|
||||
'privateViewKey': keys.privateViewKey,
|
||||
'publicSpendKey': keys.publicSpendKey,
|
||||
'publicViewKey': keys.publicViewKey};
|
||||
}
|
||||
'publicViewKey': keys.publicViewKey
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Object createMoneroTransactionCreationCredentials({
|
||||
required List<Output> outputs,
|
||||
required TransactionPriority priority}) {
|
||||
return MoneroTransactionCreationCredentials(
|
||||
outputs: outputs.map((out) => OutputInfo(
|
||||
fiatAmount: out.fiatAmount,
|
||||
cryptoAmount: out.cryptoAmount,
|
||||
address: out.address,
|
||||
note: out.note,
|
||||
sendAll: out.sendAll,
|
||||
extractedAddress: out.extractedAddress,
|
||||
isParsedAddress: out.isParsedAddress,
|
||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as MoneroTransactionPriority);
|
||||
}
|
||||
@override
|
||||
Object createMoneroTransactionCreationCredentials(
|
||||
{required List<Output> outputs, required TransactionPriority priority}) {
|
||||
return MoneroTransactionCreationCredentials(
|
||||
outputs: outputs
|
||||
.map((out) => OutputInfo(
|
||||
fiatAmount: out.fiatAmount,
|
||||
cryptoAmount: out.cryptoAmount,
|
||||
address: out.address,
|
||||
note: out.note,
|
||||
sendAll: out.sendAll,
|
||||
extractedAddress: out.extractedAddress,
|
||||
isParsedAddress: out.isParsedAddress,
|
||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as MoneroTransactionPriority);
|
||||
}
|
||||
|
||||
@override
|
||||
Object createMoneroTransactionCreationCredentialsRaw({
|
||||
required List<OutputInfo> outputs,
|
||||
required TransactionPriority priority}) {
|
||||
return MoneroTransactionCreationCredentials(
|
||||
outputs: outputs,
|
||||
priority: priority as MoneroTransactionPriority);
|
||||
}
|
||||
@override
|
||||
Object createMoneroTransactionCreationCredentialsRaw(
|
||||
{required List<OutputInfo> outputs, required TransactionPriority priority}) {
|
||||
return MoneroTransactionCreationCredentials(
|
||||
outputs: outputs, priority: priority as MoneroTransactionPriority);
|
||||
}
|
||||
|
||||
@override
|
||||
String formatterMoneroAmountToString({required int amount}) {
|
||||
return moneroAmountToString(amount: amount);
|
||||
}
|
||||
@override
|
||||
String formatterMoneroAmountToString({required int amount}) {
|
||||
return moneroAmountToString(amount: amount);
|
||||
}
|
||||
|
||||
@override
|
||||
double formatterMoneroAmountToDouble({required int amount}) {
|
||||
return moneroAmountToDouble(amount: amount);
|
||||
}
|
||||
@override
|
||||
double formatterMoneroAmountToDouble({required int amount}) {
|
||||
return moneroAmountToDouble(amount: amount);
|
||||
}
|
||||
|
||||
@override
|
||||
int formatterMoneroParseAmount({required String amount}) {
|
||||
return moneroParseAmount(amount: amount);
|
||||
}
|
||||
@override
|
||||
int formatterMoneroParseAmount({required String amount}) {
|
||||
return moneroParseAmount(amount: amount);
|
||||
}
|
||||
|
||||
@override
|
||||
Account getCurrentAccount(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
final acc = moneroWallet.walletAddresses.account;
|
||||
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
|
||||
}
|
||||
@override
|
||||
Account getCurrentAccount(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
final acc = moneroWallet.walletAddresses.account;
|
||||
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
|
||||
}
|
||||
|
||||
@override
|
||||
void setCurrentAccount(Object wallet, int id, String label, String? balance) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.account = monero_account.Account(id: id, label: label, balance: balance);
|
||||
}
|
||||
@override
|
||||
void setCurrentAccount(Object wallet, int id, String label, String? balance) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.walletAddresses.account =
|
||||
monero_account.Account(id: id, label: label, balance: balance);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStartup() {
|
||||
monero_wallet_api.onStartup();
|
||||
}
|
||||
@override
|
||||
void onStartup() {
|
||||
monero_wallet_api.onStartup();
|
||||
}
|
||||
|
||||
@override
|
||||
int getTransactionInfoAccountId(TransactionInfo tx) {
|
||||
final moneroTransactionInfo = tx as MoneroTransactionInfo;
|
||||
return moneroTransactionInfo.accountIndex;
|
||||
}
|
||||
@override
|
||||
int getTransactionInfoAccountId(TransactionInfo tx) {
|
||||
final moneroTransactionInfo = tx as MoneroTransactionInfo;
|
||||
return moneroTransactionInfo.accountIndex;
|
||||
}
|
||||
|
||||
@override
|
||||
WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource) {
|
||||
return MoneroWalletService(walletInfoSource);
|
||||
}
|
||||
@override
|
||||
WalletService createMoneroWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return MoneroWalletService(walletInfoSource, unspentCoinSource);
|
||||
}
|
||||
|
||||
@override
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.getTransactionAddress(accountIndex, addressIndex);
|
||||
}
|
||||
@override
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.getTransactionAddress(accountIndex, addressIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.getSubaddressLabel(accountIndex, addressIndex);
|
||||
}
|
||||
@override
|
||||
String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.getSubaddressLabel(accountIndex, addressIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, String> pendingTransactionInfo(Object transaction) {
|
||||
final ptx = transaction as PendingMoneroTransaction;
|
||||
return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey};
|
||||
}
|
||||
@override
|
||||
Map<String, String> pendingTransactionInfo(Object transaction) {
|
||||
final ptx = transaction as PendingMoneroTransaction;
|
||||
return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey};
|
||||
}
|
||||
|
||||
@override
|
||||
List<Unspent> getUnspents(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.unspentCoins
|
||||
.map((MoneroUnspent moneroUnspent) => Unspent(moneroUnspent.address, moneroUnspent.hash,
|
||||
moneroUnspent.value, 0, moneroUnspent.keyImage))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void updateUnspents(Object wallet) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
await moneroWallet.updateUnspent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class SendPage extends BasePage {
|
||||
AppBarStyle get appBarStyle => AppBarStyle.transparent;
|
||||
|
||||
double _sendCardHeight(BuildContext context) {
|
||||
final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465;
|
||||
final double initialHeight = sendViewModel.hasCoinControl ? 490 : 465;
|
||||
|
||||
if (!ResponsiveLayoutUtil.instance.isMobile) {
|
||||
return initialHeight - 66;
|
||||
|
||||
@@ -496,7 +496,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||
),
|
||||
),
|
||||
),
|
||||
if (sendViewModel.isElectrumWallet)
|
||||
if (sendViewModel.hasCoinControl)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: GestureDetector(
|
||||
|
||||
@@ -21,7 +21,6 @@ class TransactionDetailsPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
// FIX-ME: Added `context` it was not used here before, maby bug ?
|
||||
return SectionStandardList(
|
||||
sectionCount: 1,
|
||||
itemCounter: (int _) => transactionDetailsViewModel.items.length,
|
||||
|
||||
@@ -6,11 +6,12 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
|
||||
class TextFieldListRow extends StatelessWidget {
|
||||
TextFieldListRow(
|
||||
{required this.title,
|
||||
required this.value,
|
||||
this.titleFontSize = 14,
|
||||
this.valueFontSize = 16,
|
||||
this.onSubmitted})
|
||||
: _textController = TextEditingController() {
|
||||
required this.value,
|
||||
this.titleFontSize = 14,
|
||||
this.valueFontSize = 16,
|
||||
this.onSubmitted,
|
||||
this.onTapOutside})
|
||||
: _textController = TextEditingController() {
|
||||
_textController.text = value;
|
||||
}
|
||||
|
||||
@@ -19,6 +20,7 @@ class TextFieldListRow extends StatelessWidget {
|
||||
final double titleFontSize;
|
||||
final double valueFontSize;
|
||||
final Function(String value)? onSubmitted;
|
||||
final Function(String value)? onTapOutside;
|
||||
final TextEditingController _textController;
|
||||
|
||||
@override
|
||||
@@ -58,6 +60,7 @@ class TextFieldListRow extends StatelessWidget {
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
|
||||
border: InputBorder.none),
|
||||
onTapOutside: (_) => onTapOutside?.call(_textController.text),
|
||||
onSubmitted: (value) => onSubmitted?.call(value),
|
||||
)
|
||||
]),
|
||||
|
||||
@@ -24,7 +24,6 @@ class UnspentCoinsDetailsPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
// FIX-ME: Added `context` it was not used here before, maby bug ?
|
||||
return SectionStandardList(
|
||||
sectionCount: 1,
|
||||
itemCounter: (int _) => unspentCoinsDetailsViewModel.items.length,
|
||||
@@ -45,6 +44,7 @@ class UnspentCoinsDetailsPage extends BasePage {
|
||||
return TextFieldListRow(
|
||||
title: item.title,
|
||||
value: item.value,
|
||||
onTapOutside: item.onSubmitted,
|
||||
onSubmitted: item.onSubmitted,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class UnspentCoinsListItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
AutoSizeText(
|
||||
address,
|
||||
'${address.substring(0, 5)}...${address.substring(address.length-5)}', // ToDo: Maybe use address label
|
||||
style: TextStyle(
|
||||
color: addressColor,
|
||||
fontSize: 12,
|
||||
|
||||
@@ -172,6 +172,10 @@ abstract class SendViewModelBase with Store {
|
||||
.where((template) => _isEqualCurrency(template.cryptoCurrency))
|
||||
.toList();
|
||||
|
||||
@computed
|
||||
bool get hasCoinControl =>
|
||||
_wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin || _wallet.type == WalletType.monero;
|
||||
|
||||
@computed
|
||||
bool get isElectrumWallet =>
|
||||
_wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin;
|
||||
@@ -206,12 +210,12 @@ abstract class SendViewModelBase with Store {
|
||||
|
||||
@computed
|
||||
List<ContactRecord> get contactsToShow => contactListViewModel.contacts
|
||||
.where((element) => selectedCryptoCurrency == null || element.type == selectedCryptoCurrency)
|
||||
.where((element) => element.type == selectedCryptoCurrency)
|
||||
.toList();
|
||||
|
||||
@computed
|
||||
List<WalletContact> get walletContactsToShow => contactListViewModel.walletContacts
|
||||
.where((element) => selectedCryptoCurrency == null || element.type == selectedCryptoCurrency)
|
||||
.where((element) => element.type == selectedCryptoCurrency)
|
||||
.toList();
|
||||
|
||||
@action
|
||||
|
||||
@@ -23,6 +23,7 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
|
||||
note = unspentCoinsItem.note {
|
||||
items = [
|
||||
StandartListItem(title: S.current.transaction_details_amount, value: unspentCoinsItem.amount),
|
||||
StandartListItem(title: S.current.transaction_details_transaction_id, value: unspentCoinsItem.hash),
|
||||
StandartListItem(title: S.current.widgets_address, value: unspentCoinsItem.address),
|
||||
TextFieldListItem(
|
||||
title: S.current.note_tap_to_change,
|
||||
@@ -42,19 +43,22 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
|
||||
unspentCoinsItem.isSending = !value;
|
||||
}
|
||||
await unspentCoinsListViewModel.saveUnspentCoinInfo(unspentCoinsItem);
|
||||
}),
|
||||
BlockExplorerListItem(
|
||||
title: S.current.view_in_block_explorer,
|
||||
value: _explorerDescription(unspentCoinsListViewModel.wallet.type),
|
||||
onTap: () {
|
||||
try {
|
||||
final url = Uri.parse(
|
||||
_explorerUrl(unspentCoinsListViewModel.wallet.type, unspentCoinsItem.hash));
|
||||
return launchUrl(url);
|
||||
} catch (e) {}
|
||||
|
||||
})
|
||||
];
|
||||
|
||||
if ([WalletType.bitcoin, WalletType.litecoin].contains(unspentCoinsListViewModel.wallet.type)) {
|
||||
items.add(BlockExplorerListItem(
|
||||
title: S.current.view_in_block_explorer,
|
||||
value: _explorerDescription(unspentCoinsListViewModel.wallet.type),
|
||||
onTap: () {
|
||||
try {
|
||||
final url = Uri.parse(
|
||||
_explorerUrl(unspentCoinsListViewModel.wallet.type, unspentCoinsItem.hash));
|
||||
return launchUrl(url);
|
||||
} catch (e) {}
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
String _explorerUrl(WalletType type, String txId) {
|
||||
|
||||
@@ -13,7 +13,9 @@ abstract class UnspentCoinsItemBase with Store {
|
||||
required this.note,
|
||||
required this.isSending,
|
||||
required this.amountRaw,
|
||||
required this.vout});
|
||||
required this.vout,
|
||||
required this.keyImage
|
||||
});
|
||||
|
||||
@observable
|
||||
String address;
|
||||
@@ -38,4 +40,7 @@ abstract class UnspentCoinsItemBase with Store {
|
||||
|
||||
@observable
|
||||
int vout;
|
||||
}
|
||||
|
||||
@observable
|
||||
String? keyImage;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cake_wallet/entities/unspent_transaction_output.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_monero/monero_wallet.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
part 'unspent_coins_list_view_model.g.dart';
|
||||
|
||||
@@ -14,7 +19,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
||||
UnspentCoinsListViewModelBase(
|
||||
{required this.wallet, required Box<UnspentCoinsInfo> unspentCoinsInfo})
|
||||
: _unspentCoinsInfo = unspentCoinsInfo {
|
||||
bitcoin!.updateUnspents(wallet);
|
||||
_updateUnspents();
|
||||
}
|
||||
|
||||
WalletBase wallet;
|
||||
@@ -22,11 +27,10 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
||||
|
||||
@computed
|
||||
ObservableList<UnspentCoinsItem> get items =>
|
||||
ObservableList.of(bitcoin!.getUnspents(wallet).map((elem) {
|
||||
final amount = bitcoin!.formatterBitcoinAmountToString(amount: elem.value) +
|
||||
' ${wallet.currency.title}';
|
||||
ObservableList.of(_getUnspents().map((elem) {
|
||||
final amount = formatAmountToString(elem.value) + ' ${wallet.currency.title}';
|
||||
|
||||
final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout);
|
||||
final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage);
|
||||
|
||||
return UnspentCoinsItem(
|
||||
address: elem.address,
|
||||
@@ -36,12 +40,14 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
||||
note: info?.note ?? '',
|
||||
isSending: info?.isSending ?? true,
|
||||
amountRaw: elem.value,
|
||||
vout: elem.vout);
|
||||
vout: elem.vout,
|
||||
keyImage: elem.keyImage
|
||||
);
|
||||
}));
|
||||
|
||||
Future<void> saveUnspentCoinInfo(UnspentCoinsItem item) async {
|
||||
try {
|
||||
final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout);
|
||||
final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage);
|
||||
if (info == null) {
|
||||
final newInfo = UnspentCoinsInfo(
|
||||
walletId: wallet.id,
|
||||
@@ -51,10 +57,12 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
||||
vout: item.vout,
|
||||
isFrozen: item.isFrozen,
|
||||
isSending: item.isSending,
|
||||
noteRaw: item.note);
|
||||
noteRaw: item.note,
|
||||
keyImage: item.keyImage
|
||||
);
|
||||
|
||||
await _unspentCoinsInfo.add(newInfo);
|
||||
bitcoin!.updateUnspents(wallet);
|
||||
_updateUnspents();
|
||||
wallet.updateBalance();
|
||||
return;
|
||||
}
|
||||
@@ -63,19 +71,45 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
||||
info.note = item.note;
|
||||
|
||||
await info.save();
|
||||
bitcoin!.updateUnspents(wallet);
|
||||
_updateUnspents();
|
||||
wallet.updateBalance();
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
UnspentCoinsInfo? getUnspentCoinInfo(String hash, String address, int value, int vout) {
|
||||
UnspentCoinsInfo? getUnspentCoinInfo(String hash, String address, int value, int vout, String? keyImage) {
|
||||
return _unspentCoinsInfo.values.firstWhereOrNull((element) =>
|
||||
element.walletId == wallet.id &&
|
||||
element.hash == hash &&
|
||||
element.address == address &&
|
||||
element.value == value &&
|
||||
element.vout == vout);
|
||||
element.vout == vout &&
|
||||
element.keyImage == keyImage
|
||||
);
|
||||
}
|
||||
|
||||
String formatAmountToString(int fullBalance) {
|
||||
if (wallet.type == WalletType.monero)
|
||||
return monero!.formatterMoneroAmountToString(amount: fullBalance);
|
||||
if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type))
|
||||
return bitcoin!.formatterBitcoinAmountToString(amount: fullBalance);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
void _updateUnspents() {
|
||||
if (wallet.type == WalletType.monero)
|
||||
return monero!.updateUnspents(wallet);
|
||||
if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type))
|
||||
return bitcoin!.updateUnspents(wallet);
|
||||
}
|
||||
|
||||
List<Unspent> _getUnspents() {
|
||||
if (wallet.type == WalletType.monero)
|
||||
return monero!.getUnspents(wallet);
|
||||
if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type))
|
||||
return bitcoin!.getUnspents(wallet);
|
||||
return List.empty();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user